summaryrefslogtreecommitdiff
path: root/pacman/model/src/main/java
diff options
context:
space:
mode:
authormithe24 <mithe24@student.sdu.dk>2025-04-08 11:23:56 +0200
committermithe24 <mithe24@student.sdu.dk>2025-04-29 18:51:23 +0200
commite8e3774158f749e0214fb34ebdba29527d054874 (patch)
tree754fe56d1d421d065b3f1b22219e7b09faf0bc91 /pacman/model/src/main/java
parent6687af6f7c7d5d4524fadad1129d50040293e05c (diff)
downloadpacman-e8e3774158f749e0214fb34ebdba29527d054874.tar.gz
pacman-e8e3774158f749e0214fb34ebdba29527d054874.zip
Initial commit
Diffstat (limited to '')
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/Board.java49
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/GameState.java85
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java36
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/Position.java38
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/entities/Entity.java36
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/entities/EntityUtils.java31
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/entities/Ghost.java19
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/entities/Items.java3
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/entities/Pacman.java145
-rw-r--r--pacman/model/src/main/java/module-info.java9
10 files changed, 447 insertions, 4 deletions
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/Board.java b/pacman/model/src/main/java/com/gr15/pacman/model/Board.java
new file mode 100644
index 0000000..41595c4
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/Board.java
@@ -0,0 +1,49 @@
+package com.gr15.pacman.model;
+
+/**
+ * Board
+ */
+public class Board {
+
+ private TileType[][] tileBoard;
+ private int height;
+ private int width;
+
+ public enum TileType { WALL, EMPTY };
+ public enum Direction { UP, DOWN, LEFT, RIGHT, NONE };
+
+ public Board(int height, int width) {
+ this.width = width;
+ this.height = height;
+ }
+
+ public Board(int height, int width, TileType[][] tileBoard) {
+ this(height, width);
+ this.tileBoard = tileBoard;
+ }
+
+ public boolean isMovable(Position pos) {
+ if (!pos.inBounds(width, height)) {
+ return false;
+ } else {
+ return tileBoard[pos.y()][pos.x()] != TileType.WALL;
+ }
+ }
+
+
+ /* Getters and setters */
+ public TileType[][] getTileBoard() { return this.tileBoard; }
+ public TileType getTile(int x, int y) { return tileBoard[y][x]; }
+ public int getHeight() { return this.height; }
+ public int getWidth() { return this.width; }
+
+ public void setHeight(int newHeight) { this.height = newHeight; }
+ public void setWidth(int newWidth) { this.width = newWidth; }
+ public void setTile(int x, int y, TileType newTile) {
+ this.tileBoard[y][x] = newTile;
+ }
+ public void setTileBoard(TileType[][] newBoard) {
+ this.tileBoard = newBoard;
+ }
+
+}
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/GameState.java b/pacman/model/src/main/java/com/gr15/pacman/model/GameState.java
new file mode 100644
index 0000000..ef33488
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/GameState.java
@@ -0,0 +1,85 @@
+package com.gr15.pacman.model;
+
+import java.util.Map;
+
+import com.gr15.pacman.model.entities.Entity;
+import com.gr15.pacman.model.entities.EntityUtils;
+import com.gr15.pacman.model.entities.Items;
+import com.gr15.pacman.model.entities.Pacman;
+
+/**
+ * GameState
+ */
+public class GameState {
+
+ private Board board;
+
+ private Pacman pacman;
+ private Map<Position, Entity> entities;
+ private Map<Position, Items> items;
+
+ private int score = 0;
+ private int lives = 3;
+ private double powerModeDuration = 0;
+
+ public GameState(Board board, Pacman pacman,
+ Map<Position, Entity> entities, Map<Position, Items> items) {
+ this.board = board;
+ this.entities = entities;
+ this.items = items;
+ this.pacman = pacman;
+ }
+
+ public void update(double deltaSeconds) {
+ if (lives == 0) {
+ /* Gameover */
+ }
+
+ pacman.move(board, deltaSeconds);
+
+ /* Power mode */
+ powerModeDuration -= deltaSeconds;
+ powerModeDuration = Math.max(powerModeDuration, 0);
+
+ /* updating and checking collisions with entities */
+ entities.forEach((pos, entity) -> {
+ entity.move(board, deltaSeconds);
+ if (EntityUtils.hasCollided(pacman, entity)
+ && powerModeDuration == 0) {
+ lives -= 1;
+ } else if (EntityUtils.hasCollided(pacman, entity)) {
+ score += 100;
+ }
+ });
+
+ /* checking collisions with items */
+ Items item = items.get(pacman.getPosition());
+ if (item != null) {
+ switch (item) {
+ case PELLET -> score++;
+ case POWER_PELLET -> powerModeDuration = 10.0;
+ default -> {}
+ }
+ }
+ }
+
+ /* Getters and setters */
+ public Board getBoard() { return this.board; }
+ public Pacman getPacman() { return this.pacman; }
+ public Map<Position, Entity> getEntities() { return this.entities; }
+ public Map<Position, Items> getItems() { return this.items; }
+ public int getScore() { return this.score; }
+ public int getLives() { return this.lives; }
+
+ public void setBoard(Board newBoard) { this.board = newBoard; }
+ public void setPacman(Pacman newPacman) { this.pacman = newPacman; }
+ public void setScore(int newScore) { this.score = newScore; }
+ public void setLives(int newLives) { this.lives = newLives; }
+
+ public void setItems(Map<Position, Items> newItems) {
+ this.items = newItems;
+ }
+ public void setEntities(Map<Position, Entity> newEntities) {
+ this.entities = newEntities;
+ }
+}
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java b/pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java
new file mode 100644
index 0000000..728fbd2
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java
@@ -0,0 +1,36 @@
+package com.gr15.pacman.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.gr15.pacman.model.Board.Direction;
+import com.gr15.pacman.model.Board.TileType;
+import com.gr15.pacman.model.entities.Entity;
+import com.gr15.pacman.model.entities.Pacman;
+import com.gr15.pacman.model.entities.Items;
+
+/**
+ * jsonParser
+ */
+public final class JsonParser {
+
+ public static GameState getGameState(String path) {
+ TileType[][] tileBoard = {
+ {TileType.WALL, TileType.WALL, TileType.WALL, TileType.WALL, TileType.WALL,},
+ {TileType.WALL, TileType.EMPTY, TileType.EMPTY, TileType.EMPTY, TileType.WALL,},
+ {TileType.WALL, TileType.EMPTY, TileType.WALL, TileType.EMPTY, TileType.WALL,},
+ {TileType.WALL, TileType.EMPTY, TileType.WALL, TileType.EMPTY, TileType.WALL,},
+ {TileType.WALL, TileType.EMPTY, TileType.EMPTY, TileType.EMPTY, TileType.WALL,},
+ {TileType.WALL, TileType.EMPTY, TileType.WALL, TileType.EMPTY, TileType.WALL,},
+ {TileType.WALL, TileType.EMPTY, TileType.EMPTY, TileType.EMPTY, TileType.WALL,},
+ {TileType.WALL, TileType.WALL, TileType.WALL, TileType.WALL, TileType.WALL,},
+ };
+ Board board = new Board(8, 5, tileBoard);
+ Pacman pacman = new Pacman(new Position(1, 1), 3.0, Direction.NONE, 1);
+ Map<Position, Entity> entities = new HashMap<>();
+ Map<Position, Items> items = new HashMap<>();
+
+ return new GameState(board, pacman, entities, items);
+ }
+
+}
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/Position.java b/pacman/model/src/main/java/com/gr15/pacman/model/Position.java
new file mode 100644
index 0000000..c492628
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/Position.java
@@ -0,0 +1,38 @@
+package com.gr15.pacman.model;
+
+import java.util.List;
+
+import com.gr15.pacman.model.Board.Direction;
+
+/**
+ * Position
+ */
+public record Position(int x, int y) {
+
+ public Position offset(Direction dir) {
+ return switch(dir) {
+ case UP -> new Position(x, y-1);
+ case DOWN -> new Position(x, y+1);
+ case LEFT -> new Position(x-1, y);
+ case RIGHT -> new Position(x+1, y);
+ default -> this;
+ };
+ }
+
+ public double distance(Position other) {
+ return Math.hypot(other.x - x, other.y - y);
+ }
+
+ public boolean inBounds(int width, int height) {
+ return x >= 0 && y >= 0 && x < width && y < height;
+ }
+
+ public List<Position> neighbors() {
+ return List.of(
+ new Position(x, y+1),
+ new Position(x, y-1),
+ new Position(x-1, y),
+ new Position(x+1, y)
+ );
+ }
+}
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/entities/Entity.java b/pacman/model/src/main/java/com/gr15/pacman/model/entities/Entity.java
new file mode 100644
index 0000000..395a170
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/entities/Entity.java
@@ -0,0 +1,36 @@
+package com.gr15.pacman.model.entities;
+
+import com.gr15.pacman.model.Board;
+import com.gr15.pacman.model.Position;
+
+/**
+ * Entity
+ */
+public abstract class Entity {
+
+ private Position position;
+ private float subTileX = 0.0f;
+ private float subTileY = 0.0f;
+
+ private double radius;
+
+ public Entity(Position startPos, double radius) {
+ this.radius = radius;
+ this.position = startPos;
+ }
+
+ public abstract void move(Board board, double deltaSeconds);
+
+ /* Getters and setters */
+ public Position getPosition() { return this.position; }
+ public float getSubTileX() { return this.subTileX; }
+ public float getSubTileY() { return this.subTileY; }
+ public double getRadius() { return this.radius; }
+ public double getPositionX() { return position.x() + subTileX; }
+ public double getPositionY() { return position.y() + subTileY; }
+
+ public void setPosition(Position newPos) { this.position = newPos; }
+ public void setSubTileX(float newX) { this.subTileX = newX; }
+ public void setSubTileY(float newY) { this.subTileY = newY; }
+ public void setRadius(double newRad) { this.radius = newRad; }
+}
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/entities/EntityUtils.java b/pacman/model/src/main/java/com/gr15/pacman/model/entities/EntityUtils.java
new file mode 100644
index 0000000..fd52acb
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/entities/EntityUtils.java
@@ -0,0 +1,31 @@
+package com.gr15.pacman.model.entities;
+
+/**
+ * Util
+ */
+public final class EntityUtils {
+
+
+ public static double distance(Entity arg0, Entity arg1) {
+ double arg0X = arg0.getPosition().x() + arg0.getSubTileX();
+ double arg0Y = arg0.getPosition().y() + arg0.getSubTileY();
+ double arg1X = arg1.getPosition().x() + arg1.getSubTileX();
+ double arg1Y = arg1.getPosition().y() + arg1.getSubTileY();
+
+ return Math.hypot(arg0X - arg1X, arg0Y - arg1Y);
+ }
+
+ public static boolean hasCollided(Entity arg0, Entity arg1) {
+ double arg0X = arg0.getPosition().x() + arg0.getSubTileX();
+ double arg0Y = arg0.getPosition().y() + arg0.getSubTileY();
+ double arg1X = arg1.getPosition().x() + arg1.getSubTileX();
+ double arg1Y = arg1.getPosition().y() + arg1.getSubTileY();
+
+ double dx = arg0X - arg1X;
+ double dy = arg0Y - arg1Y;
+ double distanceSquared = dx * dx + dy * dy;
+ double combinedRadius = arg0.getRadius() + arg1.getRadius();
+
+ return distanceSquared <= combinedRadius * combinedRadius;
+ }
+}
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/entities/Ghost.java b/pacman/model/src/main/java/com/gr15/pacman/model/entities/Ghost.java
new file mode 100644
index 0000000..7ba795f
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/entities/Ghost.java
@@ -0,0 +1,19 @@
+package com.gr15.pacman.model.entities;
+
+import com.gr15.pacman.model.Board;
+import com.gr15.pacman.model.Position;
+
+/**
+ * Ghost
+ */
+public class Ghost
+ extends Entity{
+
+ public Ghost(Position startPos, double radius) {
+ super(startPos, radius);
+ }
+ @Override
+ public void move(Board board, double deltaSeconds) {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/entities/Items.java b/pacman/model/src/main/java/com/gr15/pacman/model/entities/Items.java
new file mode 100644
index 0000000..3b09a54
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/entities/Items.java
@@ -0,0 +1,3 @@
+package com.gr15.pacman.model.entities;
+
+public enum Items { PELLET, POWER_PELLET };
diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/entities/Pacman.java b/pacman/model/src/main/java/com/gr15/pacman/model/entities/Pacman.java
new file mode 100644
index 0000000..5d9cf22
--- /dev/null
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/entities/Pacman.java
@@ -0,0 +1,145 @@
+package com.gr15.pacman.model.entities;
+
+import com.gr15.pacman.model.Board;
+import com.gr15.pacman.model.Position;
+import com.gr15.pacman.model.Board.Direction;
+
+/**
+ * Pacman
+ */
+public class Pacman
+ extends Entity {
+
+ /* Tiles per second */
+ private double speed;
+ private Direction currentDirection = Direction.NONE;
+ private Direction nextDirection;
+
+ public Pacman(Position startPos, double speed, Direction startDir, double radius) {
+ super(startPos, radius);
+ this.speed = speed;
+ this.nextDirection = startDir;
+ }
+
+ @Override
+ public void move(Board board, double deltaSeconds) {
+ float subTileX = super.getSubTileX();
+ float subTileY = super.getSubTileY();
+ double distanceToMove = speed * deltaSeconds;
+
+ Position currentPos = super.getPosition();
+ boolean canMoveNext = nextDirection != Direction.NONE
+ && board.isMovable(currentPos.offset(nextDirection));
+ boolean canContinue = currentDirection != Direction.NONE
+ && board.isMovable(currentPos.offset(currentDirection));
+
+ Direction direction = canMoveNext ? nextDirection
+ : (canContinue ? currentDirection : Direction.NONE);
+
+ if (direction == Direction.NONE) {
+ /* Snap to center if not moving */
+ double centerX = 0.5;
+ double centerY = 0.5;
+ double distToCenterX = Math.abs(subTileX - centerX);
+ double distToCenterY = Math.abs(subTileY - centerY);
+
+ if (distToCenterX < distanceToMove) {
+ subTileX = (float)centerX;
+ } else {
+ subTileX += (subTileX < centerX ? 1 : -1) * distanceToMove;
+ }
+
+ if (distToCenterY < distanceToMove) {
+ subTileY = (float)centerY;
+ } else {
+ subTileY += (subTileY < centerY ? 1 : -1) * distanceToMove;
+ }
+
+ super.setSubTileX(subTileX);
+ super.setSubTileY(subTileY);
+ return;
+ }
+
+ boolean verticalMove = direction == Direction.UP
+ || direction == Direction.DOWN;
+ int directionSign = (direction == Direction.UP
+ || direction == Direction.LEFT) ? -1 : 1;
+
+ /* Determine primary and secondary sub-tile axes */
+ double subTilePrimary = verticalMove ? subTileY : subTileX;
+ double subTileSecondary = verticalMove ? subTileX : subTileY;
+ double center = Math.floor(subTileSecondary) + 0.5;
+ double distanceToCenter = Math.abs(subTileSecondary - center);
+
+ /* First, move to center if needed */
+ if (distanceToCenter > 0.01) {
+ double moveToCenter = Math.min(distanceToMove, distanceToCenter);
+ if (subTileSecondary < center) {
+ subTileSecondary += moveToCenter;
+ } else {
+ subTileSecondary -= moveToCenter;
+ }
+ distanceToMove -= moveToCenter;
+ }
+
+ /* Apply secondary axis back */
+ if (verticalMove) {
+ subTileX = (float)subTileSecondary;
+ } else {
+ subTileY = (float)subTileSecondary;
+ }
+
+ /* Now, attempt to move along primary axis */
+ while (distanceToMove > 0.0001) {
+ double maxStep = directionSign > 0 ? 1.0 - subTilePrimary
+ : subTilePrimary;
+ double step = Math.min(distanceToMove, maxStep);
+ double newSubTilePrimary = subTilePrimary + directionSign * step;
+
+
+ if ((direction == Direction.RIGHT && newSubTilePrimary >= 1.0)
+ || (direction == Direction.LEFT && newSubTilePrimary <= 0.0)
+ || (direction == Direction.DOWN && newSubTilePrimary >= 1.0)
+ || (direction == Direction.UP && newSubTilePrimary <= 0.0)) {
+
+ Position newPos = currentPos.offset(direction);
+ if (board.isMovable(newPos)) {
+ currentPos = newPos;
+ subTilePrimary = directionSign > 0 ? 0.0 : 1.0;
+ } else {
+ currentDirection = Direction.NONE;
+ subTilePrimary = directionSign > 0 ? 1.0 : 0.0;
+ break;
+ }
+ } else {
+ subTilePrimary = newSubTilePrimary;
+ }
+
+ distanceToMove -= step;
+ }
+
+ /* Assign back primary axis */
+ if (verticalMove) {
+ subTileY = (float)subTilePrimary;
+ } else {
+ subTileX = (float)subTilePrimary;
+ }
+
+ /* Update direction state */
+ if (canMoveNext) {
+ currentDirection = nextDirection;
+ nextDirection = Direction.NONE;
+ }
+
+ /* Update final state */
+ super.setSubTileX(subTileX);
+ super.setSubTileY(subTileY);
+ super.setPosition(currentPos);
+ }
+
+ /* Getters and setters */
+ public double getSpeed() { return this.speed; }
+ public Direction getDirection() { return this.currentDirection; }
+ public void setSpeed(double newSpeed) { this.speed = newSpeed; }
+ public void setDirection(Direction newDir) { this.nextDirection = newDir; }
+}
diff --git a/pacman/model/src/main/java/module-info.java b/pacman/model/src/main/java/module-info.java
index b8cd128..95d9324 100644
--- a/pacman/model/src/main/java/module-info.java
+++ b/pacman/model/src/main/java/module-info.java
@@ -1,7 +1,8 @@
/* module-info.java
* This acts as the manifest for the module.
*/
-module pacman.model {
- requires javafx.controls; /* Declares a dependency on another module */
- exports pacman.model; /* exports make specific packages */
-} /* public to other modules */
+module com.gr15.pacman.model {
+ requires transitive javafx.controls;
+ exports com.gr15.pacman.model;
+ exports com.gr15.pacman.model.entities;
+}