summaryrefslogtreecommitdiff
path: root/pacman/model/src/main
diff options
context:
space:
mode:
authormithe24 <mithe24@student.sdu.dk>2025-05-07 17:11:58 +0200
committerGitHub <noreply@github.com>2025-05-07 17:11:58 +0200
commitc164daed53574babb26796b05682432709e2c5c1 (patch)
tree50690b34f82847368be7c08c54b4489d4fea3e15 /pacman/model/src/main
parentec0f4221ecd71c0b18e8403daa58b66077ec4343 (diff)
downloadpacman-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')
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/GameState.java15
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/GameStateBuilder.java117
-rw-r--r--pacman/model/src/main/java/com/gr15/pacman/model/JsonParser.java36
-rw-r--r--pacman/model/src/main/java/module-info.java1
-rw-r--r--pacman/model/src/main/resources/maps/testmap.json20
5 files changed, 126 insertions, 63 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);
- }
-
-}
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"
- ]
-}