summaryrefslogtreecommitdiff
path: root/pacman
diff options
context:
space:
mode:
Diffstat (limited to 'pacman')
-rw-r--r--pacman/controller/src/main/java/com/gr15/pacman/controller/GameController.java2
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/Board.java1
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java2
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/Position.java2
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/entities/Entity.java2
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/entities/Pacman.java252
6 files changed, 185 insertions, 76 deletions
diff --git a/pacman/controller/src/main/java/com/gr15/pacman/controller/GameController.java b/pacman/controller/src/main/java/com/gr15/pacman/controller/GameController.java
index b1208be..075fa5c 100644
--- a/pacman/controller/src/main/java/com/gr15/pacman/controller/GameController.java
+++ b/pacman/controller/src/main/java/com/gr15/pacman/controller/GameController.java
@@ -1,7 +1,7 @@
package com.gr15.pacman.controller;
import com.gr15.pacman.model.GameState;
-import com.gr15.pacman.model.Board.Direction;
+import com.gr15.pacman.model.entities.Entity.Direction;
import com.gr15.pacman.view.GameView;
import javafx.animation.AnimationTimer;
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
index 41595c4..898ec3b 100644
--- a/pacman/model/src/main/java/com/gr15/pacman/model/Board.java
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/Board.java
@@ -10,7 +10,6 @@ public class Board {
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;
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
index 728fbd2..990fb15 100644
--- a/pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java
@@ -3,7 +3,7 @@ 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.entities.Entity.Direction;
import com.gr15.pacman.model.Board.TileType;
import com.gr15.pacman.model.entities.Entity;
import com.gr15.pacman.model.entities.Pacman;
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
index c492628..15c567a 100644
--- a/pacman/model/src/main/java/com/gr15/pacman/model/Position.java
+++ b/pacman/model/src/main/java/com/gr15/pacman/model/Position.java
@@ -2,7 +2,7 @@ package com.gr15.pacman.model;
import java.util.List;
-import com.gr15.pacman.model.Board.Direction;
+import com.gr15.pacman.model.entities.Entity.Direction;
/**
* Position
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
index 395a170..daf0eef 100644
--- 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
@@ -13,6 +13,8 @@ public abstract class Entity {
private float subTileY = 0.0f;
private double radius;
+
+ public enum Direction { UP, DOWN, LEFT, RIGHT, NONE };
public Entity(Position startPos, double radius) {
this.radius = radius;
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
index 5d9cf22..cb15b06 100644
--- 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
@@ -2,25 +2,50 @@ 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
+ * Represents the Pacman character in the game.
+ * Handles movement logic including direction changes, wall collisions,
+ * snapping to tile centers, and updating position on the game board.
*/
public class Pacman
extends Entity {
- /* Tiles per second */
+ /* Javadoc for attributes,
+ * since movement is a little complex */
+
+ /** Movement speed in tiles per second. */
private double speed;
+
+ /** Current direction of movement. */
private Direction currentDirection = Direction.NONE;
+
+ /** Desired direction to change to, if possible. */
private Direction nextDirection;
+ /**
+ * Constructs a new Pacman instance.
+ *
+ * @param startPos the starting tile {@link Position} of Pacman.
+ * @param speed the movement speed in tiles per second.
+ * @param startDir the initial movement {@link Direction}.
+ * @param radius the radius of Pacman collision.
+ */
public Pacman(Position startPos, double speed, Direction startDir, double radius) {
super(startPos, radius);
this.speed = speed;
this.nextDirection = startDir;
}
+ /**
+ * Updates Pacman's {@link Position} based on the time elapsed
+ * and the game {@link Board} state.
+ * Handles turning, snapping to tile center,
+ * and tile boundary transitions.
+ *
+ * @param board the game {@link Board}, used to determine valid movement.
+ * @param deltaSeconds time in seconds since the last update in seconds.
+ */
@Override
public void move(Board board, double deltaSeconds) {
float subTileX = super.getSubTileX();
@@ -28,118 +53,201 @@ public class Pacman
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);
+ boolean canMoveNext = canMove(board, currentPos, nextDirection);
+ boolean canContinue = canMove(board, currentPos, currentDirection);
+ Direction direction = decideDirection(canMoveNext, canContinue);
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;
+ snapToCenter(distanceToMove);
+ return; /* Returning early, since no more updating required */
}
- boolean verticalMove = direction == Direction.UP
- || direction == Direction.DOWN;
- int directionSign = (direction == Direction.UP
- || direction == Direction.LEFT) ? -1 : 1;
+ boolean verticalMove = isVertical(direction);
+ int directionSign = getDirectionSign(direction);
+
+ double subPrimary = verticalMove ? subTileY : subTileX;
+ double subSecondary = verticalMove ? subTileX : subTileY;
- /* 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);
+ double center = Math.floor(subSecondary) + 0.5;
+ double distanceToCenter = Math.abs(subSecondary - center);
- /* First, move to center if needed */
+ /* Snap to secondary axis center first */
if (distanceToCenter > 0.01) {
double moveToCenter = Math.min(distanceToMove, distanceToCenter);
- if (subTileSecondary < center) {
- subTileSecondary += moveToCenter;
- } else {
- subTileSecondary -= moveToCenter;
- }
+ subSecondary += (subSecondary < center ? 1 : -1) * moveToCenter;
distanceToMove -= moveToCenter;
}
- /* Apply secondary axis back */
+ /* Storing new secondry axis sub-tile position */
if (verticalMove) {
- subTileX = (float)subTileSecondary;
+ subTileX = (float)subSecondary;
} else {
- subTileY = (float)subTileSecondary;
+ subTileY = (float)subSecondary;
}
- /* Now, attempt to move along primary axis */
while (distanceToMove > 0.0001) {
- double maxStep = directionSign > 0 ? 1.0 - subTilePrimary
- : subTilePrimary;
+ /* Capping movement distance to a single tile */
+ double maxStep = directionSign > 0 ? 1.0 - subPrimary : subPrimary;
double step = Math.min(distanceToMove, maxStep);
- double newSubTilePrimary = subTilePrimary + directionSign * step;
-
+ double newSubPrimary = subPrimary + 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;
+ if (crossedTileBoundary(direction, newSubPrimary)) {
+ Position nextPos = currentPos.offset(direction);
+ if (board.isMovable(nextPos)) {
+ currentPos = nextPos;
+ subPrimary = directionSign > 0 ? 0.0 : 1.0;
} else {
currentDirection = Direction.NONE;
- subTilePrimary = directionSign > 0 ? 1.0 : 0.0;
- break;
+ subPrimary = directionSign > 0 ? 1.0 : 0.0;
+ break; /* stopping at wall */
}
} else {
- subTilePrimary = newSubTilePrimary;
+ subPrimary = newSubPrimary;
}
+ /* If there's still longer to go */
distanceToMove -= step;
}
- /* Assign back primary axis */
+ /* Storing primary axis sub-tile position */
if (verticalMove) {
- subTileY = (float)subTilePrimary;
+ subTileY = (float)subPrimary;
} else {
- subTileX = (float)subTilePrimary;
+ subTileX = (float)subPrimary;
}
- /* Update direction state */
+ /* If hit wall, set direction to none */
if (canMoveNext) {
currentDirection = nextDirection;
nextDirection = Direction.NONE;
}
- /* Update final state */
+ /* Setting new position */
super.setSubTileX(subTileX);
super.setSubTileY(subTileY);
super.setPosition(currentPos);
}
- /* Getters and setters */
+ /**
+ * Helper function that determines if Pacman can move
+ * in the specified direction.
+ *
+ * @param board the game {@link Board}.
+ * @param pos the current {@link Position}.
+ * @param dir the direction to check.
+ * @return true if the tile in the given {@link Direction} is movable.
+ */
+ private boolean canMove(Board board, Position pos, Direction dir) {
+ return dir != Direction.NONE && board.isMovable(pos.offset(dir));
+ }
+
+ /**
+ * Helper function that decides the direction to move in
+ * based on current and next direction availability.
+ *
+ * @param canMoveNext true if the next direction is available.
+ * @param canContinue true if continuing in the current direction is possible.
+ * @return the direction Pacman should move in.
+ */
+ private Direction decideDirection(boolean canMoveNext, boolean canContinue) {
+ if (canMoveNext) { return nextDirection; }
+ if (canContinue) { return currentDirection; }
+ return Direction.NONE;
+ }
+
+ /**
+ * helper function that checks if a direction is vertical.
+ *
+ * @param dir the direction to check.
+ * @return true if the direction is {@link Direction.UP} or {@link Direction.DOWN}.
+ */
+ private boolean isVertical(Direction dir) {
+ return dir == Direction.UP || dir == Direction.DOWN;
+ }
+
+ /**
+ * Helper function that gets the sign of movement for a {@link Direction}.
+ *
+ * @param dir the direction.
+ * @return -1 for UP or LEFT and 1 for DOWN or RIGHT.
+ */
+ private int getDirectionSign(Direction dir) {
+ return (dir == Direction.UP || dir == Direction.LEFT) ? -1 : 1;
+ }
+
+ /**
+ * Helper function that determines if Pacman has crossed a tile boundary.
+ *
+ * @param dir the direction of movement.
+ * @param newPrimary the new sub-tile coordinate in the movement axis.
+ * @return true if a tile boundary was crossed.
+ */
+ private boolean crossedTileBoundary(Direction dir, double newPrimary) {
+ return (dir == Direction.UP && newPrimary <= 0.0)
+ || (dir == Direction.DOWN && newPrimary >= 1.0)
+ || (dir == Direction.LEFT && newPrimary <= 0.0)
+ || (dir == Direction.RIGHT && newPrimary >= 1.0);
+ }
+
+ /**
+ * Helper function that snaps Pacman toward the center of the tile when not moving.
+ *
+ * @param distanceToMove the maximum distance Pacman can move.
+ */
+ private void snapToCenter(double distanceToMove) {
+ float subTileX = super.getSubTileX();
+ float subTileY =super.getSubTileY();
+ double center = 0.5;
+
+ subTileX = (float)snapAxisToCenter(subTileX, center, distanceToMove);
+ subTileY = (float)snapAxisToCenter(subTileY, center, distanceToMove);
+
+ super.setSubTileX(subTileX);
+ super.setSubTileY(subTileY);
+ }
+
+ /**
+ * Helper function that moves a sub-tile coordinate toward the center up to a maximum distance.
+ *
+ * @param sub the current sub-coordinate.
+ * @param center the center coordinate (typically 0.5).
+ * @param maxMove the maximum movement allowed.
+ * @return the updated coordinate.
+ */
+ private double snapAxisToCenter(double sub, double center, double maxMove) {
+ double dist = Math.abs(sub - center);
+ if (dist < maxMove) {
+ return center;
+ } else {
+ return sub + ((sub < center) ? 1 : -1) * maxMove;
+ }
+ }
+
+ /**
+ * Gets the current speed of Pacman.
+ *
+ * @return the speed in tiles per second.
+ */
public double getSpeed() { return this.speed; }
+
+ /**
+ * Gets the current movement direction of Pacman.
+ *
+ * @return the current {@link Direction}.
+ */
public Direction getDirection() { return this.currentDirection; }
+
+ /**
+ * Sets a new speed for Pacman.
+ *
+ * @param newSpeed the new speed value in tiles per second.
+ */
public void setSpeed(double newSpeed) { this.speed = newSpeed; }
+
+ /**
+ * Requests Pacman to change direction at the next available opportunity.
+ *
+ * @param newDir the desired direction.
+ */
public void setDirection(Direction newDir) { this.nextDirection = newDir; }
}