From e8e3774158f749e0214fb34ebdba29527d054874 Mon Sep 17 00:00:00 2001 From: mithe24 Date: Tue, 8 Apr 2025 11:23:56 +0200 Subject: Initial commit --- pacman/controller/pom.xml | 2 +- .../java/com/gr15/pacman/controller/GameApp.java | 45 +++++++ .../com/gr15/pacman/controller/GameController.java | 65 +++++++++ pacman/controller/src/main/java/module-info.java | 10 +- .../src/main/java/pacman/controller/GameApp.java | 21 --- pacman/model/pom.xml | 14 ++ .../src/main/java/com/gr15/pacman/model/Board.java | 49 +++++++ .../main/java/com/gr15/pacman/model/GameState.java | 85 ++++++++++++ .../java/com/gr15/pacman/model/JsonParser.java | 36 +++++ .../main/java/com/gr15/pacman/model/Position.java | 38 ++++++ .../com/gr15/pacman/model/entities/Entity.java | 36 +++++ .../gr15/pacman/model/entities/EntityUtils.java | 31 +++++ .../java/com/gr15/pacman/model/entities/Ghost.java | 19 +++ .../java/com/gr15/pacman/model/entities/Items.java | 3 + .../com/gr15/pacman/model/entities/Pacman.java | 145 +++++++++++++++++++++ pacman/model/src/main/java/module-info.java | 9 +- pacman/model/src/main/resources/maps/testmap.json | 20 +++ pacman/pom.xml | 4 +- .../java/com/gr15/pacman/view/AnimatedSprite.java | 31 +++++ .../main/java/com/gr15/pacman/view/GameView.java | 109 ++++++++++++++++ .../src/main/java/com/gr15/pacman/view/Sprite.java | 35 +++++ pacman/view/src/main/java/module-info.java | 11 +- .../src/main/resources/gameAssets/blueGhost.png | Bin 0 -> 258 bytes .../view/src/main/resources/gameAssets/cherry.png | Bin 0 -> 271 bytes .../view/src/main/resources/gameAssets/cherry2.png | Bin 0 -> 223 bytes .../src/main/resources/gameAssets/orangeGhost.png | Bin 0 -> 246 bytes .../src/main/resources/gameAssets/pacmanDown.png | Bin 0 -> 204 bytes .../src/main/resources/gameAssets/pacmanLeft.png | Bin 0 -> 203 bytes .../src/main/resources/gameAssets/pacmanRight.png | Bin 0 -> 205 bytes .../src/main/resources/gameAssets/pacmanUp.png | Bin 0 -> 207 bytes .../src/main/resources/gameAssets/pinkGhost.png | Bin 0 -> 249 bytes .../src/main/resources/gameAssets/redGhost.png | Bin 0 -> 249 bytes .../src/main/resources/gameAssets/scaredGhost.png | Bin 0 -> 239 bytes pacman/view/src/main/resources/gameAssets/wall.png | Bin 0 -> 152 bytes 34 files changed, 778 insertions(+), 40 deletions(-) create mode 100644 pacman/controller/src/main/java/com/gr15/pacman/controller/GameApp.java create mode 100644 pacman/controller/src/main/java/com/gr15/pacman/controller/GameController.java delete mode 100644 pacman/controller/src/main/java/pacman/controller/GameApp.java create mode 100644 pacman/model/pom.xml create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/Board.java create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/GameState.java create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/Position.java create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/entities/Entity.java create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/entities/EntityUtils.java create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/entities/Ghost.java create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/entities/Items.java create mode 100644 pacman/model/src/main/java/com/gr15/pacman/model/entities/Pacman.java create mode 100644 pacman/model/src/main/resources/maps/testmap.json create mode 100644 pacman/view/src/main/java/com/gr15/pacman/view/AnimatedSprite.java create mode 100644 pacman/view/src/main/java/com/gr15/pacman/view/GameView.java create mode 100644 pacman/view/src/main/java/com/gr15/pacman/view/Sprite.java create mode 100644 pacman/view/src/main/resources/gameAssets/blueGhost.png create mode 100644 pacman/view/src/main/resources/gameAssets/cherry.png create mode 100644 pacman/view/src/main/resources/gameAssets/cherry2.png create mode 100644 pacman/view/src/main/resources/gameAssets/orangeGhost.png create mode 100644 pacman/view/src/main/resources/gameAssets/pacmanDown.png create mode 100644 pacman/view/src/main/resources/gameAssets/pacmanLeft.png create mode 100644 pacman/view/src/main/resources/gameAssets/pacmanRight.png create mode 100644 pacman/view/src/main/resources/gameAssets/pacmanUp.png create mode 100644 pacman/view/src/main/resources/gameAssets/pinkGhost.png create mode 100644 pacman/view/src/main/resources/gameAssets/redGhost.png create mode 100644 pacman/view/src/main/resources/gameAssets/scaredGhost.png create mode 100644 pacman/view/src/main/resources/gameAssets/wall.png (limited to 'pacman') diff --git a/pacman/controller/pom.xml b/pacman/controller/pom.xml index e3a99f8..6baf25f 100644 --- a/pacman/controller/pom.xml +++ b/pacman/controller/pom.xml @@ -34,7 +34,7 @@ javafx-maven-plugin 0.0.8 - pacman.controller.GameApp + com.gr15.pacman.controller.GameApp diff --git a/pacman/controller/src/main/java/com/gr15/pacman/controller/GameApp.java b/pacman/controller/src/main/java/com/gr15/pacman/controller/GameApp.java new file mode 100644 index 0000000..1c8bc75 --- /dev/null +++ b/pacman/controller/src/main/java/com/gr15/pacman/controller/GameApp.java @@ -0,0 +1,45 @@ +package com.gr15.pacman.controller; + +import com.gr15.pacman.model.GameState; +import com.gr15.pacman.model.JsonParser; +import com.gr15.pacman.view.GameView; + +import javafx.application.Application; +import javafx.stage.Stage; + +/** + * GameApp + */ +public class GameApp + extends Application { + + GameController gameController; + GameView gameView; + GameState gameState; + + @Override + public void start(Stage primaryStage) throws Exception { + primaryStage.setTitle("Pac-Man"); + primaryStage.setResizable(false); + primaryStage.setFullScreen(true); + + try { + gameState = JsonParser.getGameState("test"); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to load game state: " + e.getMessage()); + } + + gameView = new GameView(gameState, 8, 5); + primaryStage.setScene(gameView); + + gameController = new GameController(gameState, gameView); + gameController.startGameLoop(); + + primaryStage.show(); + } + + public static void main(String[] args) { + launch(args); + } +} 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 new file mode 100644 index 0000000..b1208be --- /dev/null +++ b/pacman/controller/src/main/java/com/gr15/pacman/controller/GameController.java @@ -0,0 +1,65 @@ +package com.gr15.pacman.controller; + +import com.gr15.pacman.model.GameState; +import com.gr15.pacman.model.Board.Direction; +import com.gr15.pacman.view.GameView; + +import javafx.animation.AnimationTimer; +import javafx.scene.paint.Color; + +/** + * GameController + */ +public class GameController { + + private GameState gameState; + private GameView gameView; + + private AnimationTimer gameLoop; + private long lastUpdate = 0; + + public GameController(GameState gameState, GameView gameView) { + this.gameState = gameState; + this.gameView = gameView; + gameView.setFill(Color.BLACK); + + setupEventHandlers(); + gameLoop = new AnimationTimer() { + + @Override + public void handle(long now) { + if (lastUpdate == 0) { + lastUpdate = now; + return; /* returning early, since no time have elapsed */ + } + + double deltaSeconds = (now - lastUpdate) / 1_000_000_000.0; + lastUpdate = now; + + gameState.update(deltaSeconds); + gameView.renderGame(deltaSeconds); + } + }; + } + + private void setupEventHandlers() { + gameView.setOnKeyPressed(event -> { + switch (event.getCode()) { + case UP -> gameState.getPacman().setDirection(Direction.UP); + case DOWN -> gameState.getPacman().setDirection(Direction.DOWN); + case LEFT -> gameState.getPacman().setDirection(Direction.LEFT); + case RIGHT -> gameState.getPacman().setDirection(Direction.RIGHT); + default -> {} + } + }); + } + + public void startGameLoop() { + gameLoop.start(); + } + + public void stopGameLoop() { + lastUpdate = 0; + gameLoop.stop(); + } +} diff --git a/pacman/controller/src/main/java/module-info.java b/pacman/controller/src/main/java/module-info.java index 75c422d..8b4e271 100644 --- a/pacman/controller/src/main/java/module-info.java +++ b/pacman/controller/src/main/java/module-info.java @@ -1,9 +1,7 @@ /* module-info.java * This acts as the manifest for the module. */ -module pacman.controller { - requires javafx.controls; /* Declares a dependency on another module */ - requires pacman.model; /* Should depenend on model, */ - requires pacman.view; /* and view */ - exports pacman.controller; /* exports make specific packages */ -} /* public to other modules */ +module com.gr15.pacman.controller { + requires transitive com.gr15.pacman.view; + exports com.gr15.pacman.controller; +} diff --git a/pacman/controller/src/main/java/pacman/controller/GameApp.java b/pacman/controller/src/main/java/pacman/controller/GameApp.java deleted file mode 100644 index 648dc15..0000000 --- a/pacman/controller/src/main/java/pacman/controller/GameApp.java +++ /dev/null @@ -1,21 +0,0 @@ -package pacman.controller; - -import javafx.application.Application; -import javafx.stage.Stage; - -/** - * GameApp - */ -public class GameApp - extends Application { - - @Override - public void start(Stage arg0) throws Exception { - // TODO Auto-generated method stub - - } - - public static void main(String[] args) { - launch(args); - } -} diff --git a/pacman/model/pom.xml b/pacman/model/pom.xml new file mode 100644 index 0000000..02e5fb8 --- /dev/null +++ b/pacman/model/pom.xml @@ -0,0 +1,14 @@ + + 4.0.0 + + + com.gr15 + pacman + 1.0-SNAPSHOT + ../pom.xml + + + model + 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 entities; + private Map items; + + private int score = 0; + private int lives = 3; + private double powerModeDuration = 0; + + public GameState(Board board, Pacman pacman, + Map entities, Map 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 getEntities() { return this.entities; } + public Map 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 newItems) { + this.items = newItems; + } + public void setEntities(Map 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 entities = new HashMap<>(); + Map 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 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; +} diff --git a/pacman/model/src/main/resources/maps/testmap.json b/pacman/model/src/main/resources/maps/testmap.json new file mode 100644 index 0000000..547f48f --- /dev/null +++ b/pacman/model/src/main/resources/maps/testmap.json @@ -0,0 +1,20 @@ + +{ + "spooky": true, + "pacManSpawn": [ + { + "x": 1, + "y": 1 + } + ], + "tileBoard": [ + "x","x","x","x","x", + "x","e","e","e","x", + "x","e","x","e","x", + "x","e","e","e","x", + "x","x","e","x","x", + "x","e","e","e","x", + "x","x","e","x","x", + "x","x","x","x","x" + ] +} diff --git a/pacman/pom.xml b/pacman/pom.xml index f083890..9299cd5 100644 --- a/pacman/pom.xml +++ b/pacman/pom.xml @@ -11,8 +11,8 @@ UTF-8 - 17 - 17 + 24 + 24 17.0.2 diff --git a/pacman/view/src/main/java/com/gr15/pacman/view/AnimatedSprite.java b/pacman/view/src/main/java/com/gr15/pacman/view/AnimatedSprite.java new file mode 100644 index 0000000..763c876 --- /dev/null +++ b/pacman/view/src/main/java/com/gr15/pacman/view/AnimatedSprite.java @@ -0,0 +1,31 @@ +package com.gr15.pacman.view; + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.image.Image; + +public class AnimatedSprite extends Sprite { + private Image[] frames; + private int currentFrame = 0; + private double frameTime = 0.1; // seconds per frame + private double timeSinceLastFrame = 0.0; + + public AnimatedSprite(Image[] frames, double x, double y, double width, double height) { + super(frames[0], x, y, width, height); + this.frames = frames; + } + + public void update(double deltaSeconds) { + timeSinceLastFrame += deltaSeconds; + if (timeSinceLastFrame >= frameTime) { + currentFrame = (currentFrame + 1) % frames.length; + super.setImage(frames[currentFrame]); + timeSinceLastFrame = 0.0; + } + } + + @Override + public void render(GraphicsContext gc) { + super.render(gc); + } +} + diff --git a/pacman/view/src/main/java/com/gr15/pacman/view/GameView.java b/pacman/view/src/main/java/com/gr15/pacman/view/GameView.java new file mode 100644 index 0000000..62617d6 --- /dev/null +++ b/pacman/view/src/main/java/com/gr15/pacman/view/GameView.java @@ -0,0 +1,109 @@ +package com.gr15.pacman.view; + +import java.util.HashMap; +import java.util.Map; + +import com.gr15.pacman.model.GameState; +import com.gr15.pacman.model.Board.TileType; + +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.image.Image; +import javafx.scene.layout.StackPane; + +import com.gr15.pacman.model.entities.Entity; +import com.gr15.pacman.model.entities.Items; + +/** + * GameView + */ +public class GameView + extends Scene { + + /* Utils */ + private Canvas canvas; + private GraphicsContext gc; + private GameState gameState; + private StackPane root; + + private float scaleX = 4.0f; + private float scaleY = 4.0f; + private int tileHeight; + private int tileWidth; + + private Map tileTextures = new HashMap<>(); + private Map entityTextures = new HashMap<>(); + private Map itemTextures = new HashMap<>(); + + /* UI elements */ + private Sprite pacmanSprite; + + public GameView(GameState gameState, + int tileHeight, int tileWidth) { + super(new StackPane()); + root = (StackPane)super.getRoot(); + + canvas = new Canvas(tileWidth * 16 * scaleX, tileHeight * 16 * scaleY); + gc = canvas.getGraphicsContext2D(); + root.getChildren().add(canvas); + + this.tileHeight = tileHeight; + this.tileWidth = tileWidth; + this.gameState = gameState; + + tileTextures.put(TileType.WALL, new Image( + this.getClass().getResourceAsStream("/gameAssets/wall.png"))); + pacmanSprite = new Sprite(new Image( + this.getClass().getResourceAsStream("/gameAssets/pacmanRight.png")), + gameState.getPacman().getPositionX() - 0.5, + gameState.getPacman().getPositionY() - 0.5, + 16 * scaleX, 16 * scaleY); + } + + public void renderGame(double deltaSeconds) { + gc.clearRect(0, 0, tileWidth * 16 * scaleX, tileHeight * 16 * scaleY); + TileType[][] tileBoard = gameState.getBoard().getTileBoard(); + for (int y = 0; y < tileBoard.length; y++) { + for (int x = 0; x < tileBoard[y].length; x++) { + Image texture = tileTextures.get(tileBoard[y][x]); + if (texture != null) { + gc.drawImage(texture, + x * 16 * scaleX, + y * 16 * scaleY, + texture.getWidth() * scaleX, + texture.getHeight() * scaleY); + } + } + } + + pacmanSprite.setX((gameState.getPacman().getPositionX() + - 0.5) * 16 * scaleX); + pacmanSprite.setY((gameState.getPacman().getPositionY() + - 0.5) * 16 * scaleY); + pacmanSprite.render(gc); + + gameState.getEntities().forEach((pos, entity) -> { + Image texture = entityTextures.get(entity); + if (texture != null) { + gc.drawImage(texture, + entity.getPositionX() * 16 * scaleX, + entity.getPositionY() * 16 * scaleY, + texture.getWidth() * scaleX, + texture.getHeight() * scaleY); + } + }); + + gameState.getItems().forEach((pos, item) -> { + Image texture = itemTextures.get(item); + if (texture != null) { + gc.drawImage(texture, + pos.x() * 16 * scaleX, + pos.y() * 16 * scaleY, + texture.getWidth() * scaleX, + texture.getHeight() * scaleY); + + } + }); + } +} diff --git a/pacman/view/src/main/java/com/gr15/pacman/view/Sprite.java b/pacman/view/src/main/java/com/gr15/pacman/view/Sprite.java new file mode 100644 index 0000000..f397e7d --- /dev/null +++ b/pacman/view/src/main/java/com/gr15/pacman/view/Sprite.java @@ -0,0 +1,35 @@ +package com.gr15.pacman.view; + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.image.Image; + +public class Sprite { + private Image image; + private double x, y; + private double width, height; + + public Sprite(Image image, double x, double y, double width, double height) { + this.image = image; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public void render(GraphicsContext gc) { + gc.drawImage(image, x, y, width, height); + } + + /* Getters and setters */ + public Image getImage() { return this.image; } + public double getX() { return this.x; } + public double getY() { return this.y; } + public double getWidth() { return this.width; } + public double getHeigt() { return this.height; } + + public void setImage(Image newImage) { this.image = newImage; } + public void setX(double newX) { this.x = newX; } + public void setY(double newY) { this.y = newY; } + public void setWidth(double newWidth) { this.width = newWidth; } + public void setHeight(double newHeight) { this.height = newHeight; } +} diff --git a/pacman/view/src/main/java/module-info.java b/pacman/view/src/main/java/module-info.java index a9649df..914038a 100644 --- a/pacman/view/src/main/java/module-info.java +++ b/pacman/view/src/main/java/module-info.java @@ -1,9 +1,8 @@ /* module-info.java * This acts as the manifest for the module. */ -module pacman.view { - requires javafx.controls; /* JavaFX dependencies */ - requires javafx.graphics; - requires pacman.model; - exports pacman.view; /* exports make specific packages */ -} /* public to other modules */ +module com.gr15.pacman.view { + requires transitive javafx.graphics; + requires transitive com.gr15.pacman.model; + exports com.gr15.pacman.view; +} diff --git a/pacman/view/src/main/resources/gameAssets/blueGhost.png b/pacman/view/src/main/resources/gameAssets/blueGhost.png new file mode 100644 index 0000000..e1ee979 Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/blueGhost.png differ diff --git a/pacman/view/src/main/resources/gameAssets/cherry.png b/pacman/view/src/main/resources/gameAssets/cherry.png new file mode 100644 index 0000000..45c4f31 Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/cherry.png differ diff --git a/pacman/view/src/main/resources/gameAssets/cherry2.png b/pacman/view/src/main/resources/gameAssets/cherry2.png new file mode 100644 index 0000000..6dea0ca Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/cherry2.png differ diff --git a/pacman/view/src/main/resources/gameAssets/orangeGhost.png b/pacman/view/src/main/resources/gameAssets/orangeGhost.png new file mode 100644 index 0000000..bcd1cb8 Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/orangeGhost.png differ diff --git a/pacman/view/src/main/resources/gameAssets/pacmanDown.png b/pacman/view/src/main/resources/gameAssets/pacmanDown.png new file mode 100644 index 0000000..2c24dbe Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/pacmanDown.png differ diff --git a/pacman/view/src/main/resources/gameAssets/pacmanLeft.png b/pacman/view/src/main/resources/gameAssets/pacmanLeft.png new file mode 100644 index 0000000..168f495 Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/pacmanLeft.png differ diff --git a/pacman/view/src/main/resources/gameAssets/pacmanRight.png b/pacman/view/src/main/resources/gameAssets/pacmanRight.png new file mode 100644 index 0000000..7e370a0 Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/pacmanRight.png differ diff --git a/pacman/view/src/main/resources/gameAssets/pacmanUp.png b/pacman/view/src/main/resources/gameAssets/pacmanUp.png new file mode 100644 index 0000000..9f4a39b Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/pacmanUp.png differ diff --git a/pacman/view/src/main/resources/gameAssets/pinkGhost.png b/pacman/view/src/main/resources/gameAssets/pinkGhost.png new file mode 100644 index 0000000..12c3f84 Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/pinkGhost.png differ diff --git a/pacman/view/src/main/resources/gameAssets/redGhost.png b/pacman/view/src/main/resources/gameAssets/redGhost.png new file mode 100644 index 0000000..cfd374e Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/redGhost.png differ diff --git a/pacman/view/src/main/resources/gameAssets/scaredGhost.png b/pacman/view/src/main/resources/gameAssets/scaredGhost.png new file mode 100644 index 0000000..9e26fff Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/scaredGhost.png differ diff --git a/pacman/view/src/main/resources/gameAssets/wall.png b/pacman/view/src/main/resources/gameAssets/wall.png new file mode 100644 index 0000000..ab12c87 Binary files /dev/null and b/pacman/view/src/main/resources/gameAssets/wall.png differ -- cgit v1.2.3-70-g09d2