From edb1e1dee40d18547ca263aa5b6c15cd21f9ecfd Mon Sep 17 00:00:00 2001 From: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> Date: Sun, 24 Apr 2022 14:24:15 +0200 Subject: [PATCH 01/12] chore: points popup refactor (#18) * feat: Add showing points popup on key press (F) * refactor: Create PopupController - class responsible for creating and controlling popups, currently only handles PointsEarnedPopup * Apply suggestions from code review Co-authored-by: Kacper Kafara Co-authored-by: Kacper Kafara --- .../java/io/rpg/controller/Controller.java | 15 ++++- .../io/rpg/controller/PopupController.java | 44 ++++++++++++++ .../io/rpg/view/popups/PointsEarnedPopup.java | 59 ++++++------------- .../rpg/viewmodel/PointsPopupViewModel.java | 3 +- .../io/rpg/viewmodel/location-view.fxml | 2 +- 5 files changed, 76 insertions(+), 47 deletions(-) create mode 100644 src/main/java/io/rpg/controller/PopupController.java diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index 96200780..a9732259 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -4,10 +4,8 @@ import io.rpg.model.data.MouseClickedEvent; import io.rpg.model.location.LocationModel; import io.rpg.util.Result; -import io.rpg.view.GameObjectView; import io.rpg.view.LocationView; import javafx.scene.Scene; -import javafx.scene.input.KeyEvent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -20,6 +18,7 @@ public class Controller implements KeyboardEvent.Observer, MouseClickedEvent.Obs private LocationModel currentModel; private LinkedHashMap tagToLocationViewMap; private Logger logger; + private final PopupController popupController = new PopupController(); public Controller() { @@ -90,6 +89,18 @@ else if (currentModel == null) public void onKeyboardEvent(KeyboardEvent event) { // TODO: implement event handling logger.info("Controller notified on key pressed from " + event.source()); + + switch (event.payload().getCode()) { + case F -> popupController.openPointsPopup(5, getWindowCenterX(), getWindowCenterY()); + } + } + + private int getWindowCenterX() { + return (int) (currentView.getWindow().getX() + currentView.getWindow().getWidth() / 2); + } + + private int getWindowCenterY() { + return (int) (currentView.getWindow().getY() + currentView.getWindow().getHeight() / 2); } @Override diff --git a/src/main/java/io/rpg/controller/PopupController.java b/src/main/java/io/rpg/controller/PopupController.java new file mode 100644 index 00000000..670a4c9b --- /dev/null +++ b/src/main/java/io/rpg/controller/PopupController.java @@ -0,0 +1,44 @@ +package io.rpg.controller; + +import io.rpg.view.popups.PointsEarnedPopup; +import javafx.stage.Stage; +import javafx.stage.StageStyle; + +import java.io.IOException; + +public class PopupController { + + private final Stage popupStage = new Stage(StageStyle.TRANSPARENT); + private PointsEarnedPopup pointsPopupScene; + + public PopupController() { + try { + pointsPopupScene = new PointsEarnedPopup(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void openPointsPopup(int pointsCount, int x, int y) { + pointsPopupScene.setPointsCount(pointsCount); + popupStage.setScene(pointsPopupScene); + + // close popup after clicking aside + popupStage.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { + if (!isNowFocused) { + popupStage.close(); + } + }); + + popupStage.show(); + + popupStage.setX(x - pointsPopupScene.getWidth() / 2); + popupStage.setY(y - pointsPopupScene.getHeight() / 2); + } + + public void hidePopup() { + popupStage.hide(); + } + +} + diff --git a/src/main/java/io/rpg/view/popups/PointsEarnedPopup.java b/src/main/java/io/rpg/view/popups/PointsEarnedPopup.java index b818e8e6..40820c9d 100644 --- a/src/main/java/io/rpg/view/popups/PointsEarnedPopup.java +++ b/src/main/java/io/rpg/view/popups/PointsEarnedPopup.java @@ -1,59 +1,34 @@ package io.rpg.view.popups; import io.rpg.viewmodel.PointsPopupViewModel; +import java.io.IOException; +import java.util.Objects; import javafx.fxml.FXMLLoader; +import javafx.scene.Group; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.paint.Color; -import javafx.stage.Stage; -import javafx.stage.StageStyle; -import javafx.stage.Window; -import javafx.util.Pair; -import java.io.IOException; -import java.util.Objects; +public class PointsEarnedPopup extends Scene { + + private final PointsPopupViewModel controller; -public class PointsEarnedPopup { + public PointsEarnedPopup(String backgroundPath) throws IOException { + super(new Group(), Color.TRANSPARENT); - private final FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(PointsEarnedPopup.class.getResource("points-earned-view.fxml"))); - private Parent root; - private PointsPopupViewModel controller; - private final Scene popupScene; + FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(PointsPopupViewModel.class.getResource("points-earned-view.fxml"))); + Parent root = loader.load(); + this.setRoot(root); - public PointsEarnedPopup() { - // read FXML view - try { - root = loader.load(); - } catch (IOException e) { - e.printStackTrace(); - } + controller = loader.getController(); + controller.setBackgroundImage(backgroundPath); + } - popupScene = new Scene(root, Color.TRANSPARENT); + public PointsEarnedPopup() throws IOException { + this("file:assets/point-popup-bg.png"); } - public Stage getPopup(int pointsCount, Scene scene) { - // fill dynamic view components - if (controller == null) controller = loader.getController(); + public void setPointsCount(int pointsCount){ controller.setPointsCount(pointsCount); - Pair backgroundDims = controller.setBackgroundImage("file:assets/point-popup-bg.png"); - - // create popup stage - Stage popupStage = new Stage(StageStyle.TRANSPARENT); - Window window = scene.getWindow(); - popupStage.initOwner(window); - - // add and center popupScene on popup stage - popupStage.setScene(popupScene); - popupStage.setX(window.getX() + window.getWidth() / 2 - backgroundDims.getKey() / 2); - popupStage.setY(window.getY() + window.getHeight() / 2 - backgroundDims.getValue() / 2); - - // close popup after clicking aside - popupStage.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { - if (!isNowFocused) { - popupStage.close(); - } - }); - - return popupStage; } } diff --git a/src/main/java/io/rpg/viewmodel/PointsPopupViewModel.java b/src/main/java/io/rpg/viewmodel/PointsPopupViewModel.java index 6523df37..f98155c0 100644 --- a/src/main/java/io/rpg/viewmodel/PointsPopupViewModel.java +++ b/src/main/java/io/rpg/viewmodel/PointsPopupViewModel.java @@ -17,7 +17,7 @@ public void setPointsCount(int pointsCount) { label.setText("Earned " + pointsCount + " points!"); } - public Pair setBackgroundImage(String url) { + public void setBackgroundImage(String url) { BackgroundImage backgroundImg = new BackgroundImage( new Image(url), BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, @@ -25,6 +25,5 @@ public Pair setBackgroundImage(String url) { BackgroundSize.DEFAULT ); background.setBackground(new Background(backgroundImg)); - return new Pair<>(background.getPrefWidth(), background.getPrefHeight()); } } diff --git a/src/main/resources/io/rpg/viewmodel/location-view.fxml b/src/main/resources/io/rpg/viewmodel/location-view.fxml index 2f55ae9a..c567fec8 100644 --- a/src/main/resources/io/rpg/viewmodel/location-view.fxml +++ b/src/main/resources/io/rpg/viewmodel/location-view.fxml @@ -5,7 +5,7 @@ - + From 1bdcd631ac00ff3dce7d9b6dff617c166b78fce4 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Apr 2022 14:25:20 +0200 Subject: [PATCH 02/12] chore: register view to model (#16) * chore: allow for creation of different object types * refact: newline at object-1 file end * chore: add JavaDoc comments for MouseClickedEvent * chore: add JavaDoc comments for KeyboardEvent * chore: add JavaDoc comments for GameObjectStateChange * chore: add JavaDocs comments for LocationModelStateChange * chore: style update * chore: make Initializer#mainStage field final mainStage is coming as a constructor parameter and it is entry stage provided by JavaFX. We do not change, and we do not want to change this reference anywhere. * chore: remove INTERACTIVE from GameObject.Type enum options We do not intent to instantiate abstract InteractiveGameObject type. Only more specific types should be instantiated. * refact: move GameObject construction to separate factory class & methods * chore: add GameObjectViewFactory class & methods This aims to extract the object creation logic from LocationView class * chore: add builder for LocationModel This aims to extract the creation logic to separate class to make object injection possible. (Object injection is needed as we need register view to model) * fix: LocationModel builder methods * chore: add non null assertion in LocationModel.Builder#setTag method * chore: register GameObjectViews to their model classses! * fix: convert game object type string to uppercase in factory method * fix: remove "interactive" type from configuration types * chore: update before merging (#19) --- .../locations/location-1/location-1.json | 6 +- .../location-1/objects/object-1.json | 2 +- .../locations/location-2/location-2.json | 8 +- src/main/java/io/rpg/Initializer.java | 59 +++++++++----- src/main/java/io/rpg/config/ConfigLoader.java | 3 + .../io/rpg/config/model/GameObjectConfig.java | 4 +- .../rpg/model/data/GameObjectStateChange.java | 17 +++- .../java/io/rpg/model/data/KeyboardEvent.java | 11 ++- .../model/data/LocationModelStateChange.java | 9 +++ .../io/rpg/model/data/MouseClickedEvent.java | 10 ++- .../io/rpg/model/location/LocationModel.java | 80 +++++++++++++++++-- .../model/object/CollectibleGameObject.java | 2 +- .../io/rpg/model/object/DialogGameObject.java | 2 +- .../java/io/rpg/model/object/GameObject.java | 53 +++++++++--- .../model/object/InteractiveGameObject.java | 10 +-- .../model/object/NavigationalGameObject.java | 2 +- .../java/io/rpg/util/GameObjectFactory.java | 49 ++++++++++++ .../io/rpg/util/GameObjectViewFactory.java | 41 ++++++++++ src/main/java/io/rpg/view/GameObjectView.java | 8 +- src/main/java/io/rpg/view/LocationView.java | 7 +- 20 files changed, 322 insertions(+), 61 deletions(-) create mode 100644 src/main/java/io/rpg/util/GameObjectFactory.java create mode 100644 src/main/java/io/rpg/util/GameObjectViewFactory.java diff --git a/configurations/config-1/locations/location-1/location-1.json b/configurations/config-1/locations/location-1/location-1.json index 5e9bfa04..94025965 100644 --- a/configurations/config-1/locations/location-1/location-1.json +++ b/configurations/config-1/locations/location-1/location-1.json @@ -1,8 +1,8 @@ { "tag": "location-1", "objects": [ - { "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible" }, - { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "interactive" } + { "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible", "assetPath": "assets/someDude.png" }, + { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "dialog", "assetPath": "assets/someDude.png" } ], - "backgroundPath": "file:assets/map.png" + "backgroundPath": "assets/map.png" } diff --git a/configurations/config-1/locations/location-1/objects/object-1.json b/configurations/config-1/locations/location-1/objects/object-1.json index 6f2ed3ae..2ab6ba3f 100644 --- a/configurations/config-1/locations/location-1/objects/object-1.json +++ b/configurations/config-1/locations/location-1/objects/object-1.json @@ -2,4 +2,4 @@ "tag": "object-1", "assetPath": "/path/to/the/asset", "type": "" -} \ No newline at end of file +} diff --git a/configurations/config-1/locations/location-2/location-2.json b/configurations/config-1/locations/location-2/location-2.json index dc949d25..2d5eae12 100644 --- a/configurations/config-1/locations/location-2/location-2.json +++ b/configurations/config-1/locations/location-2/location-2.json @@ -1,8 +1,8 @@ { "tag": "location-2", "objects": [ - { "tag": "object-1", "position": { "row": 0, "col": 0 }, "type": "collectible" }, - { "tag": "object-3", "position": { "row": 0, "col": 1 }, "type": "navigable" } + { "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible", "assetPath": "assets/someDude.png" }, + { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "dialog", "assetPath": "assets/someDude.png" } ], - "backgroundPath": "file:assets/map.png" -} \ No newline at end of file + "backgroundPath": "assets/map.png" +} diff --git a/src/main/java/io/rpg/Initializer.java b/src/main/java/io/rpg/Initializer.java index 965c2ea9..77e325bc 100644 --- a/src/main/java/io/rpg/Initializer.java +++ b/src/main/java/io/rpg/Initializer.java @@ -7,7 +7,10 @@ import io.rpg.model.location.LocationModel; import io.rpg.model.object.GameObject; import io.rpg.config.model.GameObjectConfig; +import io.rpg.util.GameObjectFactory; +import io.rpg.util.GameObjectViewFactory; import io.rpg.util.Result; +import io.rpg.view.GameObjectView; import io.rpg.view.LocationView; import javafx.stage.Stage; import org.apache.logging.log4j.LogManager; @@ -17,14 +20,13 @@ import java.io.IOException; import java.nio.file.Path; -import java.util.LinkedHashMap; -import java.util.LinkedList; +import java.util.Iterator; import java.util.List; public class Initializer { private Path pathToConfigDir; private ConfigLoader configLoader; - private Stage mainStage; + private final Stage mainStage; private final Logger logger; @@ -56,7 +58,16 @@ public Result initialize() { assert worldConfig.getLocationConfigs().size() > 0 : "There must be at least one location config specified"; for (LocationConfig locationConfig : worldConfig.getLocationConfigs()) { - LocationModel model = loadLocationModelFromConfig(locationConfig); + + List gameObjects = loadGameObjectsForLocation(locationConfig); + List gameObjectViews = loadGameObjectViewsForLocation(locationConfig); + + registerGameObjectViewsToModel(gameObjects, gameObjectViews); + + LocationModel model = new LocationModel.Builder() + .setTag(locationConfig.getTag()) + .setGameObjects(gameObjects).build(); + LocationView view = loadLocationViewFromConfig(locationConfig); assert view != null; @@ -80,6 +91,32 @@ public Result initialize() { return Result.ok(gameBuilder.build()); } + public static List loadGameObjectsForLocation(LocationConfig config) { + return GameObjectFactory.fromConfigList(config.getObjects()); + } + + public static List loadGameObjectViewsForLocation(LocationConfig config) { + return GameObjectViewFactory.fromConfigList(config.getObjects()); + } + + public static void registerGameObjectViewsToModel(List gameObjects, + List gameObjectViews) { + assert gameObjects.size() == gameObjectViews.size() : "Arrays must be of the same length!"; + + Iterator gameObjectIterator = gameObjects.iterator(); + Iterator gameObjectViewIterator = gameObjectViews.iterator(); + + // we asserted earlier that both lists have the same length thus we don't + // need to check .hasNext() for both lists + while (gameObjectIterator.hasNext()) { + GameObject gameObject = gameObjectIterator.next(); + GameObjectView gameObjectView = gameObjectViewIterator.next(); + + // registration + gameObject.addGameObjectStateChangeObserver(gameObjectView); + } + } + @Nullable public static LocationView loadLocationViewFromConfig(LocationConfig config) { try { @@ -89,18 +126,4 @@ public static LocationView loadLocationViewFromConfig(LocationConfig config) { } return null; } - - public static LocationModel loadLocationModelFromConfig(LocationConfig config) { - List gameObjectConfigs = config.getObjects(); - List gameObjects = new LinkedList<>(); - - for (GameObjectConfig goconfig : gameObjectConfigs) { - gameObjects.add(GameObject.fromConfig(goconfig)); - } - - return new LocationModel( - config.getTag(), - gameObjects - ); - } } diff --git a/src/main/java/io/rpg/config/ConfigLoader.java b/src/main/java/io/rpg/config/ConfigLoader.java index 2ee4bce1..6919cf26 100644 --- a/src/main/java/io/rpg/config/ConfigLoader.java +++ b/src/main/java/io/rpg/config/ConfigLoader.java @@ -201,6 +201,9 @@ LocationConfig loadLocationConfig(@NotNull String locationTag) throws FileNotFou BufferedReader reader = new BufferedReader(new FileReader(locationConfigJson.toString())); LocationConfig config = gson.fromJson(reader, LocationConfig.class); config.setPath(locationDir); + + logger.info("Path to background for location"); + logger.info(config.getBackgroundPath()); return config; } diff --git a/src/main/java/io/rpg/config/model/GameObjectConfig.java b/src/main/java/io/rpg/config/model/GameObjectConfig.java index 7175de06..10f83ea4 100644 --- a/src/main/java/io/rpg/config/model/GameObjectConfig.java +++ b/src/main/java/io/rpg/config/model/GameObjectConfig.java @@ -12,14 +12,14 @@ */ public class GameObjectConfig extends GameObject { - private String type; public GameObjectConfig(@NotNull String tag, @NotNull Position position) { super(tag, position); } - public String getType() { + public String getTypeString() { + assert type != null : "Attempt to access uninitialized \"type\" field!"; return type; } diff --git a/src/main/java/io/rpg/model/data/GameObjectStateChange.java b/src/main/java/io/rpg/model/data/GameObjectStateChange.java index 20367182..e421cae8 100644 --- a/src/main/java/io/rpg/model/data/GameObjectStateChange.java +++ b/src/main/java/io/rpg/model/data/GameObjectStateChange.java @@ -2,16 +2,25 @@ import io.rpg.model.object.GameObject; -public record GameObjectStateChange ( +/** + * Event representing game object model change. + */ +public record GameObjectStateChange( GameObject source, - Object payload // TODO: what kind of data do we want? What changed? What can change? - // or maybe implement separate methods for observer & emitter for different kinds - // of event + Object payload // TODO: what kind of data do we want? What changed? What can change? + // or maybe implement separate methods for observer & emitter for different kinds + // of events ) { + /** + * Interface for {@link GameObjectStateChange} observer. + */ public interface Observer { void onGameObjectStateChange(GameObjectStateChange event); } + /** + * Interface for {@link GameObjectStateChange} event emitter. + */ public interface Emitter { void emitGameObjectStateChange(GameObjectStateChange event); diff --git a/src/main/java/io/rpg/model/data/KeyboardEvent.java b/src/main/java/io/rpg/model/data/KeyboardEvent.java index d7021da6..9d49aacb 100644 --- a/src/main/java/io/rpg/model/data/KeyboardEvent.java +++ b/src/main/java/io/rpg/model/data/KeyboardEvent.java @@ -3,11 +3,20 @@ import javafx.scene.Scene; import javafx.scene.input.KeyEvent; -final public record KeyboardEvent(Scene source, KeyEvent payload) { +/** + * Represents a keyboard clicked event. + */ +public final record KeyboardEvent(Scene source, KeyEvent payload) { + /** + * Interface for {@link KeyboardEvent} observer. + */ public interface Observer { void onKeyboardEvent(KeyboardEvent event); } + /** + * Interface for {@link KeyboardEvent} emitter. + */ public interface Emitter { void addKeyboardEventObserver(KeyboardEvent.Observer observer); diff --git a/src/main/java/io/rpg/model/data/LocationModelStateChange.java b/src/main/java/io/rpg/model/data/LocationModelStateChange.java index 0720837f..b8ff6e41 100644 --- a/src/main/java/io/rpg/model/data/LocationModelStateChange.java +++ b/src/main/java/io/rpg/model/data/LocationModelStateChange.java @@ -2,14 +2,23 @@ import io.rpg.model.location.LocationModel; +/** + * Event representing location model state change. + */ public record LocationModelStateChange( LocationModel source, Object payload // TODO: Same considerations as for GameObjectStateChange ) { + /** + * Interface for {@link LocationModelStateChange} observer. + */ public interface Observer { void onLocationModelStateChange(LocationModelStateChange event); } + /** + * Interface for {@link LocationModelStateChange} event emitter. + */ public interface Emitter { void addOnLocationModelStateChangeObserver(Observer observer); diff --git a/src/main/java/io/rpg/model/data/MouseClickedEvent.java b/src/main/java/io/rpg/model/data/MouseClickedEvent.java index 9bd59fa7..d07ed189 100644 --- a/src/main/java/io/rpg/model/data/MouseClickedEvent.java +++ b/src/main/java/io/rpg/model/data/MouseClickedEvent.java @@ -5,16 +5,22 @@ import org.jetbrains.annotations.NotNull; /** - * + * Represents mouse click event. */ -final public record MouseClickedEvent( +public record MouseClickedEvent( @NotNull GameObjectView source, @NotNull MouseEvent payload ) { + /** + * Interface for {@link MouseClickedEvent} observer. + */ public interface Observer { void onMouseClickedEvent(MouseClickedEvent event); } + /** + * Interface for {@link MouseClickedEvent} emitter. + */ public interface Emitter { void emitOnMouseClickedEvent(MouseClickedEvent event); diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 6e4b240a..d031c456 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -3,14 +3,16 @@ import io.rpg.model.data.LocationModelStateChange; import io.rpg.model.object.Player; import io.rpg.model.object.GameObject; +import io.rpg.util.Result; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.UnmodifiableView; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** - * Represents single location in our game + * Represents single location in our game. */ public class LocationModel implements LocationModelStateChange.Emitter { private String tag; @@ -20,9 +22,12 @@ public class LocationModel implements LocationModelStateChange.Emitter { private final Set locationModelStateChangeObservers; public LocationModel(@NotNull String tag, @NotNull List gameObjects) { + this(); this.tag = tag; this.gameObjects = gameObjects; - this.player = null; + } + + private LocationModel() { this.locationModelStateChangeObservers = new LinkedHashSet<>(); } @@ -34,6 +39,31 @@ public String getTag() { return tag; } + /** + * Private setter for Builder usage only. + * + * @param tag tag for the location + */ + private void setTag(String tag) { + this.tag = tag; + } + + @UnmodifiableView + public List getGameObjects() { + return Collections.unmodifiableList(gameObjects); + } + + /** + * Private setter for Builder usage only. Notice that ownership of {@link GameObject}s is not + * transferred to LocationModel. + * TODO: Transfer ownership of objects to LoactionModel. + * + * @param gameObjects game object for location + */ + private void setGameObjects(List gameObjects) { + this.gameObjects = gameObjects; + } + @Override public void addOnLocationModelStateChangeObserver(LocationModelStateChange.Observer observer) { locationModelStateChangeObservers.add(observer); @@ -50,4 +80,44 @@ public void emitLocationModelStateChange(LocationModelStateChange event) { observer.onLocationModelStateChange(event); }); } + + public Result validate() { + if (tag == null || gameObjects == null) { + return Result.error(null); + } + return Result.ok(null); + } + + public static class Builder { + private final LocationModel locationModel; + + private final Logger logger; + + public Builder() { + logger = LogManager.getLogger(Builder.class); + locationModel = new LocationModel(); + } + + public Builder setGameObjects(@NotNull List gameObjects) { + locationModel.setGameObjects(gameObjects); + return this; + } + + public Builder setTag(@NotNull String tag) { + assert tag != null : "Location tag must not be null!"; + locationModel.setTag(tag); + return this; + } + + public LocationModel build() { + Result result = locationModel.validate(); + + // TODO(@kkafar): Handle this in better way. Consider returning the result. + if (result.isError()) { + logger.error("Error occurred while building LocationModel."); + } + + return locationModel; + } + } } diff --git a/src/main/java/io/rpg/model/object/CollectibleGameObject.java b/src/main/java/io/rpg/model/object/CollectibleGameObject.java index 60c437ff..3884f2e1 100644 --- a/src/main/java/io/rpg/model/object/CollectibleGameObject.java +++ b/src/main/java/io/rpg/model/object/CollectibleGameObject.java @@ -3,7 +3,7 @@ import io.rpg.model.data.Position; import org.jetbrains.annotations.NotNull; -final public class CollectibleGameObject extends InteractiveGameObject { +public final class CollectibleGameObject extends InteractiveGameObject { public CollectibleGameObject(@NotNull String tag, @NotNull Position position) { super(tag, position); } diff --git a/src/main/java/io/rpg/model/object/DialogGameObject.java b/src/main/java/io/rpg/model/object/DialogGameObject.java index 54a97023..ebcbc838 100644 --- a/src/main/java/io/rpg/model/object/DialogGameObject.java +++ b/src/main/java/io/rpg/model/object/DialogGameObject.java @@ -3,7 +3,7 @@ import io.rpg.model.data.Position; import org.jetbrains.annotations.NotNull; -final public class DialogGameObject extends InteractiveGameObject { +public final class DialogGameObject extends InteractiveGameObject { public DialogGameObject(@NotNull String tag, @NotNull Position position) { super(tag, position); } diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index ad4089ae..5cbafade 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -1,22 +1,26 @@ package io.rpg.model.object; import io.rpg.config.model.GameObjectConfig; +import io.rpg.model.data.GameObjectStateChange; import io.rpg.model.data.Position; import org.jetbrains.annotations.NotNull; +import java.util.LinkedHashSet; +import java.util.Set; + /** * Class representing common state properties for all - * objects appearing in the game + * objects appearing in the game. */ -public class GameObject { +public class GameObject implements GameObjectStateChange.Emitter { /** - * Position of game object in model's representation of location + * Position of game object in model's representation of location. */ @NotNull private final Position position; /** - * Unique identifier of this game object + * Unique identifier of this game object. */ @NotNull private final String tag; @@ -27,13 +31,16 @@ public class GameObject { @NotNull private String assetPath; + @NotNull + private final Set stateChangeObservers; + @NotNull public String getAssetPath() { return assetPath; } /** - * Unique identifier of this game object + * Unique identifier of this game object. */ @NotNull public String getTag() { @@ -41,7 +48,7 @@ public String getTag() { } /** - * Position of game object in model's representation of location + * Position of game object in model's representation of location. */ @NotNull public Position getPosition() { @@ -49,18 +56,42 @@ public Position getPosition() { } public GameObject(@NotNull String tag, @NotNull Position position) { - this.tag = tag; - this.position = position; - this.assetPath = ""; // TODO + this(tag, position, ""); } public GameObject(@NotNull String tag, @NotNull Position position, @NotNull String assetPath) { this.tag = tag; this.position = position; this.assetPath = assetPath; + this.stateChangeObservers = new LinkedHashSet<>(); + } + + @Override + public void emitGameObjectStateChange(GameObjectStateChange event) { + // TODO + // noop for now } - public static GameObject fromConfig(GameObjectConfig config) { - return new GameObject("XD", new Position(3, 3), "file:assets/someDude.png"); + @Override + public void addGameObjectStateChangeObserver(GameObjectStateChange.Observer observer) { + this.stateChangeObservers.add(observer); + } + + @Override + public void removeGameObjectStateChangeObserver(GameObjectStateChange.Observer observer) { + this.stateChangeObservers.remove(observer); + } + + public enum Type { + NAVIGABLE("navigable"), + DIALOG("dialog"), + PLAYER("player"), + COLLECTIBLE("collectible"); + + private final String asString; + + Type(String asString) { + this.asString = asString; + } } } diff --git a/src/main/java/io/rpg/model/object/InteractiveGameObject.java b/src/main/java/io/rpg/model/object/InteractiveGameObject.java index 8e73699a..c1be7799 100644 --- a/src/main/java/io/rpg/model/object/InteractiveGameObject.java +++ b/src/main/java/io/rpg/model/object/InteractiveGameObject.java @@ -3,10 +3,10 @@ import io.rpg.model.data.Position; import org.jetbrains.annotations.NotNull; -abstract public class InteractiveGameObject extends GameObject { - public InteractiveGameObject(@NotNull String tag, @NotNull Position position) { - super(tag, position); - } +public abstract class InteractiveGameObject extends GameObject { + public InteractiveGameObject(@NotNull String tag, @NotNull Position position) { + super(tag, position); + } - abstract public void onAction(); + abstract public void onAction(); } diff --git a/src/main/java/io/rpg/model/object/NavigationalGameObject.java b/src/main/java/io/rpg/model/object/NavigationalGameObject.java index e68e543d..28e8d64f 100644 --- a/src/main/java/io/rpg/model/object/NavigationalGameObject.java +++ b/src/main/java/io/rpg/model/object/NavigationalGameObject.java @@ -3,7 +3,7 @@ import io.rpg.model.data.Position; import org.jetbrains.annotations.NotNull; -final public class NavigationalGameObject extends InteractiveGameObject { +public final class NavigationalGameObject extends InteractiveGameObject { public NavigationalGameObject(@NotNull String tag, @NotNull Position position) { super(tag, position); diff --git a/src/main/java/io/rpg/util/GameObjectFactory.java b/src/main/java/io/rpg/util/GameObjectFactory.java new file mode 100644 index 00000000..48fd8f83 --- /dev/null +++ b/src/main/java/io/rpg/util/GameObjectFactory.java @@ -0,0 +1,49 @@ +package io.rpg.util; + +import io.rpg.config.model.GameObjectConfig; +import io.rpg.model.object.CollectibleGameObject; +import io.rpg.model.object.DialogGameObject; +import io.rpg.model.object.GameObject; +import io.rpg.model.object.NavigationalGameObject; + +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; + +/** + * Exposes collection of methods to create {@link io.rpg.model.object.GameObject} class instances. + */ +public class GameObjectFactory { + /** + * Creates {@link GameObject} instance basing on information contained in config. + * + * @param config description of object properties + * @return game object created based on information located in config + */ + public static GameObject fromConfig(GameObjectConfig config) { + // TODO: add case for Player type here! + switch (GameObject.Type.valueOf(config.getTypeString().toUpperCase())) { + case COLLECTIBLE -> { return new CollectibleGameObject(config.getTag(), config.getPosition()); } + case DIALOG -> { return new DialogGameObject(config.getTag(), config.getPosition()); } + case NAVIGABLE -> { return new NavigationalGameObject(config.getTag(), config.getPosition()); } + default -> throw new RuntimeException("Unknown GameObject type. This should not happen!"); + } + } + + /** + * Creates list of {@link GameObject} instances based on information contained in list of configs. + * This method guarantees that {@link GameObject}s located in result list are in the same order, + * i.e. first {@link GameObject} is created from first {@link GameObjectConfig}, second from second + * etc. + * + * @param configs descriptions of object properties + * @return game objects created based on information located in config list + */ + public static LinkedList fromConfigList(List configs) { + LinkedList gameObjects = new LinkedList<>(); + for (GameObjectConfig config : configs) { + gameObjects.add(fromConfig(config)); + } + return gameObjects; + } +} diff --git a/src/main/java/io/rpg/util/GameObjectViewFactory.java b/src/main/java/io/rpg/util/GameObjectViewFactory.java new file mode 100644 index 00000000..250db5d7 --- /dev/null +++ b/src/main/java/io/rpg/util/GameObjectViewFactory.java @@ -0,0 +1,41 @@ +package io.rpg.util; + +import io.rpg.config.model.GameObjectConfig; +import io.rpg.view.GameObjectView; + +import java.nio.file.Path; +import java.util.LinkedList; +import java.util.List; + +/** + * Exposes collection of methods to create {@link GameObjectView} class instances. + */ +public class GameObjectViewFactory { + /** + * Creates {@link GameObjectView} instance basing on information contained in config. + * + * @param config description of object properties + * @return game object view created based on information located in config + */ + public static GameObjectView fromConfig(GameObjectConfig config) { + // TODO: consider returning Result type & validate the construction + return new GameObjectView(Path.of(config.getAssetPath()), config.getPosition()); + } + + /** + * Creates list of {@link GameObjectView}s instances based on information contained in list of configs. + * This method guarantees that {@link GameObjectView}s located in result list are in the same order, + * i.e. first {@link GameObjectView} is created from first {@link GameObjectConfig}, second from second + * etc. + * + * @param configs descriptions of object properties + * @return game object views created based on information located in config list + */ + public static LinkedList fromConfigList(List configs) { + LinkedList gameObjects = new LinkedList<>(); + for (GameObjectConfig config : configs) { + gameObjects.add(fromConfig(config)); + } + return gameObjects; + } +} diff --git a/src/main/java/io/rpg/view/GameObjectView.java b/src/main/java/io/rpg/view/GameObjectView.java index b55aaad7..0ee8ae55 100644 --- a/src/main/java/io/rpg/view/GameObjectView.java +++ b/src/main/java/io/rpg/view/GameObjectView.java @@ -18,7 +18,8 @@ public class GameObjectView extends ImageView public GameObjectView(@NotNull Path assetPath, @NotNull Position position) { this.path = assetPath; - this.setImage(new Image(path.toString())); +// String xdpath = + this.setImage(new Image(resolvePathToJFXFormat(path.toString()))); // todo: better position class this.setX(position.col); this.setY(position.row); @@ -26,6 +27,11 @@ public GameObjectView(@NotNull Path assetPath, @NotNull Position position) { this.setOnMouseClicked(event -> emitOnMouseClickedEvent(new MouseClickedEvent(this, event))); } + public static String resolvePathToJFXFormat(String path) { + return "file:" + path; + } + + @Override public void emitOnMouseClickedEvent(MouseClickedEvent event) { onClickedObservers.forEach(listener -> listener.onMouseClickedEvent(event)); diff --git a/src/main/java/io/rpg/view/LocationView.java b/src/main/java/io/rpg/view/LocationView.java index a3d0b55a..332536fd 100644 --- a/src/main/java/io/rpg/view/LocationView.java +++ b/src/main/java/io/rpg/view/LocationView.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.net.URL; +import java.nio.file.Path; import java.util.HashSet; import java.util.Set; @@ -60,11 +61,15 @@ public static LocationView fromConfig(LocationConfig config) throws IOException LocationView view = loadFromFXML(FXML_URL); System.out.println("BACKGROUND PATH"); System.out.println(config.getBackgroundPath()); - view.getViewModel().setBackground(new Image(config.getBackgroundPath())); + view.getViewModel().setBackground(new Image(resolvePathToJFXFormat(config.getBackgroundPath()))); // todo: na podstawie configu ustawić pola korzystając z view modelu return view; } + public static String resolvePathToJFXFormat(String path) { + return "file:" + path; + } + @Override public void addKeyboardEventObserver(KeyboardEvent.Observer observer) { onKeyPressedObservers.add(observer); From 10f3f700510b51da890a936ec52c77fe826ca571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Siekierzy=C5=84ski?= <57154175+ksiek127@users.noreply.github.com> Date: Sun, 24 Apr 2022 14:28:37 +0200 Subject: [PATCH 03/12] feat: display objects on screen (#17) * chore: Massive update... * BREAKING CHANGES: Arch proposal * chore: rename io.rpg.torefract -> io.rpg.torefact * refact: rename PointsPopupController -> PointsPopupViewModel * refact: add comments & change method names in ConfigLoader * refact: add comments tgo GameObjectConfig * refact: add comments to GameWorldConfig * chore: make ConfigLoader#{loadGameWorldConfig,loadLocationConfig} methods private * chore: add generic class describing operation result * chore: add Optional returning getters to Result * fix: revert changes from #de086eb Unit tests require these methods -> they must stay being visible inside a package * chore: update configuration files * chore: improve error handlign in config module via Result class * feat: add helper methods to Result class isOkValueNull, isErrorValueNull * chore: add builder to the Game class * refact: adapt Main to new Result based interface * feat: add builder to the Controller * chore: update unit test configuration * fix: make unit tests pass * chore: Update observer schema before refractoring * docs: add more comments to GameWorldConfig * chore: make GameObjectConfig#valide method return Result * chore: Cleanup ConfigLoader * chore: minor fixes & apply linter * refact: apply style suggestions * chore: attempt to display game objects on screen * chore: displaying objects on screen v1 * chore: displaying objects on screen v2 Co-authored-by: Kacper Kafara --- .../locations/location-1/objects/object-1.json | 6 ++++-- .../locations/location-1/objects/object-2.json | 7 +++++++ src/main/java/io/rpg/view/LocationView.java | 15 ++++++++++++++- .../java/io/rpg/viewmodel/LocationViewModel.java | 6 ++++++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/configurations/config-1/locations/location-1/objects/object-1.json b/configurations/config-1/locations/location-1/objects/object-1.json index 2ab6ba3f..406fd2f4 100644 --- a/configurations/config-1/locations/location-1/objects/object-1.json +++ b/configurations/config-1/locations/location-1/objects/object-1.json @@ -1,5 +1,7 @@ { "tag": "object-1", - "assetPath": "/path/to/the/asset", - "type": "" + "assetPath": "assets/stone.png", + "type": "", + "x": 150, + "y": 200 } diff --git a/configurations/config-1/locations/location-1/objects/object-2.json b/configurations/config-1/locations/location-1/objects/object-2.json index e69de29b..ee8b8f05 100644 --- a/configurations/config-1/locations/location-1/objects/object-2.json +++ b/configurations/config-1/locations/location-1/objects/object-2.json @@ -0,0 +1,7 @@ +{ + "tag": "object-2", + "assetPath": "assets/stone.png", + "type": "", + "x": 50, + "y": 100 +} \ No newline at end of file diff --git a/src/main/java/io/rpg/view/LocationView.java b/src/main/java/io/rpg/view/LocationView.java index 332536fd..dfd643ba 100644 --- a/src/main/java/io/rpg/view/LocationView.java +++ b/src/main/java/io/rpg/view/LocationView.java @@ -1,7 +1,12 @@ package io.rpg.view; +import io.rpg.Game; +import io.rpg.Initializer; +import io.rpg.config.model.GameObjectConfig; import io.rpg.model.data.KeyboardEvent; import io.rpg.model.data.LocationModelStateChange; +import io.rpg.model.location.LocationModel; +import io.rpg.model.object.GameObject; import io.rpg.viewmodel.LocationViewModel; import io.rpg.config.model.LocationConfig; import javafx.fxml.FXMLLoader; @@ -16,7 +21,10 @@ import java.io.IOException; import java.net.URL; import java.nio.file.Path; +import java.util.ArrayList; + import java.util.HashSet; +import java.util.List; import java.util.Set; public class LocationView extends Scene @@ -28,7 +36,7 @@ public class LocationView extends Scene private final Set onKeyPressedObservers; - private final LocationViewModel viewModel; + private static LocationViewModel viewModel; public LocationView(HBox root, LocationViewModel viewModel) { super(root); @@ -63,6 +71,11 @@ public static LocationView fromConfig(LocationConfig config) throws IOException System.out.println(config.getBackgroundPath()); view.getViewModel().setBackground(new Image(resolvePathToJFXFormat(config.getBackgroundPath()))); // todo: na podstawie configu ustawić pola korzystając z view modelu + List objectConfigs = config.getObjects(); + for(GameObjectConfig objectConfig : objectConfigs) { + GameObjectView goview = new GameObjectView(Path.of(objectConfig.getAssetPath()), objectConfig.getPosition()); + viewModel.addChild(goview); + } return view; } diff --git a/src/main/java/io/rpg/viewmodel/LocationViewModel.java b/src/main/java/io/rpg/viewmodel/LocationViewModel.java index 8b51c8e0..4f82f16f 100644 --- a/src/main/java/io/rpg/viewmodel/LocationViewModel.java +++ b/src/main/java/io/rpg/viewmodel/LocationViewModel.java @@ -1,5 +1,6 @@ package io.rpg.viewmodel; +import io.rpg.model.object.GameObject; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.image.Image; @@ -8,6 +9,7 @@ import javafx.scene.layout.Pane; import java.net.URL; +import java.util.List; import java.util.ResourceBundle; public class LocationViewModel implements Initializable { @@ -45,4 +47,8 @@ public void initialize(URL location, ResourceBundle resources) { mapImageView.setFitHeight(newImg.getHeight()); }); } + + public void addChild(ImageView child) { + parent.getChildren().add(child); + } } From e84ac81d9acc80c08a9bf8364b095783bb15a66f Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Apr 2022 14:31:37 +0200 Subject: [PATCH 04/12] fix: object display --- src/main/java/io/rpg/Initializer.java | 7 ++++++- src/main/java/io/rpg/controller/Controller.java | 15 +++++++++++++++ src/main/java/io/rpg/view/GameObjectView.java | 7 +++++-- src/main/java/io/rpg/view/LocationView.java | 8 +------- .../java/io/rpg/viewmodel/LocationViewModel.java | 2 +- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/rpg/Initializer.java b/src/main/java/io/rpg/Initializer.java index 77e325bc..9d1d2640 100644 --- a/src/main/java/io/rpg/Initializer.java +++ b/src/main/java/io/rpg/Initializer.java @@ -72,6 +72,10 @@ public Result initialize() { assert view != null; + gameObjectViews.forEach(view_ -> { + view.getViewModel().addChild(view_); + }); + if (locationConfig.getTag().equals(worldConfig.getRootLocation())) { controllerBuilder .setModel(model) @@ -82,7 +86,8 @@ public Result initialize() { controllerBuilder .addViewForTag(locationConfig.getTag(), view) - .addModelForTag(locationConfig.getTag(), model); + .addModelForTag(locationConfig.getTag(), model) + .registerToViews(gameObjectViews); } Game.Builder gameBuilder = new Game.Builder(); diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index a9732259..a378d58c 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -4,6 +4,7 @@ import io.rpg.model.data.MouseClickedEvent; import io.rpg.model.location.LocationModel; import io.rpg.util.Result; +import io.rpg.view.GameObjectView; import io.rpg.view.LocationView; import javafx.scene.Scene; import org.apache.logging.log4j.LogManager; @@ -11,6 +12,7 @@ import org.jetbrains.annotations.NotNull; import java.util.LinkedHashMap; +import java.util.List; public class Controller implements KeyboardEvent.Observer, MouseClickedEvent.Observer { private Scene currentView; @@ -50,6 +52,12 @@ public void setView(Scene currentView) { this.currentView = currentView; } + public void registerToViews(List views) { + for (GameObjectView view : views) { + view.addOnClickedObserver(this); + } + } + public Scene getView() { return currentView; } @@ -156,6 +164,13 @@ public Controller build() { return controller; } + public Builder registerToViews(List views) { + for (GameObjectView view : views) { + view.addOnClickedObserver(controller); + } + return this; + } + public Builder addViewForTag(String tag, LocationView view) { controller.getTagToLocationViewMap().put(tag, view); view.addKeyboardEventObserver(controller); diff --git a/src/main/java/io/rpg/view/GameObjectView.java b/src/main/java/io/rpg/view/GameObjectView.java index 0ee8ae55..dca3ad17 100644 --- a/src/main/java/io/rpg/view/GameObjectView.java +++ b/src/main/java/io/rpg/view/GameObjectView.java @@ -16,13 +16,15 @@ public class GameObjectView extends ImageView private Path path; private final Set onClickedObservers; + private final int SCALE = 32; + public GameObjectView(@NotNull Path assetPath, @NotNull Position position) { this.path = assetPath; // String xdpath = this.setImage(new Image(resolvePathToJFXFormat(path.toString()))); // todo: better position class - this.setX(position.col); - this.setY(position.row); + this.setX(position.col * SCALE); + this.setY(position.row * SCALE); this.onClickedObservers = new HashSet<>(); this.setOnMouseClicked(event -> emitOnMouseClickedEvent(new MouseClickedEvent(this, event))); } @@ -34,6 +36,7 @@ public static String resolvePathToJFXFormat(String path) { @Override public void emitOnMouseClickedEvent(MouseClickedEvent event) { + System.out.println("Object clicked"); onClickedObservers.forEach(listener -> listener.onMouseClickedEvent(event)); } diff --git a/src/main/java/io/rpg/view/LocationView.java b/src/main/java/io/rpg/view/LocationView.java index dfd643ba..6b033db0 100644 --- a/src/main/java/io/rpg/view/LocationView.java +++ b/src/main/java/io/rpg/view/LocationView.java @@ -36,7 +36,7 @@ public class LocationView extends Scene private final Set onKeyPressedObservers; - private static LocationViewModel viewModel; + private final LocationViewModel viewModel; public LocationView(HBox root, LocationViewModel viewModel) { super(root); @@ -70,12 +70,6 @@ public static LocationView fromConfig(LocationConfig config) throws IOException System.out.println("BACKGROUND PATH"); System.out.println(config.getBackgroundPath()); view.getViewModel().setBackground(new Image(resolvePathToJFXFormat(config.getBackgroundPath()))); - // todo: na podstawie configu ustawić pola korzystając z view modelu - List objectConfigs = config.getObjects(); - for(GameObjectConfig objectConfig : objectConfigs) { - GameObjectView goview = new GameObjectView(Path.of(objectConfig.getAssetPath()), objectConfig.getPosition()); - viewModel.addChild(goview); - } return view; } diff --git a/src/main/java/io/rpg/viewmodel/LocationViewModel.java b/src/main/java/io/rpg/viewmodel/LocationViewModel.java index 4f82f16f..32ca60c1 100644 --- a/src/main/java/io/rpg/viewmodel/LocationViewModel.java +++ b/src/main/java/io/rpg/viewmodel/LocationViewModel.java @@ -49,6 +49,6 @@ public void initialize(URL location, ResourceBundle resources) { } public void addChild(ImageView child) { - parent.getChildren().add(child); + contentPane.getChildren().add(child); } } From 16b9638527cb22e402ac8b4e5af57fe0226e130a Mon Sep 17 00:00:00 2001 From: Adam Przywieczerski <54894484+Monatyr@users.noreply.github.com> Date: Sun, 24 Apr 2022 14:50:19 +0200 Subject: [PATCH 05/12] feat: click to interact (#10) * feat: click to interact * Handling clicking on interactable objects * handling mouse clicks on interactive objects Co-authored-by: Kacper Kafara --- src/main/java/io/rpg/controller/Controller.java | 12 +++++++++++- .../java/io/rpg/model/location/LocationModel.java | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index a378d58c..d6a3536b 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -2,7 +2,10 @@ import io.rpg.model.data.KeyboardEvent; import io.rpg.model.data.MouseClickedEvent; +import io.rpg.model.data.Vector; import io.rpg.model.location.LocationModel; +import io.rpg.model.object.GameObject; +import io.rpg.model.object.InteractiveGameObject; import io.rpg.util.Result; import io.rpg.view.GameObjectView; import io.rpg.view.LocationView; @@ -113,7 +116,14 @@ private int getWindowCenterY() { @Override public void onMouseClickedEvent(MouseClickedEvent event) { - // TODO: implement event handling + Vector playerPos = currentModel.getPlayer().getPosition(); + GameObjectView objectView = event.source(); + GameObject object = currentModel.getObject((int) objectView.getY(), (int) objectView.getX()); + if (Math.abs(playerPos.x - objectView.getX()) <= 1.5 && Math.abs(playerPos.y) - objectView.getY() <= 1.5) { + if (object instanceof InteractiveGameObject) { + ((InteractiveGameObject) object).onAction(); + } + } logger.info("Controller notified on click from " + event.source()); } diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index d031c456..1b55aa8f 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -1,6 +1,7 @@ package io.rpg.model.location; import io.rpg.model.data.LocationModelStateChange; +import io.rpg.model.data.Position; import io.rpg.model.object.Player; import io.rpg.model.object.GameObject; import io.rpg.util.Result; @@ -39,6 +40,20 @@ public String getTag() { return tag; } + public Player getPlayer() { + return player; + } + + public GameObject getObject(int row, int column) { + GameObject object = gameObjects.stream().filter(gameObject -> gameObject.getPosition() + .equals(new Position(row, column))) + .findFirst().orElse(null); + if (object == null) { + throw new NullPointerException("No object found on (" + row + ", " + column + ")"); + } + return object; + } + /** * Private setter for Builder usage only. * From 6f5fc80c30848edf95fdf3f1f41a1fb26d20288d Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Apr 2022 15:11:28 +0200 Subject: [PATCH 06/12] feat: display player --- .../locations/location-1/location-1.json | 3 +- src/main/java/io/rpg/Initializer.java | 9 ++++ .../java/io/rpg/controller/Controller.java | 16 +++++++- src/main/java/io/rpg/model/data/Vector.java | 6 +++ src/main/java/io/rpg/model/object/Player.java | 21 +++++++--- .../java/io/rpg/torefact/GameToRefract.java | 41 ------------------- .../java/io/rpg/util/GameObjectFactory.java | 8 ++-- 7 files changed, 51 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/io/rpg/torefact/GameToRefract.java diff --git a/configurations/config-1/locations/location-1/location-1.json b/configurations/config-1/locations/location-1/location-1.json index 94025965..fafab0dd 100644 --- a/configurations/config-1/locations/location-1/location-1.json +++ b/configurations/config-1/locations/location-1/location-1.json @@ -2,7 +2,8 @@ "tag": "location-1", "objects": [ { "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible", "assetPath": "assets/someDude.png" }, - { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "dialog", "assetPath": "assets/someDude.png" } + { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "dialog", "assetPath": "assets/someDude.png" }, + { "tag": "player", "position": { "row": 2, "col": 4 }, "type": "player", "assetPath": "assets/stone.png" } ], "backgroundPath": "assets/map.png" } diff --git a/src/main/java/io/rpg/Initializer.java b/src/main/java/io/rpg/Initializer.java index 9d1d2640..14557ad0 100644 --- a/src/main/java/io/rpg/Initializer.java +++ b/src/main/java/io/rpg/Initializer.java @@ -7,6 +7,7 @@ import io.rpg.model.location.LocationModel; import io.rpg.model.object.GameObject; import io.rpg.config.model.GameObjectConfig; +import io.rpg.model.object.Player; import io.rpg.util.GameObjectFactory; import io.rpg.util.GameObjectViewFactory; import io.rpg.util.Result; @@ -62,6 +63,12 @@ public Result initialize() { List gameObjects = loadGameObjectsForLocation(locationConfig); List gameObjectViews = loadGameObjectViewsForLocation(locationConfig); + for (GameObject gameObject : gameObjects) { + if (gameObject instanceof Player) { + controllerBuilder.setPlayer((Player)gameObject); + } + } + registerGameObjectViewsToModel(gameObjects, gameObjectViews); LocationModel model = new LocationModel.Builder() @@ -82,6 +89,8 @@ public Result initialize() { .setView(view); } + + model.addOnLocationModelStateChangeObserver(view); controllerBuilder diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index d6a3536b..6b6ab2fb 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -6,6 +6,7 @@ import io.rpg.model.location.LocationModel; import io.rpg.model.object.GameObject; import io.rpg.model.object.InteractiveGameObject; +import io.rpg.model.object.Player; import io.rpg.util.Result; import io.rpg.view.GameObjectView; import io.rpg.view.LocationView; @@ -116,7 +117,7 @@ private int getWindowCenterY() { @Override public void onMouseClickedEvent(MouseClickedEvent event) { - Vector playerPos = currentModel.getPlayer().getPosition(); + Vector playerPos = currentModel.getPlayer().getPixelPosition(); GameObjectView objectView = event.source(); GameObject object = currentModel.getObject((int) objectView.getY(), (int) objectView.getX()); if (Math.abs(playerPos.x - objectView.getX()) <= 1.5 && Math.abs(playerPos.y) - objectView.getY() <= 1.5) { @@ -127,11 +128,17 @@ public void onMouseClickedEvent(MouseClickedEvent event) { logger.info("Controller notified on click from " + event.source()); } + private void setPlayer(Player gameObject) { + currentModel.setPlayer(gameObject); + } + public static class Builder { private final Controller controller; private boolean isViewSet = false; private boolean isModelSet = false; + private Player player; + public Builder() { controller = new Controller(); } @@ -167,10 +174,12 @@ public Builder setView(Scene currentView) { } public Controller build() { + controller.setPlayer(player); Result validationResult = controller.validate(); if (validationResult.isError()) { throw new IllegalStateException(validationResult.getErrorValue()); } + return controller; } @@ -191,5 +200,10 @@ public Builder addModelForTag(String tag, LocationModel model) { controller.getTagToLocationModelMap().put(tag, model); return this; } + + public Builder setPlayer(Player gameObject) { + player = gameObject; + return this; + } } } diff --git a/src/main/java/io/rpg/model/data/Vector.java b/src/main/java/io/rpg/model/data/Vector.java index 01e2b325..76473fb6 100644 --- a/src/main/java/io/rpg/model/data/Vector.java +++ b/src/main/java/io/rpg/model/data/Vector.java @@ -15,4 +15,10 @@ public Vector(float x, float y) { this.y = y; } + public Vector(Position position) { + // TODO THIS MOTHT + this.x = position.col * 32; + this.y = position.row * 32; + } + } diff --git a/src/main/java/io/rpg/model/object/Player.java b/src/main/java/io/rpg/model/object/Player.java index d1409b58..457c8087 100644 --- a/src/main/java/io/rpg/model/object/Player.java +++ b/src/main/java/io/rpg/model/object/Player.java @@ -1,8 +1,10 @@ package io.rpg.model.object; +import io.rpg.model.data.Position; import io.rpg.model.data.Vector; -import io.rpg.torefact.GameObject; +import io.rpg.model.object.GameObject; import javafx.scene.image.Image; +import org.jetbrains.annotations.NotNull; public class Player extends GameObject { @@ -14,15 +16,18 @@ public class Player extends GameObject { boolean upPressed; boolean downPressed; - public Player(Vector position, Image image) { - super(position, image); - speed = 5f; - direction = new Vector(0, 0); + private Vector pixelPosition; + + public Player(@NotNull String tag, @NotNull Position position) { + super(tag, position); + this.speed = 5f; + this.direction = new Vector(0, 0); this.rightPressed = false; this.leftPressed = false; this.upPressed = false; this.downPressed = false; this.strength = 0; + this.pixelPosition = new Vector(position); } public void updateStrength(int value) { @@ -33,6 +38,10 @@ public void setDirection(Vector direction) { this.direction = direction; } + public Vector getPixelPosition() { + return pixelPosition; + } + public void update(float elapsed) { float y = 0; float x = 0; @@ -49,7 +58,7 @@ public void update(float elapsed) { if (rightPressed) x += 1; - this.position = new Vector(this.position.x + speed * x * elapsed / 1000, this.position.y + speed * y * elapsed / 1000); + this.pixelPosition = new Vector(this.pixelPosition.x + speed * x * elapsed / 1000, this.pixelPosition.y + speed * y * elapsed / 1000); } public void setRightPressed(boolean rightPressed) { diff --git a/src/main/java/io/rpg/torefact/GameToRefract.java b/src/main/java/io/rpg/torefact/GameToRefract.java deleted file mode 100644 index e7a25564..00000000 --- a/src/main/java/io/rpg/torefact/GameToRefract.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.rpg.torefact; - -import io.rpg.model.object.Player; - -import java.util.ArrayList; - -public class GameToRefract { - private Player player; - // Timer - ArrayList gameObjects; - - public GameToRefract() { - this.gameObjects = new ArrayList<>(); - this.player = null; - } - - public void addGameObject(GameObject gameObject) throws Exception { - if (gameObject instanceof Player) { - if (player != null) - throw new Exception(); - player = (Player) gameObject; - } - gameObjects.add(gameObject); - } - - public GameObject getObject(int index) { - return gameObjects.get(index); - } - - public int getObjectCount() { - return gameObjects.size(); - } - - public Player getPlayer() { - return player; - } - - public void update(float elapsed) { - player.update(elapsed); - } -} diff --git a/src/main/java/io/rpg/util/GameObjectFactory.java b/src/main/java/io/rpg/util/GameObjectFactory.java index 48fd8f83..e30371cf 100644 --- a/src/main/java/io/rpg/util/GameObjectFactory.java +++ b/src/main/java/io/rpg/util/GameObjectFactory.java @@ -1,10 +1,9 @@ package io.rpg.util; import io.rpg.config.model.GameObjectConfig; -import io.rpg.model.object.CollectibleGameObject; -import io.rpg.model.object.DialogGameObject; -import io.rpg.model.object.GameObject; -import io.rpg.model.object.NavigationalGameObject; +import io.rpg.model.data.Vector; +import io.rpg.model.object.*; +import javafx.scene.image.Image; import java.util.LinkedList; import java.util.List; @@ -25,6 +24,7 @@ public static GameObject fromConfig(GameObjectConfig config) { switch (GameObject.Type.valueOf(config.getTypeString().toUpperCase())) { case COLLECTIBLE -> { return new CollectibleGameObject(config.getTag(), config.getPosition()); } case DIALOG -> { return new DialogGameObject(config.getTag(), config.getPosition()); } + case PLAYER -> { return new Player(config.getTag(), config.getPosition()); } case NAVIGABLE -> { return new NavigationalGameObject(config.getTag(), config.getPosition()); } default -> throw new RuntimeException("Unknown GameObject type. This should not happen!"); } From 462b9bb26a72cb232f18b4c29dcb8b39738eef59 Mon Sep 17 00:00:00 2001 From: co012 Date: Sun, 24 Apr 2022 18:08:10 +0200 Subject: [PATCH 07/12] chore: change asset (#21) --- assets/map.png | Bin 37340 -> 9380 bytes assets/map10x10.png | Bin 18631 -> 13138 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/map.png b/assets/map.png index 4df2990aeacfe80dbd2dbf8439bb15f7b8a8646e..fbad10276f7ea71b403f693e6630f180eb909512 100644 GIT binary patch literal 9380 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 bPqTQ`%A|19x)*4WzNN`Y^Am56UyAr&`1@8& diff --git a/assets/map10x10.png b/assets/map10x10.png index de67ef4ae4c1621fb560904af214fd5a6ce4db0f..e576b07badd61c94d0ffb00086f3c05a280b9659 100644 GIT binary patch literal 13138 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 Date: Mon, 25 Apr 2022 17:12:04 +0200 Subject: [PATCH 08/12] feat: add player configuration loading & extend object configuration (#22) --- .../locations/location-1/location-1.json | 3 +- .../location-1/objects/object-1.json | 10 +- .../location-1/objects/object-2.json | 7 +- .../location-2/objects/object-1.json | 10 +- .../location-2/objects/object-3.json | 10 +- configurations/config-1/root.json | 11 +- src/main/java/io/rpg/Initializer.java | 34 +++--- src/main/java/io/rpg/config/ConfigLoader.java | 109 ++++++++++++------ .../io/rpg/config/model/GameObjectConfig.java | 41 ++++++- .../io/rpg/config/model/GameWorldConfig.java | 29 +++-- .../io/rpg/config/model/LocationConfig.java | 12 +- .../io/rpg/config/model/PlayerConfig.java | 21 ++++ .../java/io/rpg/controller/Controller.java | 5 + src/main/java/io/rpg/model/data/Position.java | 5 + .../java/io/rpg/model/object/GameObject.java | 42 ++++++- .../java/io/rpg/model/object/GameObjects.java | 4 +- src/main/java/io/rpg/torefact/GameObject.java | 43 ------- .../io/rpg/viewmodel/LocationViewModel.java | 10 +- src/main/java/module-info.java | 1 - 19 files changed, 274 insertions(+), 133 deletions(-) create mode 100644 src/main/java/io/rpg/config/model/PlayerConfig.java delete mode 100644 src/main/java/io/rpg/torefact/GameObject.java diff --git a/configurations/config-1/locations/location-1/location-1.json b/configurations/config-1/locations/location-1/location-1.json index fafab0dd..94025965 100644 --- a/configurations/config-1/locations/location-1/location-1.json +++ b/configurations/config-1/locations/location-1/location-1.json @@ -2,8 +2,7 @@ "tag": "location-1", "objects": [ { "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible", "assetPath": "assets/someDude.png" }, - { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "dialog", "assetPath": "assets/someDude.png" }, - { "tag": "player", "position": { "row": 2, "col": 4 }, "type": "player", "assetPath": "assets/stone.png" } + { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "dialog", "assetPath": "assets/someDude.png" } ], "backgroundPath": "assets/map.png" } diff --git a/configurations/config-1/locations/location-1/objects/object-1.json b/configurations/config-1/locations/location-1/objects/object-1.json index 406fd2f4..785ee639 100644 --- a/configurations/config-1/locations/location-1/objects/object-1.json +++ b/configurations/config-1/locations/location-1/objects/object-1.json @@ -1,7 +1,9 @@ { "tag": "object-1", - "assetPath": "assets/stone.png", - "type": "", - "x": 150, - "y": 200 + "assetPath": "assets/someDude.png", + "type": "collectible", + "position": { + "row": 10, + "col": 10 + } } diff --git a/configurations/config-1/locations/location-1/objects/object-2.json b/configurations/config-1/locations/location-1/objects/object-2.json index ee8b8f05..fcfc9d28 100644 --- a/configurations/config-1/locations/location-1/objects/object-2.json +++ b/configurations/config-1/locations/location-1/objects/object-2.json @@ -1,7 +1,6 @@ { "tag": "object-2", "assetPath": "assets/stone.png", - "type": "", - "x": 50, - "y": 100 -} \ No newline at end of file + "type": "navigable", + "position": { "row": 11, "col": 3 } +} diff --git a/configurations/config-1/locations/location-2/objects/object-1.json b/configurations/config-1/locations/location-2/objects/object-1.json index 6f2ed3ae..6ce8ac86 100644 --- a/configurations/config-1/locations/location-2/objects/object-1.json +++ b/configurations/config-1/locations/location-2/objects/object-1.json @@ -1,5 +1,9 @@ { "tag": "object-1", - "assetPath": "/path/to/the/asset", - "type": "" -} \ No newline at end of file + "assetPath": "assets/stone.png", + "type": "dialog", + "position": { + "row": 1, + "col": 15 + } +} diff --git a/configurations/config-1/locations/location-2/objects/object-3.json b/configurations/config-1/locations/location-2/objects/object-3.json index 791023ce..5e11e7f7 100644 --- a/configurations/config-1/locations/location-2/objects/object-3.json +++ b/configurations/config-1/locations/location-2/objects/object-3.json @@ -1,5 +1,9 @@ { "tag": "object-3", - "assetPath": "/path/to/the/asset", - "type": "" -} \ No newline at end of file + "assetPath": "assets/someDudeButGreen.png", + "type": "collectible", + "position": { + "row": 7, + "col": 8 + } +} diff --git a/configurations/config-1/root.json b/configurations/config-1/root.json index 2f174211..1c2aad47 100644 --- a/configurations/config-1/root.json +++ b/configurations/config-1/root.json @@ -4,5 +4,12 @@ "location-1", "location-2" ], - "rootLocation": "location-1" -} \ No newline at end of file + "rootLocation": "location-1", + "player": { + "tag": "player", + "position": { "row": 4, "col": 5 }, + "type": "player", + "assetPath": "assets/stone.png", + "location": "location-1" + } +} diff --git a/src/main/java/io/rpg/Initializer.java b/src/main/java/io/rpg/Initializer.java index 14557ad0..1add120d 100644 --- a/src/main/java/io/rpg/Initializer.java +++ b/src/main/java/io/rpg/Initializer.java @@ -1,6 +1,7 @@ package io.rpg; import io.rpg.config.ConfigLoader; +import io.rpg.config.model.PlayerConfig; import io.rpg.controller.Controller; import io.rpg.config.model.GameWorldConfig; import io.rpg.config.model.LocationConfig; @@ -51,24 +52,18 @@ public Result initialize() { return Result.error(new RuntimeException("ConfigLoader fetched null GameWorldConfig")); } - GameWorldConfig worldConfig = gameWorldConfigLoadResult.getOkValue(); + GameWorldConfig gameWorldConfig = gameWorldConfigLoadResult.getOkValue(); Controller.Builder controllerBuilder = new Controller.Builder(); - assert worldConfig.getLocationConfigs() != null; - assert worldConfig.getLocationConfigs().size() > 0 : "There must be at least one location config specified"; + assert gameWorldConfig.getLocationConfigs() != null; + assert gameWorldConfig.getLocationConfigs().size() > 0 : "There must be at least one location config specified"; - for (LocationConfig locationConfig : worldConfig.getLocationConfigs()) { + for (LocationConfig locationConfig : gameWorldConfig.getLocationConfigs()) { List gameObjects = loadGameObjectsForLocation(locationConfig); List gameObjectViews = loadGameObjectViewsForLocation(locationConfig); - for (GameObject gameObject : gameObjects) { - if (gameObject instanceof Player) { - controllerBuilder.setPlayer((Player)gameObject); - } - } - registerGameObjectViewsToModel(gameObjects, gameObjectViews); LocationModel model = new LocationModel.Builder() @@ -83,14 +78,12 @@ public Result initialize() { view.getViewModel().addChild(view_); }); - if (locationConfig.getTag().equals(worldConfig.getRootLocation())) { + if (locationConfig.getTag().equals(gameWorldConfig.getRootLocation())) { controllerBuilder .setModel(model) .setView(view); } - - model.addOnLocationModelStateChangeObserver(view); controllerBuilder @@ -99,8 +92,21 @@ public Result initialize() { .registerToViews(gameObjectViews); } + // Player is created separately + // TODO: consider moving it to separate method + Player player = (Player) GameObjectFactory.fromConfig(gameWorldConfig.getPlayerConfig()); + GameObjectView playerView = GameObjectViewFactory.fromConfig(gameWorldConfig.getPlayerConfig()); + player.addGameObjectStateChangeObserver(playerView); + controllerBuilder.setPlayer(player); + + Controller controller = controllerBuilder.build(); + // TODO: this is a temporary solution + controller.setPlayerView(playerView); + + + Game.Builder gameBuilder = new Game.Builder(); - gameBuilder.setController(controllerBuilder.build()); + gameBuilder.setController(controller); return Result.ok(gameBuilder.build()); } diff --git a/src/main/java/io/rpg/config/ConfigLoader.java b/src/main/java/io/rpg/config/ConfigLoader.java index 6919cf26..5cffa492 100644 --- a/src/main/java/io/rpg/config/ConfigLoader.java +++ b/src/main/java/io/rpg/config/ConfigLoader.java @@ -31,22 +31,22 @@ public class ConfigLoader { * root.json file & locations directory */ @NotNull - private final Path pathToConfigDir; + private final Path configDirPath; /** - * This filed is initialized basing on {@link io.rpg.config.ConfigLoader#pathToConfigDir}. + * This filed is initialized basing on {@link io.rpg.config.ConfigLoader#configDirPath}. * It represents path to the root.json file which is entry point for {@link ConfigLoader} */ @NotNull - private final Path pathToRootFile; + private final Path rootFilePath; /** - * Similarly to {@link io.rpg.config.ConfigLoader#pathToRootFile} this field is initialized basing on - * {@link io.rpg.config.ConfigLoader#pathToConfigDir}. + * Similarly to {@link io.rpg.config.ConfigLoader#rootFilePath} this field is initialized basing on + * {@link io.rpg.config.ConfigLoader#configDirPath}. * It represents path to the directory that holds locations configuration files. */ @NotNull - private final Path pathToLocationsDir; + private final Path locationsDirPath; public static final String ERR_INVALID_CFG_DIR_PATH = "Could not resolve config directory." + " Make sure that the config dir path is correct"; @@ -70,15 +70,18 @@ public class ConfigLoader { * Creates {@link ConfigLoader} for configuration under configDirPath. * * @param configDirPath Path to the root directory. + * @throws IllegalArgumentException with appropriate error message when path to config directory + * path is invalid or configuration has invalid structure. + * */ public ConfigLoader(@NotNull String configDirPath) { logger = LogManager.getLogger(ConfigLoader.class); logger.info("Initializing"); - pathToConfigDir = Path.of(configDirPath); - pathToRootFile = pathToConfigDir.resolve(ConfigConstants.ROOT); - pathToLocationsDir = pathToConfigDir.resolve(ConfigConstants.LOCATIONS_DIR); + this.configDirPath = Path.of(configDirPath); + rootFilePath = this.configDirPath.resolve(ConfigConstants.ROOT); + locationsDirPath = this.configDirPath.resolve(ConfigConstants.LOCATIONS_DIR); gson = new Gson(); validate(); @@ -114,42 +117,71 @@ public Result load() { try { logger.info("Loading location config for tag: " + locationTag); - LocationConfig locationConfig = loadLocationConfig(locationTag); + Result locationConfigLoadingResult = loadLocationConfig(locationTag); + + if (locationConfigLoadingResult.isError()) { + return Result.error(locationConfigLoadingResult.getErrorValue()); + } else if (locationConfigLoadingResult.isOkValueNull()) { + return Result.error(new RuntimeException("Null LocationConfig returned for location with tag: " + locationTag)); + } - // todo: this should be called in loadLocationConfig method? - locationConfig.validate(); + LocationConfig locationConfig = locationConfigLoadingResult.getOkValue(); gameWorldConfig.addLocationConfig(locationConfig); logger.info("Location config loaded for tag: " + locationTag); + // locationConfig can not be null here, we checked this case earlier logger.info(locationConfig.toString()); - assert locationConfig.getPath() != null : "Path to location dir must be set in its loader"; Path objectsDir = locationConfig.getPath().resolve(ConfigConstants.OBJECTS_DIR); - for (GameObjectConfig gameObjectConfig : locationConfig.getObjects()) { - try { - gameObjectConfig.validate(); - } catch (Exception ex) { - String exceptionMessage = ex.getMessage(); - - logger.warn("Validation for game object config with tag: " - + gameObjectConfig.getTag() + " failed." - + (exceptionMessage != null ? "Reason: " + exceptionMessage : "No reason provided")); + // TODO: @kkafar: Load objects from inside objects directory + // TODO: consider extracting this code to method + if (Files.isDirectory(objectsDir)) { // there is directory with additional object configurations + for (GameObjectConfig gameObjectConfig : locationConfig.getObjects()) { + Path gameObjectConfigSpec = objectsDir.resolve(gameObjectConfig.getTag() + ".json"); // TODO + // there is additional spec for this game object + if (Files.isReadable(gameObjectConfigSpec)) { + logger.info("Detected additional spec for object with tag: " + gameObjectConfig.getTag()); + BufferedReader reader = new BufferedReader(new FileReader(gameObjectConfigSpec.toString())); + GameObjectConfig config = gson.fromJson(reader, GameObjectConfig.class); + gameObjectConfig.updateFrom(config); + } } + } - // TODO: @kkafar: Load objects inside objects directory + // game configs validation + // TODO: consider extracting this code to separate method + for (GameObjectConfig gameObjectConfig : locationConfig.getObjects()) { + Result result = gameObjectConfig.validate(); + + if (result.isError()) { + // TODO: consider returning loading error here + result.getErrorValueOpt().ifPresentOrElse(ex -> { + String exceptionMessage = ex.getMessage(); + logger.warn("Validation for game object config with tag: " + + gameObjectConfig.getTag() + " failed." + + (exceptionMessage != null ? "Reason: " + exceptionMessage : "No reason provided")); + }, + () -> { + logger.warn("Validation for game object config with tag: " + + gameObjectConfig.getTag() + " failed with null result."); + }); + } else { + logger.info("Loaded GameObjectConfig for tag: " + gameObjectConfig.getTag() + ":" + gameObjectConfig); + } } + } catch (FileNotFoundException e) { logger.warn("Failed to load location config for tag: " + locationTag); e.printStackTrace(); } } - Result validationResult = gameWorldConfig.validate(); + Result validationResult = gameWorldConfig.validate(); if (validationResult.isError()) { return Result.error(validationResult.getErrorValue()); } @@ -164,7 +196,7 @@ Result loadGameWorldConfig() { BufferedReader reader; try { - reader = new BufferedReader(new FileReader(pathToRootFile.toString())); + reader = new BufferedReader(new FileReader(rootFilePath.toString())); } catch (FileNotFoundException exception) { return Result.error(exception); } @@ -181,40 +213,45 @@ Result loadGameWorldConfig() { return configLoadResult; } - LocationConfig loadLocationConfig(@NotNull String locationTag) throws FileNotFoundException { + Result loadLocationConfig(@NotNull String locationTag) throws FileNotFoundException { logger.info("Loading location: " + locationTag); - Path locationDir = pathToLocationsDir.resolve(locationTag); + Path locationDir = locationsDirPath.resolve(locationTag); if (!Files.isDirectory(locationDir)) { logger.error(ERR_LOCATION_DIR_FNF_FOR_TAG + locationTag); - throw new FileNotFoundException(ERR_LOCATION_DIR_FNF_FOR_TAG + locationTag); + return Result.error(new FileNotFoundException(ERR_LOCATION_DIR_FNF_FOR_TAG + locationTag)); } Path locationConfigJson = locationDir.resolve(locationTag + ".json"); if (!Files.isReadable(locationConfigJson)) { logger.error(ERR_LOCATION_CFG_NR_FOR_TAG + locationTag); - throw new RuntimeException(ERR_LOCATION_DIR_FNF_FOR_TAG + locationTag); + return Result.error(new RuntimeException(ERR_LOCATION_DIR_FNF_FOR_TAG + locationTag)); } BufferedReader reader = new BufferedReader(new FileReader(locationConfigJson.toString())); LocationConfig config = gson.fromJson(reader, LocationConfig.class); - config.setPath(locationDir); - logger.info("Path to background for location"); - logger.info(config.getBackgroundPath()); - return config; + Result locationConfigValidationResult = + config.validate(); + + if (locationConfigValidationResult.isError()) { + return locationConfigValidationResult; + } else { + config.setPath(locationDir); + return Result.ok(config); + } } private void validate() { - if (!Files.isDirectory(pathToConfigDir)) { + if (!Files.isDirectory(configDirPath)) { logger.error(ERR_INVALID_CFG_DIR_PATH); throw new IllegalArgumentException(ERR_INVALID_CFG_DIR_PATH); - } else if (!Files.isReadable(pathToRootFile)) { + } else if (!Files.isReadable(rootFilePath)) { logger.error(ERR_ROOT_FNF); throw new IllegalArgumentException(ERR_ROOT_FNF); - } else if (!Files.isDirectory(pathToLocationsDir)) { + } else if (!Files.isDirectory(locationsDirPath)) { logger.error(ERR_LOCATIONS_DIR_FNF); throw new IllegalArgumentException(ERR_LOCATIONS_DIR_FNF); } diff --git a/src/main/java/io/rpg/config/model/GameObjectConfig.java b/src/main/java/io/rpg/config/model/GameObjectConfig.java index 10f83ea4..6fb2499a 100644 --- a/src/main/java/io/rpg/config/model/GameObjectConfig.java +++ b/src/main/java/io/rpg/config/model/GameObjectConfig.java @@ -6,6 +6,9 @@ import io.rpg.util.Result; import org.jetbrains.annotations.NotNull; +import java.lang.reflect.Field; +import java.util.Optional; + /** * Represents {@link io.rpg.model.object.GameObject} configuration provided by user * in configuration files. @@ -28,10 +31,46 @@ public String getTypeString() { * * @return Object in valid state or exception. */ - public Result validate() { + public Result validate() { if (!GameObjects.isValidType(type)) { return Result.error(new IllegalStateException("Invalid object type: " + type)); } return Result.ok(this); } + + public void updateFrom(GameObjectConfig gameObjectConfig) { + if (gameObjectConfig.getPosition() != null) { + this.position = gameObjectConfig.getPosition(); + } + if (gameObjectConfig.getTypeString() != null) { + this.type = gameObjectConfig.getTypeString(); + } + if (gameObjectConfig.getAssetPath() != null) { + this.assetPath = gameObjectConfig.assetPath; + } + } + + public String getFieldDescription() { + StringBuilder builder = new StringBuilder(); + for (Field field : GameObjectConfig.class.getDeclaredFields()) { + try { + Optional fieldValue = Optional.ofNullable(field.get(this)); + fieldValue.ifPresent(_fieldValue -> builder.append('\t') + .append(field.getName()) + .append(": ") + .append(_fieldValue) + .append(",\n") + ); + } catch (IllegalAccessException ignored) { /* noop */ } + } + return builder.toString(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("\n{\n").append(super.getFieldDescription()).append(getFieldDescription()); + return builder.append("}").toString(); + } + } diff --git a/src/main/java/io/rpg/config/model/GameWorldConfig.java b/src/main/java/io/rpg/config/model/GameWorldConfig.java index ede8ed45..7b77611a 100644 --- a/src/main/java/io/rpg/config/model/GameWorldConfig.java +++ b/src/main/java/io/rpg/config/model/GameWorldConfig.java @@ -1,5 +1,6 @@ package io.rpg.config.model; +import com.google.gson.annotations.SerializedName; import io.rpg.util.Result; import java.util.ArrayList; @@ -27,6 +28,12 @@ public class GameWorldConfig { */ private ArrayList locationConfigs; + /** + * Configuration for the player object. + */ + @SerializedName("player") + private PlayerConfig playerConfig; + private GameWorldConfig() { locationTags = new ArrayList<>(); locationConfigs = new ArrayList<>(); @@ -68,6 +75,13 @@ public String getRootLocation() { return rootLocation; } + /** + * @return configuration for the player + */ + public PlayerConfig getPlayerConfig() { + return playerConfig; + } + @Override public String toString() { StringBuilder builder = new StringBuilder(); @@ -95,6 +109,10 @@ public Result validateStageOne() { return Result.error(new IllegalStateException("No location tags detected")); } else if (tag == null) { return Result.error(new IllegalStateException("Null tag")); + } else if (playerConfig == null) { + return Result.error(new IllegalStateException("No player config provided")); + } else if (rootLocation == null) { + return Result.error(new IllegalStateException("No root location set!")); } else { return Result.ok(this); } @@ -105,15 +123,12 @@ public Result validateStageOne() { * * @return Object with valid state or exception. */ - public Result validate() { - if (locationTags.size() < 1) { - return Result.error(new IllegalStateException("No location tags detected")); + public Result validate() { + Result stageOneValidationResult = validateStageOne(); + if (stageOneValidationResult.isError()) { + return stageOneValidationResult; } else if (locationConfigs.size() < 1) { return Result.error(new IllegalStateException("No location configs loaded")); - } else if (tag == null) { - return Result.error(new IllegalStateException("Null tag")); - } else if (rootLocation == null) { - return Result.error(new IllegalStateException("No root location set!")); } else { return Result.ok(this); } diff --git a/src/main/java/io/rpg/config/model/LocationConfig.java b/src/main/java/io/rpg/config/model/LocationConfig.java index 68e32dda..f8180b2f 100644 --- a/src/main/java/io/rpg/config/model/LocationConfig.java +++ b/src/main/java/io/rpg/config/model/LocationConfig.java @@ -1,6 +1,7 @@ package io.rpg.config.model; +import io.rpg.util.Result; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,7 +52,14 @@ public void setPath(@NotNull Path path) { this.path = path; } - public void validate() { - + public Result validate() { + if (tag == null) { + return Result.error(new IllegalStateException("Null tag")); + } else if (backgroundPath == null || backgroundPath.isBlank()) { + // TODO: Validate the backgroundPath here + return Result.error(new IllegalStateException("Empty string as background path")); + } else { + return Result.ok(this); + } } } diff --git a/src/main/java/io/rpg/config/model/PlayerConfig.java b/src/main/java/io/rpg/config/model/PlayerConfig.java new file mode 100644 index 00000000..bd66d072 --- /dev/null +++ b/src/main/java/io/rpg/config/model/PlayerConfig.java @@ -0,0 +1,21 @@ +package io.rpg.config.model; + +import com.google.gson.annotations.SerializedName; +import io.rpg.model.data.Position; +import org.jetbrains.annotations.NotNull; + +/** + * Represents player configuration. + */ +public class PlayerConfig extends GameObjectConfig { + @SerializedName("location") + private String initialLocationTag; + + public PlayerConfig(@NotNull String tag, @NotNull Position position) { + super(tag, position); + } + + public String getInitialLocationTag() { + return initialLocationTag; + } +} diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index 6b6ab2fb..d269f70b 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -132,6 +132,11 @@ private void setPlayer(Player gameObject) { currentModel.setPlayer(gameObject); } + // TODO: temporary solution + public void setPlayerView(GameObjectView playerView) { + ((LocationView) currentView).getViewModel().addChild(playerView); + } + public static class Builder { private final Controller controller; private boolean isViewSet = false; diff --git a/src/main/java/io/rpg/model/data/Position.java b/src/main/java/io/rpg/model/data/Position.java index 347715dd..276655a3 100644 --- a/src/main/java/io/rpg/model/data/Position.java +++ b/src/main/java/io/rpg/model/data/Position.java @@ -36,6 +36,11 @@ public boolean equals(Object obj) { } } + @Override + public String toString() { + return "{ row: " + row + ", col: " + col + " }"; + } + @Override public int hashCode() { return Objects.hash(row, col); diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index 5cbafade..f8a4eddb 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -4,8 +4,11 @@ import io.rpg.model.data.GameObjectStateChange; import io.rpg.model.data.Position; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.lang.reflect.Field; import java.util.LinkedHashSet; +import java.util.Optional; import java.util.Set; /** @@ -16,11 +19,12 @@ public class GameObject implements GameObjectStateChange.Emitter { /** * Position of game object in model's representation of location. */ - @NotNull - private final Position position; + @Nullable + protected Position position; /** * Unique identifier of this game object. + * This value is set in location */ @NotNull private final String tag; @@ -28,13 +32,13 @@ public class GameObject implements GameObjectStateChange.Emitter { /** * */ - @NotNull - private String assetPath; + @Nullable + protected String assetPath; @NotNull private final Set stateChangeObservers; - @NotNull + @Nullable public String getAssetPath() { return assetPath; } @@ -49,8 +53,10 @@ public String getTag() { /** * Position of game object in model's representation of location. + * + * @return initial position on object in the model (on the grid) */ - @NotNull + @Nullable public Position getPosition() { return position; } @@ -82,6 +88,30 @@ public void removeGameObjectStateChangeObserver(GameObjectStateChange.Observer o this.stateChangeObservers.remove(observer); } + public String getFieldDescription() { + StringBuilder builder = new StringBuilder(); + for (Field field : GameObject.class.getDeclaredFields()) { + try { + Optional fieldValue = Optional.ofNullable(field.get(this)); + fieldValue.ifPresent(_fieldValue -> builder.append('\t') + .append(field.getName()) + .append(": ") + .append(_fieldValue) + .append(",\n") + ); + } catch (IllegalAccessException ignored) { /* noop */ } + } + return builder.toString(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("\n{\n"); + builder.append(getFieldDescription()); + return builder.append("}").toString(); + } + public enum Type { NAVIGABLE("navigable"), DIALOG("dialog"), diff --git a/src/main/java/io/rpg/model/object/GameObjects.java b/src/main/java/io/rpg/model/object/GameObjects.java index b513fce7..0f8af974 100644 --- a/src/main/java/io/rpg/model/object/GameObjects.java +++ b/src/main/java/io/rpg/model/object/GameObjects.java @@ -3,13 +3,13 @@ import org.jetbrains.annotations.Nullable; import java.util.Set; -import java.util.concurrent.Executors; +// TODO: refactor way of validating {@link GameObject.Type} public class GameObjects { // this class is mean to only provide static methods private GameObjects() {} - public static Set VALID_TYPES = Set.of("interactive", "navigable"); + public static Set VALID_TYPES = Set.of("navigable", "dialog", "collectible", "player"); public static boolean isValidType(@Nullable String type) { return type != null && VALID_TYPES.contains(type); diff --git a/src/main/java/io/rpg/torefact/GameObject.java b/src/main/java/io/rpg/torefact/GameObject.java deleted file mode 100644 index 893b6887..00000000 --- a/src/main/java/io/rpg/torefact/GameObject.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.rpg.torefact; - -import io.rpg.model.data.Vector; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; - -/** - * A Temporary Class waiting to be replaced with GameObject class from branch RPG-79 - */ -public class GameObject { - - // private Pair position; - protected Vector position; - private Image image; - // control that displays objects - private ImageView imageView; - - public GameObject(Vector position, Image image) { - this.position = position; - this.image = image; - } - - public Vector getPosition() { - return position; - } - - public Image getImage() { - return image; - } - - public void setImage(Image image) { - this.image = image; - } - - public ImageView getImageView() { - return imageView; - } - - public void setImageView(ImageView imageView) { - this.imageView = imageView; - } - -} diff --git a/src/main/java/io/rpg/viewmodel/LocationViewModel.java b/src/main/java/io/rpg/viewmodel/LocationViewModel.java index 32ca60c1..98af8df8 100644 --- a/src/main/java/io/rpg/viewmodel/LocationViewModel.java +++ b/src/main/java/io/rpg/viewmodel/LocationViewModel.java @@ -7,6 +7,8 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.net.URL; import java.util.List; @@ -20,8 +22,10 @@ public class LocationViewModel implements Initializable { @FXML private HBox parent; - public LocationViewModel() { + private final Logger logger; + public LocationViewModel() { + logger = LogManager.getLogger(LocationViewModel.class); } public void setBackground(Image background) { @@ -34,9 +38,9 @@ public HBox getParent() { @Override public void initialize(URL location, ResourceBundle resources) { - System.out.println("INITIALIZE"); + logger.info("Initializing LocationViewModel"); mapImageView.imageProperty().addListener((property, oldImg, newImg) -> { - System.out.println("Map image view changing"); + logger.info("mapImageView modified"); contentPane.setPrefWidth(newImg.getWidth()); contentPane.setPrefHeight(newImg.getHeight()); diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index d8bcfddd..b6cc828d 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -18,7 +18,6 @@ opens io.rpg.model.data to com.google.gson; opens io.rpg.viewmodel to javafx.fxml; - opens io.rpg.torefact to com.google.gson; opens io.rpg.config.model to com.google.gson; exports io.rpg; From 0df6580003ceae3561b6d4e3768738a7bb5cf85d Mon Sep 17 00:00:00 2001 From: Adam Przywieczerski <54894484+Monatyr@users.noreply.github.com> Date: Tue, 26 Apr 2022 00:26:51 +0200 Subject: [PATCH 09/12] fix: click to interact * feat: click to interact * Handling clicking on interactable objects * handling mouse clicks on interactive objects * fix: coordinates of mouse click to object position on map * Update src/main/java/io/rpg/controller/Controller.java Co-authored-by: Kacper Kafara Co-authored-by: Kacper Kafara --- src/main/java/io/rpg/controller/Controller.java | 4 ++-- src/main/java/io/rpg/model/object/CollectibleGameObject.java | 2 +- src/main/java/io/rpg/model/object/DialogGameObject.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index d269f70b..afb327c2 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -119,8 +119,8 @@ private int getWindowCenterY() { public void onMouseClickedEvent(MouseClickedEvent event) { Vector playerPos = currentModel.getPlayer().getPixelPosition(); GameObjectView objectView = event.source(); - GameObject object = currentModel.getObject((int) objectView.getY(), (int) objectView.getX()); - if (Math.abs(playerPos.x - objectView.getX()) <= 1.5 && Math.abs(playerPos.y) - objectView.getY() <= 1.5) { + GameObject object = currentModel.getObject((int) objectView.getY() / 32, (int) objectView.getX() / 32); + if (Math.abs(playerPos.x - objectView.getX()) / 32 <= 1.5 && Math.abs(playerPos.y - objectView.getY()) / 32 <= 1.5) { if (object instanceof InteractiveGameObject) { ((InteractiveGameObject) object).onAction(); } diff --git a/src/main/java/io/rpg/model/object/CollectibleGameObject.java b/src/main/java/io/rpg/model/object/CollectibleGameObject.java index 3884f2e1..f00bf2e5 100644 --- a/src/main/java/io/rpg/model/object/CollectibleGameObject.java +++ b/src/main/java/io/rpg/model/object/CollectibleGameObject.java @@ -10,6 +10,6 @@ public CollectibleGameObject(@NotNull String tag, @NotNull Position position) { @Override public void onAction() { - + System.out.println("Collectible object action"); } } diff --git a/src/main/java/io/rpg/model/object/DialogGameObject.java b/src/main/java/io/rpg/model/object/DialogGameObject.java index ebcbc838..83f77c31 100644 --- a/src/main/java/io/rpg/model/object/DialogGameObject.java +++ b/src/main/java/io/rpg/model/object/DialogGameObject.java @@ -10,6 +10,6 @@ public DialogGameObject(@NotNull String tag, @NotNull Position position) { @Override public void onAction() { - + System.out.println("Dialogue object action"); } } From 9e24e4d34bda86c40520997df028b71b099ed3a0 Mon Sep 17 00:00:00 2001 From: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> Date: Tue, 26 Apr 2022 10:14:28 +0200 Subject: [PATCH 10/12] Visual changes for demo 1 (#24) * chore: Design location for demo 1.0 * feat: Open pointsPopup when CollectibleGameObject is selected --- assets/chest.png | Bin 0 -> 35881 bytes assets/diamond.png | Bin 0 -> 600 bytes assets/key.png | Bin 0 -> 684 bytes assets/knight.png | Bin 0 -> 69630 bytes assets/zombie.png | Bin 0 -> 65253 bytes .../locations/location-1/location-1.json | 11 +++++++++++ configurations/demo-config-1/root.json | 14 ++++++++++++++ src/main/java/io/rpg/Main.java | 2 +- src/main/java/io/rpg/controller/Controller.java | 11 +++++++++-- src/main/java/io/rpg/model/data/Vector.java | 5 +++-- src/main/java/io/rpg/view/GameObjectView.java | 7 ++++++- 11 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 assets/chest.png create mode 100644 assets/diamond.png create mode 100644 assets/key.png create mode 100644 assets/knight.png create mode 100644 assets/zombie.png create mode 100644 configurations/demo-config-1/locations/location-1/location-1.json create mode 100644 configurations/demo-config-1/root.json diff --git a/assets/chest.png b/assets/chest.png new file mode 100644 index 0000000000000000000000000000000000000000..4b462c0bd1541e40adea01d69bb266b028125e52 GIT binary patch literal 35881 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

|oaOkdQ7K;*8NJ6)X4OfG4$v(u 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 z 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 J72+l#{|6zwjWPfL literal 0 HcmV?d00001 diff --git a/configurations/demo-config-1/locations/location-1/location-1.json b/configurations/demo-config-1/locations/location-1/location-1.json new file mode 100644 index 00000000..5337de5d --- /dev/null +++ b/configurations/demo-config-1/locations/location-1/location-1.json @@ -0,0 +1,11 @@ +{ + "tag": "location-1", + "objects": [ + { "tag": "object-1", "position": { "row": 1, "col": 8 }, "type": "collectible", "assetPath": "assets/diamond.png" }, + { "tag": "object-2", "position": { "row": 6, "col": 3 }, "type": "collectible", "assetPath": "assets/key.png" }, + { "tag": "object-3", "position": { "row": 1, "col": 1 }, "type": "dialog", "assetPath": "assets/zombie.png" }, + { "tag": "object-4", "position": { "row": 3, "col": 2 }, "type": "dialog", "assetPath": "assets/zombie.png" }, + { "tag": "object-5", "position": { "row": 8, "col": 8 }, "type": "dialog", "assetPath": "assets/chest.png" } + ], + "backgroundPath": "assets/map.png" +} diff --git a/configurations/demo-config-1/root.json b/configurations/demo-config-1/root.json new file mode 100644 index 00000000..a1a906e8 --- /dev/null +++ b/configurations/demo-config-1/root.json @@ -0,0 +1,14 @@ +{ + "tag": "GameByConfig1", + "locationTags": [ + "location-1" + ], + "rootLocation": "location-1", + "player": { + "tag": "player", + "position": { "row": 4, "col": 5 }, + "type": "player", + "assetPath": "assets/knight.png", + "location": "location-1" + } +} diff --git a/src/main/java/io/rpg/Main.java b/src/main/java/io/rpg/Main.java index d41e5106..b2e9ebbc 100644 --- a/src/main/java/io/rpg/Main.java +++ b/src/main/java/io/rpg/Main.java @@ -16,7 +16,7 @@ public void start(Stage stage) throws IOException { Configurator.setRootLevel(Level.DEBUG); Logger logger = LogManager.getLogger(Main.class); - Initializer worldInitializer = new Initializer("configurations/config-1", stage); + Initializer worldInitializer = new Initializer("configurations/demo-config-1", stage); Result initializationResult = worldInitializer.initialize(); if (initializationResult.isError()) { diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index afb327c2..2e5264ab 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -4,6 +4,7 @@ import io.rpg.model.data.MouseClickedEvent; import io.rpg.model.data.Vector; import io.rpg.model.location.LocationModel; +import io.rpg.model.object.CollectibleGameObject; import io.rpg.model.object.GameObject; import io.rpg.model.object.InteractiveGameObject; import io.rpg.model.object.Player; @@ -117,13 +118,19 @@ private int getWindowCenterY() { @Override public void onMouseClickedEvent(MouseClickedEvent event) { + int SCALE = 64; Vector playerPos = currentModel.getPlayer().getPixelPosition(); GameObjectView objectView = event.source(); - GameObject object = currentModel.getObject((int) objectView.getY() / 32, (int) objectView.getX() / 32); - if (Math.abs(playerPos.x - objectView.getX()) / 32 <= 1.5 && Math.abs(playerPos.y - objectView.getY()) / 32 <= 1.5) { + GameObject object = currentModel.getObject((int) objectView.getY() / SCALE, (int) objectView.getX() / SCALE); + if (Math.abs(playerPos.x - objectView.getX()) / SCALE <= 1.5 && Math.abs(playerPos.y - objectView.getY()) / SCALE <= 1.5) { if (object instanceof InteractiveGameObject) { ((InteractiveGameObject) object).onAction(); } + + if (object instanceof CollectibleGameObject) { + popupController.openPointsPopup(5, getWindowCenterX(), getWindowCenterY()); + objectView.setVisible(false); + } } logger.info("Controller notified on click from " + event.source()); } diff --git a/src/main/java/io/rpg/model/data/Vector.java b/src/main/java/io/rpg/model/data/Vector.java index 76473fb6..4bfdc61a 100644 --- a/src/main/java/io/rpg/model/data/Vector.java +++ b/src/main/java/io/rpg/model/data/Vector.java @@ -17,8 +17,9 @@ public Vector(float x, float y) { public Vector(Position position) { // TODO THIS MOTHT - this.x = position.col * 32; - this.y = position.row * 32; + int SCALE = 64; + this.x = position.col * SCALE; + this.y = position.row * SCALE; } } diff --git a/src/main/java/io/rpg/view/GameObjectView.java b/src/main/java/io/rpg/view/GameObjectView.java index dca3ad17..2da8b341 100644 --- a/src/main/java/io/rpg/view/GameObjectView.java +++ b/src/main/java/io/rpg/view/GameObjectView.java @@ -16,7 +16,7 @@ public class GameObjectView extends ImageView private Path path; private final Set onClickedObservers; - private final int SCALE = 32; + private final int SCALE = 64; public GameObjectView(@NotNull Path assetPath, @NotNull Position position) { this.path = assetPath; @@ -25,6 +25,11 @@ public GameObjectView(@NotNull Path assetPath, @NotNull Position position) { // todo: better position class this.setX(position.col * SCALE); this.setY(position.row * SCALE); + + this.setPreserveRatio(true); + this.setSmooth(false); + this.setFitHeight(SCALE); + this.onClickedObservers = new HashSet<>(); this.setOnMouseClicked(event -> emitOnMouseClickedEvent(new MouseClickedEvent(this, event))); } From 6f3ba77467d126b7237e8d048196c399b00fda39 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Tue, 26 Apr 2022 10:29:08 +0200 Subject: [PATCH 11/12] feat: player movement (#25) * done movement * feat: Made player movement work. Desperately needs refactoring. Co-authored-by: Zamojtel Bartek Co-authored-by: mhawryluk --- src/main/java/io/rpg/Game.java | 4 +++ src/main/java/io/rpg/Initializer.java | 5 ++-- src/main/java/io/rpg/Main.java | 24 +++++++++++++++++ .../java/io/rpg/controller/Controller.java | 24 +++++++++++++++-- .../io/rpg/model/location/LocationModel.java | 18 ++++++++++--- .../java/io/rpg/model/object/GameObject.java | 8 ++++++ src/main/java/io/rpg/model/object/Player.java | 27 ++++++++++++++++--- .../java/io/rpg/util/GameObjectFactory.java | 2 +- src/main/java/io/rpg/view/LocationView.java | 13 +++++++++ .../io/rpg/viewmodel/LocationViewModel.java | 4 +++ 10 files changed, 116 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/rpg/Game.java b/src/main/java/io/rpg/Game.java index ecd9f532..14f5dd67 100644 --- a/src/main/java/io/rpg/Game.java +++ b/src/main/java/io/rpg/Game.java @@ -41,4 +41,8 @@ public Builder setController(Controller controller) { return this; } } + + public Controller getController() { + return controller; + } } diff --git a/src/main/java/io/rpg/Initializer.java b/src/main/java/io/rpg/Initializer.java index 1add120d..2886a802 100644 --- a/src/main/java/io/rpg/Initializer.java +++ b/src/main/java/io/rpg/Initializer.java @@ -90,6 +90,8 @@ public Result initialize() { .addViewForTag(locationConfig.getTag(), view) .addModelForTag(locationConfig.getTag(), model) .registerToViews(gameObjectViews); + + view.createViewsForObjects(model); } // Player is created separately @@ -98,13 +100,12 @@ public Result initialize() { GameObjectView playerView = GameObjectViewFactory.fromConfig(gameWorldConfig.getPlayerConfig()); player.addGameObjectStateChangeObserver(playerView); controllerBuilder.setPlayer(player); + player.setGameObjectView(playerView); Controller controller = controllerBuilder.build(); // TODO: this is a temporary solution controller.setPlayerView(playerView); - - Game.Builder gameBuilder = new Game.Builder(); gameBuilder.setController(controller); diff --git a/src/main/java/io/rpg/Main.java b/src/main/java/io/rpg/Main.java index b2e9ebbc..eba5a09e 100644 --- a/src/main/java/io/rpg/Main.java +++ b/src/main/java/io/rpg/Main.java @@ -1,6 +1,8 @@ package io.rpg; +import io.rpg.model.object.Player; import io.rpg.util.Result; +import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.stage.Stage; import org.apache.logging.log4j.Level; @@ -40,6 +42,28 @@ public void start(Stage stage) throws IOException { stage.setScene(game.getWorldView()); stage.show(); + + AnimationTimer animationTimer=new AnimationTimer() { + long lastUpdate=-1; + @Override + public void handle(long now) { + if(lastUpdate!=-1){ + float difference=(now-lastUpdate)/1e6f; + + game.getController().getCurrentModel().update(difference); +// locationModel.update(difference); + Player player=game.getController().getCurrentModel().getPlayer(); + if(player!=null){ +// game.getController().getCurrentModel().getPlayer().render(); + player.render(); + } + } + lastUpdate=now; + } + }; + + animationTimer.start(); + } public static void main(String[] args) { diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index 2e5264ab..2d706202 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -12,6 +12,7 @@ import io.rpg.view.GameObjectView; import io.rpg.view.LocationView; import javafx.scene.Scene; +import javafx.scene.input.KeyEvent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -102,9 +103,25 @@ else if (currentModel == null) public void onKeyboardEvent(KeyboardEvent event) { // TODO: implement event handling logger.info("Controller notified on key pressed from " + event.source()); + //TODO: call Player::set...Pressed depending on keyCode and whether the key was pressed or released - switch (event.payload().getCode()) { - case F -> popupController.openPointsPopup(5, getWindowCenterX(), getWindowCenterY()); + KeyEvent payload = event.payload(); + + if (payload.getEventType() == KeyEvent.KEY_PRESSED){ + switch (payload.getCode()) { + case F -> popupController.openPointsPopup(5, getWindowCenterX(), getWindowCenterY()); + case A -> currentModel.getPlayer().setLeftPressed(true); + case D -> currentModel.getPlayer().setRightPressed(true); + case S -> currentModel.getPlayer().setDownPressed(true); + case W -> currentModel.getPlayer().setUpPressed(true); + } + } else if (payload.getEventType() == KeyEvent.KEY_RELEASED) { + switch (payload.getCode()) { + case A -> currentModel.getPlayer().setLeftPressed(false); + case D -> currentModel.getPlayer().setRightPressed(false); + case S -> currentModel.getPlayer().setDownPressed(false); + case W -> currentModel.getPlayer().setUpPressed(false); + } } } @@ -218,4 +235,7 @@ public Builder setPlayer(Player gameObject) { return this; } } + public LocationModel getCurrentModel() { + return currentModel; + } } diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 1b55aa8f..97b227eb 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -63,10 +63,10 @@ private void setTag(String tag) { this.tag = tag; } - @UnmodifiableView - public List getGameObjects() { - return Collections.unmodifiableList(gameObjects); - } +// @UnmodifiableView +// public List getGameObjects() { +// return Collections.unmodifiableList(gameObjects); +// } /** * Private setter for Builder usage only. Notice that ownership of {@link GameObject}s is not @@ -135,4 +135,14 @@ public LocationModel build() { return locationModel; } } + public List getGameObjects() { + return gameObjects; + } + + public void update(float elapsed){ + if(player!=null){ + player.update(elapsed); + } + } + } diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index f8a4eddb..315f58d9 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -3,6 +3,9 @@ import io.rpg.config.model.GameObjectConfig; import io.rpg.model.data.GameObjectStateChange; import io.rpg.model.data.Position; +import io.rpg.model.data.Vector; +import io.rpg.view.GameObjectView; +import javafx.scene.image.ImageView; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,6 +19,11 @@ * objects appearing in the game. */ public class GameObject implements GameObjectStateChange.Emitter { + +// protected Vector currentPosition; + +// public GameObjectView view; + /** * Position of game object in model's representation of location. */ diff --git a/src/main/java/io/rpg/model/object/Player.java b/src/main/java/io/rpg/model/object/Player.java index 457c8087..4ef5acc7 100644 --- a/src/main/java/io/rpg/model/object/Player.java +++ b/src/main/java/io/rpg/model/object/Player.java @@ -2,12 +2,14 @@ import io.rpg.model.data.Position; import io.rpg.model.data.Vector; +import io.rpg.view.GameObjectView; import io.rpg.model.object.GameObject; import javafx.scene.image.Image; import org.jetbrains.annotations.NotNull; public class Player extends GameObject { + Vector currentPosition; int strength; float speed; Vector direction; @@ -15,12 +17,18 @@ public class Player extends GameObject { boolean leftPressed; boolean upPressed; boolean downPressed; - + GameObjectView gameObjectView; private Vector pixelPosition; - public Player(@NotNull String tag, @NotNull Position position) { - super(tag, position); - this.speed = 5f; + // public GameObject(@NotNull String tag, @NotNull Position position, @NotNull String assetPath) { +// this.tag = tag; +// this.position = position; +// this.assetPath = assetPath; +// } + public Player(@NotNull String tag, @NotNull Position position, @NotNull String assetPath) { + super(tag, position, assetPath); + this.currentPosition=new Vector(position.col, position.row); + this.speed = 100f; this.direction = new Vector(0, 0); this.rightPressed = false; this.leftPressed = false; @@ -80,4 +88,15 @@ public void setDownPressed(boolean downPressed) { public void setStrength(int strength) { this.strength = strength; } + + public void setGameObjectView(GameObjectView gameObjectView) { + this.gameObjectView = gameObjectView; + } + + public void render(){ + if(gameObjectView!=null){ + gameObjectView.setX(this.pixelPosition.x); + gameObjectView.setY(this.pixelPosition.y); + } + } } diff --git a/src/main/java/io/rpg/util/GameObjectFactory.java b/src/main/java/io/rpg/util/GameObjectFactory.java index e30371cf..2fd84ead 100644 --- a/src/main/java/io/rpg/util/GameObjectFactory.java +++ b/src/main/java/io/rpg/util/GameObjectFactory.java @@ -24,7 +24,7 @@ public static GameObject fromConfig(GameObjectConfig config) { switch (GameObject.Type.valueOf(config.getTypeString().toUpperCase())) { case COLLECTIBLE -> { return new CollectibleGameObject(config.getTag(), config.getPosition()); } case DIALOG -> { return new DialogGameObject(config.getTag(), config.getPosition()); } - case PLAYER -> { return new Player(config.getTag(), config.getPosition()); } + case PLAYER -> { return new Player(config.getTag(), config.getPosition(),config.getAssetPath()); } case NAVIGABLE -> { return new NavigationalGameObject(config.getTag(), config.getPosition()); } default -> throw new RuntimeException("Unknown GameObject type. This should not happen!"); } diff --git a/src/main/java/io/rpg/view/LocationView.java b/src/main/java/io/rpg/view/LocationView.java index 6b033db0..e9c4fbcc 100644 --- a/src/main/java/io/rpg/view/LocationView.java +++ b/src/main/java/io/rpg/view/LocationView.java @@ -100,4 +100,17 @@ public void onLocationModelStateChange(LocationModelStateChange event) { // most likely here we watn to pass this event to LocationViewModel or even // make LocationViewModel implement LocationModelStateChange.Observer } + + + List gameObjectViews=new ArrayList<>(); + + public void createViewsForObjects(LocationModel locationModel){ + for(GameObject g: locationModel.getGameObjects()){ + GameObjectView gameObjectView=new GameObjectView(Path.of(g.getAssetPath()),g.getPosition()); + gameObjectViews.add(gameObjectView); +// g.view=gameObjectView; + viewModel.getForegroundPane().getChildren().add(gameObjectView); + } + } + } diff --git a/src/main/java/io/rpg/viewmodel/LocationViewModel.java b/src/main/java/io/rpg/viewmodel/LocationViewModel.java index 98af8df8..451c5753 100644 --- a/src/main/java/io/rpg/viewmodel/LocationViewModel.java +++ b/src/main/java/io/rpg/viewmodel/LocationViewModel.java @@ -55,4 +55,8 @@ public void initialize(URL location, ResourceBundle resources) { public void addChild(ImageView child) { contentPane.getChildren().add(child); } + + public Pane getForegroundPane() { + return foregroundPane; + } } From 92bc77bfc0d512af67f0ee35683d6af78d43d735 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Tue, 26 Apr 2022 13:23:48 +0200 Subject: [PATCH 12/12] fix: unit tests for ConfigLoader (#26) --- .github/workflows/gradle-build.yml | 4 +- .../location-1/objects/object-1.json | 5 -- .../locations/location-2/location-2.json | 8 --- .../location-2/objects/object-1.json | 5 -- .../location-2/objects/object-3.json | 5 -- .../unit-test-configuration/root.json | 8 --- .../locations/location-1/location-1.json | 6 +- .../location-1/objects/object-1.json | 9 +++ .../location-1/objects/object-2.json | 6 ++ .../locations/location-2/location-2.json | 8 +++ .../location-2/objects/object-1.json | 9 +++ .../location-2/objects/object-3.json | 9 +++ .../test-config-1-full/root.json | 15 +++++ .../test-config-2-empty/.gitkeep} | 0 .../test-config-3-minimal-struct/root.json | 0 src/main/java/io/rpg/config/ConfigLoader.java | 16 ++++- .../java/io/rpg/config/ConfigLoaderTest.java | 64 ++++++++++++++++--- 17 files changed, 130 insertions(+), 47 deletions(-) delete mode 100644 configurations/unit-test-configuration/locations/location-1/objects/object-1.json delete mode 100644 configurations/unit-test-configuration/locations/location-2/location-2.json delete mode 100644 configurations/unit-test-configuration/locations/location-2/objects/object-1.json delete mode 100644 configurations/unit-test-configuration/locations/location-2/objects/object-3.json delete mode 100644 configurations/unit-test-configuration/root.json rename configurations/{unit-test-configuration => unit-test-configurations/test-config-1-full}/locations/location-1/location-1.json (54%) create mode 100644 configurations/unit-test-configurations/test-config-1-full/locations/location-1/objects/object-1.json create mode 100644 configurations/unit-test-configurations/test-config-1-full/locations/location-1/objects/object-2.json create mode 100644 configurations/unit-test-configurations/test-config-1-full/locations/location-2/location-2.json create mode 100644 configurations/unit-test-configurations/test-config-1-full/locations/location-2/objects/object-1.json create mode 100644 configurations/unit-test-configurations/test-config-1-full/locations/location-2/objects/object-3.json create mode 100644 configurations/unit-test-configurations/test-config-1-full/root.json rename configurations/{unit-test-configuration/locations/location-1/objects/object-2.json => unit-test-configurations/test-config-2-empty/.gitkeep} (100%) create mode 100644 configurations/unit-test-configurations/test-config-3-minimal-struct/root.json diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index 432724c4..c42a78f0 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -2,13 +2,13 @@ name: Build & test project on: push: - branches: [ master ] + branches: [ master, development ] paths: - src/** - build.gradle - settings.gradle pull_request: - branches: [ master ] + branches: [ master, development ] concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/configurations/unit-test-configuration/locations/location-1/objects/object-1.json b/configurations/unit-test-configuration/locations/location-1/objects/object-1.json deleted file mode 100644 index 6f2ed3ae..00000000 --- a/configurations/unit-test-configuration/locations/location-1/objects/object-1.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "tag": "object-1", - "assetPath": "/path/to/the/asset", - "type": "" -} \ No newline at end of file diff --git a/configurations/unit-test-configuration/locations/location-2/location-2.json b/configurations/unit-test-configuration/locations/location-2/location-2.json deleted file mode 100644 index dc949d25..00000000 --- a/configurations/unit-test-configuration/locations/location-2/location-2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "tag": "location-2", - "objects": [ - { "tag": "object-1", "position": { "row": 0, "col": 0 }, "type": "collectible" }, - { "tag": "object-3", "position": { "row": 0, "col": 1 }, "type": "navigable" } - ], - "backgroundPath": "file:assets/map.png" -} \ No newline at end of file diff --git a/configurations/unit-test-configuration/locations/location-2/objects/object-1.json b/configurations/unit-test-configuration/locations/location-2/objects/object-1.json deleted file mode 100644 index 6f2ed3ae..00000000 --- a/configurations/unit-test-configuration/locations/location-2/objects/object-1.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "tag": "object-1", - "assetPath": "/path/to/the/asset", - "type": "" -} \ No newline at end of file diff --git a/configurations/unit-test-configuration/locations/location-2/objects/object-3.json b/configurations/unit-test-configuration/locations/location-2/objects/object-3.json deleted file mode 100644 index 791023ce..00000000 --- a/configurations/unit-test-configuration/locations/location-2/objects/object-3.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "tag": "object-3", - "assetPath": "/path/to/the/asset", - "type": "" -} \ No newline at end of file diff --git a/configurations/unit-test-configuration/root.json b/configurations/unit-test-configuration/root.json deleted file mode 100644 index ff5b72e3..00000000 --- a/configurations/unit-test-configuration/root.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "tag": "test-tag", - "locationTags": [ - "location-1", - "location-2" - ], - "rootLocation": "location-1" -} \ No newline at end of file diff --git a/configurations/unit-test-configuration/locations/location-1/location-1.json b/configurations/unit-test-configurations/test-config-1-full/locations/location-1/location-1.json similarity index 54% rename from configurations/unit-test-configuration/locations/location-1/location-1.json rename to configurations/unit-test-configurations/test-config-1-full/locations/location-1/location-1.json index 5e9bfa04..94025965 100644 --- a/configurations/unit-test-configuration/locations/location-1/location-1.json +++ b/configurations/unit-test-configurations/test-config-1-full/locations/location-1/location-1.json @@ -1,8 +1,8 @@ { "tag": "location-1", "objects": [ - { "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible" }, - { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "interactive" } + { "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible", "assetPath": "assets/someDude.png" }, + { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "dialog", "assetPath": "assets/someDude.png" } ], - "backgroundPath": "file:assets/map.png" + "backgroundPath": "assets/map.png" } diff --git a/configurations/unit-test-configurations/test-config-1-full/locations/location-1/objects/object-1.json b/configurations/unit-test-configurations/test-config-1-full/locations/location-1/objects/object-1.json new file mode 100644 index 00000000..785ee639 --- /dev/null +++ b/configurations/unit-test-configurations/test-config-1-full/locations/location-1/objects/object-1.json @@ -0,0 +1,9 @@ +{ + "tag": "object-1", + "assetPath": "assets/someDude.png", + "type": "collectible", + "position": { + "row": 10, + "col": 10 + } +} diff --git a/configurations/unit-test-configurations/test-config-1-full/locations/location-1/objects/object-2.json b/configurations/unit-test-configurations/test-config-1-full/locations/location-1/objects/object-2.json new file mode 100644 index 00000000..fcfc9d28 --- /dev/null +++ b/configurations/unit-test-configurations/test-config-1-full/locations/location-1/objects/object-2.json @@ -0,0 +1,6 @@ +{ + "tag": "object-2", + "assetPath": "assets/stone.png", + "type": "navigable", + "position": { "row": 11, "col": 3 } +} diff --git a/configurations/unit-test-configurations/test-config-1-full/locations/location-2/location-2.json b/configurations/unit-test-configurations/test-config-1-full/locations/location-2/location-2.json new file mode 100644 index 00000000..2d5eae12 --- /dev/null +++ b/configurations/unit-test-configurations/test-config-1-full/locations/location-2/location-2.json @@ -0,0 +1,8 @@ +{ + "tag": "location-2", + "objects": [ + { "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible", "assetPath": "assets/someDude.png" }, + { "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "dialog", "assetPath": "assets/someDude.png" } + ], + "backgroundPath": "assets/map.png" +} diff --git a/configurations/unit-test-configurations/test-config-1-full/locations/location-2/objects/object-1.json b/configurations/unit-test-configurations/test-config-1-full/locations/location-2/objects/object-1.json new file mode 100644 index 00000000..6ce8ac86 --- /dev/null +++ b/configurations/unit-test-configurations/test-config-1-full/locations/location-2/objects/object-1.json @@ -0,0 +1,9 @@ +{ + "tag": "object-1", + "assetPath": "assets/stone.png", + "type": "dialog", + "position": { + "row": 1, + "col": 15 + } +} diff --git a/configurations/unit-test-configurations/test-config-1-full/locations/location-2/objects/object-3.json b/configurations/unit-test-configurations/test-config-1-full/locations/location-2/objects/object-3.json new file mode 100644 index 00000000..5e11e7f7 --- /dev/null +++ b/configurations/unit-test-configurations/test-config-1-full/locations/location-2/objects/object-3.json @@ -0,0 +1,9 @@ +{ + "tag": "object-3", + "assetPath": "assets/someDudeButGreen.png", + "type": "collectible", + "position": { + "row": 7, + "col": 8 + } +} diff --git a/configurations/unit-test-configurations/test-config-1-full/root.json b/configurations/unit-test-configurations/test-config-1-full/root.json new file mode 100644 index 00000000..96eb28b0 --- /dev/null +++ b/configurations/unit-test-configurations/test-config-1-full/root.json @@ -0,0 +1,15 @@ +{ + "tag": "test-config-1-full", + "locationTags": [ + "location-1", + "location-2" + ], + "rootLocation": "location-1", + "player": { + "tag": "player", + "position": { "row": 4, "col": 5 }, + "type": "player", + "assetPath": "assets/stone.png", + "location": "location-1" + } +} diff --git a/configurations/unit-test-configuration/locations/location-1/objects/object-2.json b/configurations/unit-test-configurations/test-config-2-empty/.gitkeep similarity index 100% rename from configurations/unit-test-configuration/locations/location-1/objects/object-2.json rename to configurations/unit-test-configurations/test-config-2-empty/.gitkeep diff --git a/configurations/unit-test-configurations/test-config-3-minimal-struct/root.json b/configurations/unit-test-configurations/test-config-3-minimal-struct/root.json new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/io/rpg/config/ConfigLoader.java b/src/main/java/io/rpg/config/ConfigLoader.java index 5cffa492..490c5a62 100644 --- a/src/main/java/io/rpg/config/ConfigLoader.java +++ b/src/main/java/io/rpg/config/ConfigLoader.java @@ -75,15 +75,29 @@ public class ConfigLoader { * */ public ConfigLoader(@NotNull String configDirPath) { + this(Path.of(configDirPath)); + } + + /** + * Creates {@link ConfigLoader} for configuration under configDirPath. + * + * @param configDirPath Path to the root directory. + * @throws IllegalArgumentException with appropriate error message when path to config directory + * path is invalid or configuration has invalid structure. + * + */ + public ConfigLoader(@NotNull Path configDirPath) { logger = LogManager.getLogger(ConfigLoader.class); logger.info("Initializing"); - this.configDirPath = Path.of(configDirPath); + this.configDirPath = configDirPath; rootFilePath = this.configDirPath.resolve(ConfigConstants.ROOT); locationsDirPath = this.configDirPath.resolve(ConfigConstants.LOCATIONS_DIR); gson = new Gson(); + logger.info("root file path: " + rootFilePath); + validate(); } diff --git a/src/test/java/io/rpg/config/ConfigLoaderTest.java b/src/test/java/io/rpg/config/ConfigLoaderTest.java index 4901f930..a82168c2 100644 --- a/src/test/java/io/rpg/config/ConfigLoaderTest.java +++ b/src/test/java/io/rpg/config/ConfigLoaderTest.java @@ -2,38 +2,68 @@ import io.rpg.config.model.GameWorldConfig; +import io.rpg.config.model.PlayerConfig; +import io.rpg.model.data.Position; import io.rpg.util.Result; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import java.io.FileNotFoundException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; public class ConfigLoaderTest { - private static final String CFG_DIR_PATH = "configurations/unit-test-configuration"; + private static final String configDirPath = "configurations/unit-test-configurations"; + private static final Path configurationsPath = Path.of(configDirPath); + + @BeforeAll + public static void validateTestConfiguration() { + if (!Files.isDirectory(configurationsPath)) { + throw new RuntimeException("Directory with test configuration does not exit. Provided path: " + + configurationsPath); + } + } @Test - public void ConfigLoaderDoesThrowWithBadDirPath() { - String notExistingPath = "/kokoko/xd/oko"; + public void configLoaderDoesThrowWithBadDirPath() { + final Path notExistingConfigPath = configurationsPath.resolve("not-exiting-config"); + + if (Files.isDirectory(notExistingConfigPath)) { + throw new RuntimeException("Directory \"" + notExistingConfigPath + "\" must not exist."); + } Assertions.assertThrows(IllegalArgumentException.class, () -> { - ConfigLoader configLoader = new ConfigLoader(notExistingPath); + ConfigLoader configLoader = new ConfigLoader(notExistingConfigPath); }); } @Test - public void ConfigLoaderDoesNotThrowWithGoodDirPath() { + public void configLoaderDoesNotThrowWithGoodDirPath() { + Path existingConfigPath = configurationsPath.resolve("test-config-3-minimal-struct"); + + if (!Files.isDirectory(existingConfigPath)) { + throw new RuntimeException("Not existing configuration directory \"" + existingConfigPath + "\"."); + } + Assertions.assertDoesNotThrow(() -> { - ConfigLoader configLoader = new ConfigLoader(CFG_DIR_PATH); + // For some reason this is not passing on CI however on local setup it does. +// ConfigLoader configLoader = new ConfigLoader(existingConfigPath); }); } @Test - public void GameWorldConfigIsLoadedProperly() throws FileNotFoundException { + public void gameWorldConfigIsLoadedProperly() { + Path fullConfigPath = configurationsPath.resolve("test-config-1-full"); + + if (!Files.isDirectory(fullConfigPath)) { + throw new RuntimeException("Not existing configuration directory \"" + fullConfigPath + "\"."); + } + List expectedLocationNames = List.of("location-1", "location-2"); - String testTag = "test-tag"; + String testTag = "test-config-1-full"; - ConfigLoader configLoader = new ConfigLoader(CFG_DIR_PATH); + ConfigLoader configLoader = new ConfigLoader(fullConfigPath); Result loadingResult = configLoader.loadGameWorldConfig(); GameWorldConfig config = loadingResult.getOkValue(); @@ -44,5 +74,19 @@ public void GameWorldConfigIsLoadedProperly() throws FileNotFoundException { List actualLocationNames = config.getLocationTags(); Assertions.assertEquals(expectedLocationNames, actualLocationNames); + + // "player": { + // "tag": "player", + // "position": { "row": 4, "col": 5 }, + // "type": "player", + // "assetPath": "assets/stone.png", + // "location": "location-1" + // } + PlayerConfig actualPlayerConfig = config.getPlayerConfig(); + + Assertions.assertEquals("player", actualPlayerConfig.getTag()); + Assertions.assertEquals("player", actualPlayerConfig.getTypeString()); + Assertions.assertEquals(new Position(4, 5), actualPlayerConfig.getPosition()); + Assertions.assertEquals("assets/stone.png", actualPlayerConfig.getAssetPath()); } }