diff options
| author | mithe24 <mithe24@student.sdu.dk> | 2025-05-07 17:11:58 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-07 17:11:58 +0200 |
| commit | c164daed53574babb26796b05682432709e2c5c1 (patch) | |
| tree | 50690b34f82847368be7c08c54b4489d4fea3e15 /pacman/model/src/main/java/com | |
| parent | ec0f4221ecd71c0b18e8403daa58b66077ec4343 (diff) | |
| download | pacman-c164daed53574babb26796b05682432709e2c5c1.tar.gz pacman-c164daed53574babb26796b05682432709e2c5c1.zip | |
Feature/json parser (#18)
* chore(model/json-parser): Added maven dependency
* chore(model): Removed old test JSON file
* refactor(model/GameState): List better then map, entities should be able
to overlap
* feat(Pacman): Added GameState builder to initiate GameState with given
paramters.
Added a short example JSON-file, more key-value pairs needs to be added
as the game progresses.
Likewise the builder won't parse for any other key-value pair
automatically.
Diffstat (limited to 'pacman/model/src/main/java/com')
3 files changed, 125 insertions, 43 deletions
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); - } - -} |