diff options
Diffstat (limited to '')
9 files changed, 170 insertions, 74 deletions
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 index 1c8bc75..ffd4493 100644 --- a/pacman/controller/src/main/java/com/gr15/pacman/controller/GameApp.java +++ b/pacman/controller/src/main/java/com/gr15/pacman/controller/GameApp.java @@ -1,7 +1,9 @@ package com.gr15.pacman.controller; +import java.io.InputStream; + import com.gr15.pacman.model.GameState; -import com.gr15.pacman.model.JsonParser; +import com.gr15.pacman.model.GameStateBuilder; import com.gr15.pacman.view.GameView; import javafx.application.Application; @@ -23,14 +25,13 @@ public class GameApp 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); + InputStream inputStream = this.getClass() + .getResourceAsStream("/testGameState.json"); + GameState gameState = GameStateBuilder.fromJson(inputStream); + inputStream.close(); + int tileWidth = gameState.getBoard().getWidth(); + int tileHeight = gameState.getBoard().getHeight(); + gameView = new GameView(gameState,tileWidth, tileHeight); primaryStage.setScene(gameView); gameController = new GameController(gameState, gameView); diff --git a/pacman/controller/src/main/resources/testGameState.json b/pacman/controller/src/main/resources/testGameState.json new file mode 100644 index 0000000..48e333a --- /dev/null +++ b/pacman/controller/src/main/resources/testGameState.json @@ -0,0 +1,22 @@ +{ + "pacman": { + "x": 1, + "y": 1, + "speed": 3.0, + "radius": 1.0 + }, + + "itmes": [], + "board": [ + ["W","W","W","W","W","W","W","W","W"], + ["W","E","E","E","E","E","E","E","W"], + ["E","E","W","W","E","W","W","E","E"], + ["W","E","W","W","E","W","W","E","W"], + ["W","E","W","W","E","W","W","E","W"], + ["W","E","E","E","E","E","E","E","W"], + ["W","E","W","W","E","W","W","E","W"], + ["E","E","W","W","E","W","W","E","E"], + ["W","E","E","E","E","E","E","E","W"], + ["W","W","W","W","W","W","W","W","W"] + ] +} diff --git a/pacman/model/pom.xml b/pacman/model/pom.xml index 02e5fb8..6eac4b2 100644 --- a/pacman/model/pom.xml +++ b/pacman/model/pom.xml @@ -11,4 +11,12 @@ </parent> <artifactId>model</artifactId> + <dependencies> + <!-- https://mvnrepository.com/artifact/org.json/json --> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20250107</version> + </dependency> + </dependencies> </project> 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 index ef33488..609bfc0 100644 --- a/pacman/model/src/main/java/com/gr15/pacman/model/GameState.java +++ b/pacman/model/src/main/java/com/gr15/pacman/model/GameState.java @@ -1,5 +1,6 @@ package com.gr15.pacman.model; +import java.util.List; import java.util.Map; import com.gr15.pacman.model.entities.Entity; @@ -15,15 +16,15 @@ public class GameState { private Board board; private Pacman pacman; - private Map<Position, Entity> entities; + private List<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) { + protected GameState(Board board, Pacman pacman, + List<Entity> entities, Map<Position, Items> items) { this.board = board; this.entities = entities; this.items = items; @@ -42,7 +43,7 @@ public class GameState { powerModeDuration = Math.max(powerModeDuration, 0); /* updating and checking collisions with entities */ - entities.forEach((pos, entity) -> { + for (Entity entity : entities) { entity.move(board, deltaSeconds); if (EntityUtils.hasCollided(pacman, entity) && powerModeDuration == 0) { @@ -50,7 +51,7 @@ public class GameState { } else if (EntityUtils.hasCollided(pacman, entity)) { score += 100; } - }); + } /* checking collisions with items */ Items item = items.get(pacman.getPosition()); @@ -66,7 +67,7 @@ public class GameState { /* Getters and setters */ public Board getBoard() { return this.board; } public Pacman getPacman() { return this.pacman; } - public Map<Position, Entity> getEntities() { return this.entities; } + public List<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; } @@ -79,7 +80,7 @@ public class GameState { public void setItems(Map<Position, Items> newItems) { this.items = newItems; } - public void setEntities(Map<Position, Entity> newEntities) { + public void setEntities(List<Entity> newEntities) { this.entities = newEntities; } } diff --git a/pacman/model/src/main/java/com/gr15/pacman/model/GameStateBuilder.java b/pacman/model/src/main/java/com/gr15/pacman/model/GameStateBuilder.java new file mode 100644 index 0000000..aab7dd9 --- /dev/null +++ b/pacman/model/src/main/java/com/gr15/pacman/model/GameStateBuilder.java @@ -0,0 +1,117 @@ +package com.gr15.pacman.model; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; + +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.Ghost; +import com.gr15.pacman.model.entities.Items; +import com.gr15.pacman.model.entities.Pacman; + +/** + * Utility class to build a {@link GameState} object from a JSON configuration. + * + * <p> + * This class provides static methods to parse game data such as the board, + * entities, and items from a JSON input stream and use it to initialize + * a game state. It handles parsing logic and translates string representations + * into model objects used by the game engine. + * </p> + */ +public class GameStateBuilder { + + /** + Parses a JSON input stream and constructs a {@link GameState} based on the configuration. + * <p> + * Expected JSON structure includes: + * <ul> + * <li>{@code pacmanSpawnPoint}: an array of two integers + * representing the X and Y coordinates.</li> + * <li>{@code board}: a 2D array of strings + * representing the board tiles ("W" for wall, "E" for empty).</li> + * <li>{@code pacman}: a JSON object containing properties + * such as {@code x}, {@code y}, {@code speed}, and {@code radius}.</li> + * </ul> + * + * @param inputStream the input stream of the JSON file. + * @return a {@link GameState} object built from the JSON configuration. + * @throws RuntimeException if the JSON is invalid or the file cannot be read. + */ + public static GameState fromJson(InputStream inputStream) { + /* Reader gets closed automatically, + * because it's in the resources part of a try-with-resource statement. + * The InputStream gets closed by Reader */ + try (InputStreamReader reader = new InputStreamReader(inputStream)) { + JSONTokener tokener = new JSONTokener(reader); + JSONObject jsonObject = new JSONObject(tokener); + return buildFromJsonObject(jsonObject); + } catch (JSONException jsonException) { + throw new RuntimeException(""" + Failed to parse JSON content. + Please ensure the file contains valid JSON.""", jsonException); + } catch (IOException ioException) { + throw new RuntimeException(""" + Error reading JSON file. + Ensure the file exists and is accessible""", ioException); + } + } + + /** + * Internal helper method that constructs a {@link GameState} object + * from a given {@link JSONObject}. + * + * <p> + * This method extracts the board layout, Pacman parameters, + * and initializes the entities and items. + * + * @param jsonObject the JSON object containing game configuration data. + * @return a fully constructed {@link GameState} object. + * @throws RuntimeException if required fields are missing or incorrectly formatted. + + */ + private static GameState buildFromJsonObject(JSONObject jsonObject) { + try { + JSONArray stringBoard = jsonObject.getJSONArray("board"); + TileType[][] tileBoard = new TileType + [stringBoard.length()] + [stringBoard.getJSONArray(0).length()]; + for (int y = 0; y < stringBoard.length(); y++) { + JSONArray row = stringBoard.getJSONArray(y); + for (int x = 0; x < row.length(); x++) { + switch (row.getString(x)) { + case "W" -> tileBoard[y][x] = TileType.WALL; + case "E" -> tileBoard[y][x] = TileType.EMPTY; + default -> {} + } + } + } + Board board = new Board(tileBoard[0].length, tileBoard.length, tileBoard); + + JSONObject pacmanJsonObject = jsonObject.getJSONObject("pacman"); + double speed = pacmanJsonObject.getDouble("speed"); + double radius = pacmanJsonObject.getDouble("radius"); + Position pacmanStartPos = new Position( + pacmanJsonObject.getInt("x"), + pacmanJsonObject.getInt("y")); + Pacman pacman = new Pacman(pacmanStartPos, speed, Direction.NONE, radius); + + ArrayList<Entity> entities = new ArrayList<>(); + Map<Position, Items> items = new HashMap<>(); + + return new GameState(board, pacman, entities, items); + } catch (JSONException jsonException) { + throw new RuntimeException("Failed to parse GameState json", jsonException); + } + } +} 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 deleted file mode 100644 index 990fb15..0000000 --- a/pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.gr15.pacman.model; - -import java.util.HashMap; -import java.util.Map; - -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; -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/module-info.java b/pacman/model/src/main/java/module-info.java index 95d9324..5a7d26d 100644 --- a/pacman/model/src/main/java/module-info.java +++ b/pacman/model/src/main/java/module-info.java @@ -3,6 +3,7 @@ */ module com.gr15.pacman.model { requires transitive javafx.controls; + requires org.json; 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 deleted file mode 100644 index 547f48f..0000000 --- a/pacman/model/src/main/resources/maps/testmap.json +++ /dev/null @@ -1,20 +0,0 @@ - -{ - "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/view/src/main/java/com/gr15/pacman/view/GameView.java b/pacman/view/src/main/java/com/gr15/pacman/view/GameView.java index 62617d6..d56a1e1 100644 --- a/pacman/view/src/main/java/com/gr15/pacman/view/GameView.java +++ b/pacman/view/src/main/java/com/gr15/pacman/view/GameView.java @@ -1,6 +1,7 @@ package com.gr15.pacman.view; import java.util.HashMap; +import java.util.List; import java.util.Map; import com.gr15.pacman.model.GameState; @@ -83,7 +84,8 @@ public class GameView - 0.5) * 16 * scaleY); pacmanSprite.render(gc); - gameState.getEntities().forEach((pos, entity) -> { + List<Entity> entities = gameState.getEntities(); + for (Entity entity : entities) { Image texture = entityTextures.get(entity); if (texture != null) { gc.drawImage(texture, @@ -92,7 +94,7 @@ public class GameView texture.getWidth() * scaleX, texture.getHeight() * scaleY); } - }); + } gameState.getItems().forEach((pos, item) -> { Image texture = itemTextures.get(item); |