From 0815b7b19ccbb33f2ff0ebbfe706cd3e7956040a Mon Sep 17 00:00:00 2001 From: co012 Date: Thu, 5 May 2022 19:53:50 +0200 Subject: [PATCH 01/18] chore: deleted tag setter --- .../io/rpg/model/location/LocationModel.java | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 07da8020..5b2db102 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -46,23 +46,15 @@ public Player getPlayer() { public GameObject getObject(int row, int column) { - GameObject object = gameObjects.stream().filter(gameObject -> gameObject.getPosition() - .equals(new Position(row, column))) - .findFirst().orElse(null); + 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. - * - * @param tag tag for the location - */ - private void setTag(String tag) { - this.tag = tag; - } + // @UnmodifiableView // public List getGameObjects() { @@ -120,8 +112,7 @@ public Builder setGameObjects(@NotNull List gameObjects) { } public Builder setTag(@NotNull String tag) { - assert tag != null : "Location tag must not be null!"; - locationModel.setTag(tag); + locationModel.tag = tag; return this; } @@ -136,12 +127,13 @@ public LocationModel build() { return locationModel; } } + public List getGameObjects() { return gameObjects; } - public void update(float elapsed){ - if(player!=null){ + public void update(float elapsed) { + if (player != null) { player.update(elapsed); } } From f4d031aebb021a84abb9956d884f6dca16280e42 Mon Sep 17 00:00:00 2001 From: co012 Date: Thu, 5 May 2022 20:29:10 +0200 Subject: [PATCH 02/18] chore: change checkstyle.xml to allow method chaining --- config/checkstyle/checkstyle.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index f160a312..7d3736bb 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -149,11 +149,6 @@ - - - - - From d06347c6ce6aec2277f6e752bc105fed17dbc718 Mon Sep 17 00:00:00 2001 From: co012 Date: Thu, 5 May 2022 20:30:20 +0200 Subject: [PATCH 03/18] chore: remove duplicate code --- src/main/java/io/rpg/Initializer.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/io/rpg/Initializer.java b/src/main/java/io/rpg/Initializer.java index a76d14cb..cad7ca36 100644 --- a/src/main/java/io/rpg/Initializer.java +++ b/src/main/java/io/rpg/Initializer.java @@ -1,16 +1,13 @@ 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; import io.rpg.controller.PlayerController; import io.rpg.model.actions.LocationChangeAction; -import io.rpg.model.data.Position; 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; @@ -79,7 +76,6 @@ public Result initialize() { assert view != null; gameObjectViews.forEach(view::addChild); - model.addOnLocationModelStateChangeObserver(view); controllerBuilder @@ -87,7 +83,6 @@ public Result initialize() { .addModelForTag(locationConfig.getTag(), model) .registerToViews(gameObjectViews); - view.createViewsForObjects(model); } // Player is created separately From 8eccada92658f964180f59863ad5a39ced5cc281 Mon Sep 17 00:00:00 2001 From: co012 Date: Thu, 5 May 2022 20:51:04 +0200 Subject: [PATCH 04/18] chore: removed assetPath from GameObject and GameObjectConfig no longer extends GameObject --- .../io/rpg/config/model/GameObjectConfig.java | 31 ++++++++++++------- .../java/io/rpg/model/object/GameObject.java | 6 +--- .../java/io/rpg/config/ConfigLoaderTest.java | 4 +-- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/main/java/io/rpg/config/model/GameObjectConfig.java b/src/main/java/io/rpg/config/model/GameObjectConfig.java index 6fb2499a..419cf392 100644 --- a/src/main/java/io/rpg/config/model/GameObjectConfig.java +++ b/src/main/java/io/rpg/config/model/GameObjectConfig.java @@ -13,12 +13,28 @@ * Represents {@link io.rpg.model.object.GameObject} configuration provided by user * in configuration files. */ -public class GameObjectConfig extends GameObject { +public class GameObjectConfig { private String type; + private String tag; + private Position position; + private String assetPath; public GameObjectConfig(@NotNull String tag, @NotNull Position position) { - super(tag, position); + this.tag = tag; + this.position = position; + } + + public String getTag() { + return tag; + } + + public Position getPosition() { + return position; + } + + public String getAssetPath() { + return assetPath; } public String getTypeString() { @@ -39,15 +55,10 @@ public Result validate() { } public void updateFrom(GameObjectConfig gameObjectConfig) { - if (gameObjectConfig.getPosition() != null) { - this.position = gameObjectConfig.getPosition(); - } + this.position = gameObjectConfig.position; if (gameObjectConfig.getTypeString() != null) { this.type = gameObjectConfig.getTypeString(); } - if (gameObjectConfig.getAssetPath() != null) { - this.assetPath = gameObjectConfig.assetPath; - } } public String getFieldDescription() { @@ -68,9 +79,7 @@ public String getFieldDescription() { @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("\n{\n").append(super.getFieldDescription()).append(getFieldDescription()); - return builder.append("}").toString(); + return "\n{\n" + getFieldDescription() + "}"; } } diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index 315f58d9..26c6dee4 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -70,13 +70,8 @@ public Position getPosition() { } public GameObject(@NotNull String tag, @NotNull Position position) { - 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<>(); } @@ -96,6 +91,7 @@ public void removeGameObjectStateChangeObserver(GameObjectStateChange.Observer o this.stateChangeObservers.remove(observer); } + public String getFieldDescription() { StringBuilder builder = new StringBuilder(); for (Field field : GameObject.class.getDeclaredFields()) { diff --git a/src/test/java/io/rpg/config/ConfigLoaderTest.java b/src/test/java/io/rpg/config/ConfigLoaderTest.java index a82168c2..c73c3163 100644 --- a/src/test/java/io/rpg/config/ConfigLoaderTest.java +++ b/src/test/java/io/rpg/config/ConfigLoaderTest.java @@ -79,7 +79,7 @@ public void gameWorldConfigIsLoadedProperly() { // "tag": "player", // "position": { "row": 4, "col": 5 }, // "type": "player", - // "assetPath": "assets/stone.png", + // "assetPath": "assets/stone.png", (Removed) // "location": "location-1" // } PlayerConfig actualPlayerConfig = config.getPlayerConfig(); @@ -87,6 +87,6 @@ public void gameWorldConfigIsLoadedProperly() { 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()); + // Assertions.assertEquals("assets/stone.png", actualPlayerConfig.getAssetPath()); } } From 37efc9de0ea441a5d797b31d5b4859ce00ed7285 Mon Sep 17 00:00:00 2001 From: co012 Date: Thu, 5 May 2022 21:54:35 +0200 Subject: [PATCH 05/18] feat: Made DiscretePane --- src/main/java/io/rpg/view/DiscretePane.java | 45 +++++++++++++++++++ .../io/rpg/viewmodel/location-view.fxml | 3 +- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/rpg/view/DiscretePane.java diff --git a/src/main/java/io/rpg/view/DiscretePane.java b/src/main/java/io/rpg/view/DiscretePane.java new file mode 100644 index 00000000..f7c6577c --- /dev/null +++ b/src/main/java/io/rpg/view/DiscretePane.java @@ -0,0 +1,45 @@ +package io.rpg.view; + +import java.util.List; +import javafx.geometry.HPos; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.geometry.VPos; +import javafx.scene.Node; +import javafx.scene.image.ImageView; +import javafx.scene.layout.Pane; + +public class DiscretePane extends Pane { + private static final double FIELD_SIZE = 64; + + @Override + protected void layoutChildren() { + List managed = getManagedChildren(); + Insets insets = getInsets(); + Pos align = Pos.CENTER; + double top = snapSpaceY(insets.getTop()); + double left = snapSpaceX(insets.getLeft()); + + + + + double x = left + FIELD_SIZE; + double y = top; + double baselineOffset = -1; + + for (int i = 0, size = managed.size(); i < size; i++) { + Node child = managed.get(i); + child.maxWidth(FIELD_SIZE); + child.maxHeight(FIELD_SIZE); + if (child instanceof ImageView imageView){ + imageView.setFitWidth(FIELD_SIZE); + imageView.setFitHeight(FIELD_SIZE); + layoutInArea(child,imageView.getX() * FIELD_SIZE , imageView.getY() * FIELD_SIZE, FIELD_SIZE, FIELD_SIZE, + baselineOffset, + HPos.LEFT, VPos.TOP); + } + + } + + } +} diff --git a/src/main/resources/io/rpg/viewmodel/location-view.fxml b/src/main/resources/io/rpg/viewmodel/location-view.fxml index c567fec8..fecd5b24 100644 --- a/src/main/resources/io/rpg/viewmodel/location-view.fxml +++ b/src/main/resources/io/rpg/viewmodel/location-view.fxml @@ -5,6 +5,7 @@ + @@ -14,7 +15,7 @@ - + From d8f12d00d91736d22d1e073fee1fa43c414bb450 Mon Sep 17 00:00:00 2001 From: co012 Date: Thu, 5 May 2022 21:56:26 +0200 Subject: [PATCH 06/18] chore: got rid of SCALE --- src/main/java/io/rpg/controller/Controller.java | 5 ++--- src/main/java/io/rpg/model/data/Position.java | 1 - src/main/java/io/rpg/model/data/Vector.java | 6 ++---- src/main/java/io/rpg/model/object/Player.java | 4 ++-- src/main/java/io/rpg/util/GameObjectFactory.java | 3 +-- src/main/java/io/rpg/view/GameObjectView.java | 10 ++-------- src/main/java/io/rpg/view/LocationView.java | 15 +-------------- src/main/java/module-info.java | 1 + 8 files changed, 11 insertions(+), 34 deletions(-) diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index c4bebae8..c708344c 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -163,11 +163,10 @@ 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() / SCALE, (int) objectView.getX() / SCALE); - if (Math.abs(playerPos.x - objectView.getX()) / SCALE <= 1.5 && Math.abs(playerPos.y - objectView.getY()) / SCALE <= 1.5) { + 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(); } diff --git a/src/main/java/io/rpg/model/data/Position.java b/src/main/java/io/rpg/model/data/Position.java index 276655a3..928ca2a0 100644 --- a/src/main/java/io/rpg/model/data/Position.java +++ b/src/main/java/io/rpg/model/data/Position.java @@ -9,7 +9,6 @@ */ public class Position { public final int row; - public final int col; public Position(int row, int col) { diff --git a/src/main/java/io/rpg/model/data/Vector.java b/src/main/java/io/rpg/model/data/Vector.java index 4bfdc61a..d5130d0a 100644 --- a/src/main/java/io/rpg/model/data/Vector.java +++ b/src/main/java/io/rpg/model/data/Vector.java @@ -16,10 +16,8 @@ public Vector(float x, float y) { } public Vector(Position position) { - // TODO THIS MOTHT - int SCALE = 64; - this.x = position.col * SCALE; - this.y = position.row * SCALE; + this.x = position.col; + this.y = position.row; } } diff --git a/src/main/java/io/rpg/model/object/Player.java b/src/main/java/io/rpg/model/object/Player.java index 4f5b8e6e..603a16cc 100644 --- a/src/main/java/io/rpg/model/object/Player.java +++ b/src/main/java/io/rpg/model/object/Player.java @@ -22,9 +22,9 @@ public class Player extends GameObject { public Player(@NotNull String tag, @NotNull Position position, @NotNull String assetPath) { - super(tag, position, assetPath); + super(tag, position); this.currentPosition = new Vector(position.col, position.row); - this.speed = 100f; + this.speed = 6f; this.direction = new Vector(0, 0); this.rightPressed = false; this.leftPressed = false; diff --git a/src/main/java/io/rpg/util/GameObjectFactory.java b/src/main/java/io/rpg/util/GameObjectFactory.java index 2fd84ead..a8f67f16 100644 --- a/src/main/java/io/rpg/util/GameObjectFactory.java +++ b/src/main/java/io/rpg/util/GameObjectFactory.java @@ -20,11 +20,10 @@ public class GameObjectFactory { * @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 PLAYER -> { return new Player(config.getTag(), config.getPosition(),config.getAssetPath()); } + 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/GameObjectView.java b/src/main/java/io/rpg/view/GameObjectView.java index 2da8b341..f84fe71e 100644 --- a/src/main/java/io/rpg/view/GameObjectView.java +++ b/src/main/java/io/rpg/view/GameObjectView.java @@ -16,19 +16,13 @@ public class GameObjectView extends ImageView private Path path; private final Set onClickedObservers; - private final int SCALE = 64; 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 * SCALE); - this.setY(position.row * SCALE); - - this.setPreserveRatio(true); - this.setSmooth(false); - this.setFitHeight(SCALE); + this.setX(position.col); + this.setY(position.row); this.onClickedObservers = new HashSet<>(); this.setOnMouseClicked(event -> emitOnMouseClickedEvent(new MouseClickedEvent(this, event))); diff --git a/src/main/java/io/rpg/view/LocationView.java b/src/main/java/io/rpg/view/LocationView.java index 11889df2..7a343efe 100644 --- a/src/main/java/io/rpg/view/LocationView.java +++ b/src/main/java/io/rpg/view/LocationView.java @@ -1,16 +1,11 @@ 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 java.util.Collection; -import java.util.Collections; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; @@ -31,7 +26,6 @@ public class LocationView extends Scene implements KeyboardEvent.Emitter, LocationModelStateChange.Observer { - static final int SCALE = 32; // TODO: REMOVE THIS private final static URL FXML_URL = LocationViewModel.class.getResource("location-view.fxml"); private final Logger logger; @@ -100,20 +94,13 @@ public void emitKeyboardEvent(KeyboardEvent event) { @Override public void onLocationModelStateChange(LocationModelStateChange event) { // TODO: implement state change & appropriate events - // most likely here we watn to pass this event to LocationViewModel or even + // most likely here we want 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); - viewModel.getForegroundPane().getChildren().add(gameObjectView); - } - } public void removeChild(GameObjectView view) { viewModel.getForegroundPane().getChildren().remove(view); diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index b6cc828d..c4140771 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -18,6 +18,7 @@ opens io.rpg.model.data to com.google.gson; opens io.rpg.viewmodel to javafx.fxml; + opens io.rpg.view to javafx.fxml; opens io.rpg.config.model to com.google.gson; exports io.rpg; From e646a184741828a67206dff4a00a905bb135184c Mon Sep 17 00:00:00 2001 From: co012 Date: Fri, 6 May 2022 21:40:16 +0200 Subject: [PATCH 07/18] chore: improve DiscretePane --- src/main/java/io/rpg/view/DiscretePane.java | 76 ++++++++++++++------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/src/main/java/io/rpg/view/DiscretePane.java b/src/main/java/io/rpg/view/DiscretePane.java index f7c6577c..b5e6a222 100644 --- a/src/main/java/io/rpg/view/DiscretePane.java +++ b/src/main/java/io/rpg/view/DiscretePane.java @@ -1,45 +1,73 @@ package io.rpg.view; -import java.util.List; +import javafx.collections.ListChangeListener; import javafx.geometry.HPos; -import javafx.geometry.Insets; -import javafx.geometry.Pos; +import javafx.geometry.Point2D; import javafx.geometry.VPos; import javafx.scene.Node; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; +/** + * Custom pane. It scales children to correct size and lays them in correct spot. + */ public class DiscretePane extends Pane { private static final double FIELD_SIZE = 64; - @Override - protected void layoutChildren() { - List managed = getManagedChildren(); - Insets insets = getInsets(); - Pos align = Pos.CENTER; - double top = snapSpaceY(insets.getTop()); - double left = snapSpaceX(insets.getLeft()); + /** + * Creates a DiscretePane. + */ + public DiscretePane() { + super(); + getChildren().addListener((ListChangeListener) c -> { + while (c.next()) { + if (c.wasAdded()) { + c.getAddedSubList().forEach(this::modifyNewChild); + } + } + }); + } + + private void modifyNewChild(Node node) { + node.maxWidth(FIELD_SIZE); + node.maxHeight(FIELD_SIZE); + if (node instanceof ImageView imageView) { + imageView.setFitWidth(FIELD_SIZE); + imageView.setFitHeight(FIELD_SIZE); + } + } + @Override + protected void layoutChildren() { + double baselineOffset = 0; + for (Node child : getManagedChildren()) { + Point2D position = calcLayoutPosition(child); - double x = left + FIELD_SIZE; - double y = top; - double baselineOffset = -1; + layoutInArea(child, + position.getX(), + position.getY(), + FIELD_SIZE, + FIELD_SIZE, + baselineOffset, + HPos.LEFT, + VPos.TOP); + } + } - for (int i = 0, size = managed.size(); i < size; i++) { - Node child = managed.get(i); - child.maxWidth(FIELD_SIZE); - child.maxHeight(FIELD_SIZE); - if (child instanceof ImageView imageView){ - imageView.setFitWidth(FIELD_SIZE); - imageView.setFitHeight(FIELD_SIZE); - layoutInArea(child,imageView.getX() * FIELD_SIZE , imageView.getY() * FIELD_SIZE, FIELD_SIZE, FIELD_SIZE, - baselineOffset, - HPos.LEFT, VPos.TOP); - } + private Point2D calcLayoutPosition(Node child) { + double x; + double y; + if (child instanceof GameObjectView gameObjectView) { + x = gameObjectView.getX() * FIELD_SIZE; + y = gameObjectView.getY() * FIELD_SIZE; + } else { + x = child.getLayoutX(); + y = child.getLayoutY(); } + return new Point2D(x, y); } } From 449e1a9b4aa42035a2a915367ffe3d65afd32628 Mon Sep 17 00:00:00 2001 From: co012 Date: Sun, 8 May 2022 19:08:47 +0200 Subject: [PATCH 08/18] chore: replace Vector with build-in Point2D --- .../java/io/rpg/controller/Controller.java | 6 ++-- src/main/java/io/rpg/model/data/Vector.java | 23 ------------- .../java/io/rpg/model/object/GameObject.java | 32 ++++--------------- src/main/java/io/rpg/model/object/Player.java | 28 +++++++--------- .../java/io/rpg/util/GameObjectFactory.java | 3 -- 5 files changed, 21 insertions(+), 71 deletions(-) delete mode 100644 src/main/java/io/rpg/model/data/Vector.java diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index c708344c..41d3effa 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -5,7 +5,6 @@ import io.rpg.model.data.KeyboardEvent; import io.rpg.model.data.MouseClickedEvent; import io.rpg.model.data.Position; -import io.rpg.model.data.Vector; import io.rpg.model.location.LocationModel; import io.rpg.model.object.*; import io.rpg.util.Result; @@ -13,6 +12,7 @@ import io.rpg.view.LocationView; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import javafx.geometry.Point2D; import javafx.scene.Scene; import javafx.scene.input.KeyEvent; import javafx.stage.Stage; @@ -163,10 +163,10 @@ private int getWindowCenterY() { @Override public void onMouseClickedEvent(MouseClickedEvent event) { - Vector playerPos = currentModel.getPlayer().getPixelPosition(); + Point2D 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) { + if (Math.abs(playerPos.getX() - objectView.getX()) <= 1.5 && Math.abs(playerPos.getY() - objectView.getY()) <= 1.5) { if (object instanceof InteractiveGameObject) { ((InteractiveGameObject) object).onAction(); } diff --git a/src/main/java/io/rpg/model/data/Vector.java b/src/main/java/io/rpg/model/data/Vector.java deleted file mode 100644 index d5130d0a..00000000 --- a/src/main/java/io/rpg/model/data/Vector.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.rpg.model.data; - -/** - * TODO. - */ -public class Vector { - @SuppressWarnings("checkstyle:MemberName") - public final float x; - - @SuppressWarnings("checkstyle:MemberName") - public final float y; - - public Vector(float x, float y) { - this.x = x; - this.y = y; - } - - public Vector(Position position) { - this.x = position.col; - this.y = position.row; - } - -} diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index 26c6dee4..782cd83b 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -1,18 +1,14 @@ package io.rpg.model.object; -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; - import java.lang.reflect.Field; import java.util.LinkedHashSet; import java.util.Optional; import java.util.Set; +import javafx.geometry.Point2D; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Class representing common state properties for all @@ -20,15 +16,11 @@ */ public class GameObject implements GameObjectStateChange.Emitter { -// protected Vector currentPosition; - -// public GameObjectView view; - /** * Position of game object in model's representation of location. */ @Nullable - protected Position position; + protected Point2D position; /** * Unique identifier of this game object. @@ -37,20 +29,9 @@ public class GameObject implements GameObjectStateChange.Emitter { @NotNull private final String tag; - /** - * - */ - @Nullable - protected String assetPath; - @NotNull private final Set stateChangeObservers; - @Nullable - public String getAssetPath() { - return assetPath; - } - /** * Unique identifier of this game object. */ @@ -66,12 +47,13 @@ public String getTag() { */ @Nullable public Position getPosition() { - return position; + assert position != null; + return new Position((int) position.getY(), (int) position.getX()); } public GameObject(@NotNull String tag, @NotNull Position position) { this.tag = tag; - this.position = position; + this.position = new Point2D(position.col, position.row); this.stateChangeObservers = new LinkedHashSet<>(); } diff --git a/src/main/java/io/rpg/model/object/Player.java b/src/main/java/io/rpg/model/object/Player.java index 603a16cc..31a93251 100644 --- a/src/main/java/io/rpg/model/object/Player.java +++ b/src/main/java/io/rpg/model/object/Player.java @@ -1,48 +1,39 @@ package io.rpg.model.object; 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 javafx.geometry.Point2D; import org.jetbrains.annotations.NotNull; public class Player extends GameObject { - private Vector currentPosition; private int strength; private float speed; - private Vector direction; private boolean rightPressed; private boolean leftPressed; private boolean upPressed; private boolean downPressed; private GameObjectView gameObjectView; - private Vector pixelPosition; + private Point2D pixelPosition; public Player(@NotNull String tag, @NotNull Position position, @NotNull String assetPath) { super(tag, position); - this.currentPosition = new Vector(position.col, position.row); this.speed = 6f; - 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); + this.pixelPosition = new Point2D(position.col, position.row); } public void updateStrength(int value) { strength += value; } - public void setDirection(Vector direction) { - this.direction = direction; - } - public Vector getPixelPosition() { + public Point2D getPixelPosition() { return pixelPosition; } @@ -66,7 +57,10 @@ public void update(float elapsed) { x += 1; } - this.pixelPosition = new Vector(this.pixelPosition.x + speed * x * elapsed / 1000, this.pixelPosition.y + speed * y * elapsed / 1000); + Point2D nextPosition = new Point2D(x, y) + .multiply(speed * elapsed / 1000) + .add(this.pixelPosition); + this.pixelPosition = nextPosition; } public void setRightPressed(boolean rightPressed) { @@ -95,12 +89,12 @@ public void setGameObjectView(GameObjectView gameObjectView) { public void render() { if (gameObjectView != null) { - gameObjectView.setX(this.pixelPosition.x); - gameObjectView.setY(this.pixelPosition.y); + gameObjectView.setX(this.pixelPosition.getX()); + gameObjectView.setY(this.pixelPosition.getY()); } } public void setPosition(Position position) { - pixelPosition = new Vector(position); + pixelPosition = new Point2D(position.col, position.row); } } diff --git a/src/main/java/io/rpg/util/GameObjectFactory.java b/src/main/java/io/rpg/util/GameObjectFactory.java index a8f67f16..c9b38b82 100644 --- a/src/main/java/io/rpg/util/GameObjectFactory.java +++ b/src/main/java/io/rpg/util/GameObjectFactory.java @@ -1,13 +1,10 @@ package io.rpg.util; import io.rpg.config.model.GameObjectConfig; -import io.rpg.model.data.Vector; import io.rpg.model.object.*; -import javafx.scene.image.Image; 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. From 5d0ea361890b3313fb01ba130ee911c3bd979c67 Mon Sep 17 00:00:00 2001 From: co012 Date: Sun, 8 May 2022 19:49:40 +0200 Subject: [PATCH 09/18] chore: preparation for event base position changing --- src/main/java/io/rpg/Initializer.java | 2 -- .../java/io/rpg/controller/Controller.java | 5 ++-- .../java/io/rpg/model/object/GameObject.java | 25 ++++++++++++++++--- src/main/java/io/rpg/model/object/Player.java | 19 +++++--------- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/main/java/io/rpg/Initializer.java b/src/main/java/io/rpg/Initializer.java index cad7ca36..9e03aa2c 100644 --- a/src/main/java/io/rpg/Initializer.java +++ b/src/main/java/io/rpg/Initializer.java @@ -95,8 +95,6 @@ public Result initialize() { Controller controller = controllerBuilder.build(); -// // TODO: this is a temporary solution -// controller.setPlayerView(playerView); Game.Builder gameBuilder = new Game.Builder(); Game game = gameBuilder diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index 41d3effa..27ef0bd0 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -163,10 +163,11 @@ private int getWindowCenterY() { @Override public void onMouseClickedEvent(MouseClickedEvent event) { - Point2D playerPos = currentModel.getPlayer().getPixelPosition(); + Point2D playerPos = currentModel.getPlayer().getExactPosition(); GameObjectView objectView = event.source(); GameObject object = currentModel.getObject((int) objectView.getY(), (int) objectView.getX()); - if (Math.abs(playerPos.getX() - objectView.getX()) <= 1.5 && Math.abs(playerPos.getY() - objectView.getY()) <= 1.5) { + double distance = playerPos.distance(objectView.getX(), objectView.getY()); + if (distance < 1.5) { if (object instanceof InteractiveGameObject) { ((InteractiveGameObject) object).onAction(); } diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index 782cd83b..b4dd07c2 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -20,7 +20,7 @@ public class GameObject implements GameObjectStateChange.Emitter { * Position of game object in model's representation of location. */ @Nullable - protected Point2D position; + protected Point2D exactPosition; /** * Unique identifier of this game object. @@ -47,13 +47,26 @@ public String getTag() { */ @Nullable public Position getPosition() { - assert position != null; - return new Position((int) position.getY(), (int) position.getX()); + assert exactPosition != null; + return new Position((int) Math.round(exactPosition.getY()), (int) Math.round(exactPosition.getX())); + } + + public void setExactPosition(Point2D position) { + emitPositionChangeEvent(this.exactPosition, position); + this.exactPosition = position; + } + + private void emitPositionChangeEvent(Point2D oldPosition, Point2D newPosition) { + // TODO: 08.05.2022 + } + + public Point2D getExactPosition() { + return exactPosition; } public GameObject(@NotNull String tag, @NotNull Position position) { this.tag = tag; - this.position = new Point2D(position.col, position.row); + this.exactPosition = new Point2D(position.col, position.row); this.stateChangeObservers = new LinkedHashSet<>(); } @@ -98,6 +111,10 @@ public String toString() { return builder.append("}").toString(); } + public void setPosition(Position playerPosition) { + setExactPosition(new Point2D(playerPosition.col, playerPosition.row)); + } + public enum Type { NAVIGABLE("navigable"), DIALOG("dialog"), diff --git a/src/main/java/io/rpg/model/object/Player.java b/src/main/java/io/rpg/model/object/Player.java index 31a93251..cbb35bee 100644 --- a/src/main/java/io/rpg/model/object/Player.java +++ b/src/main/java/io/rpg/model/object/Player.java @@ -14,7 +14,6 @@ public class Player extends GameObject { private boolean upPressed; private boolean downPressed; private GameObjectView gameObjectView; - private Point2D pixelPosition; public Player(@NotNull String tag, @NotNull Position position, @NotNull String assetPath) { @@ -25,7 +24,6 @@ public Player(@NotNull String tag, @NotNull Position position, @NotNull String a this.upPressed = false; this.downPressed = false; this.strength = 0; - this.pixelPosition = new Point2D(position.col, position.row); } public void updateStrength(int value) { @@ -33,10 +31,6 @@ public void updateStrength(int value) { } - public Point2D getPixelPosition() { - return pixelPosition; - } - public void update(float elapsed) { float y = 0; float x = 0; @@ -59,8 +53,9 @@ public void update(float elapsed) { Point2D nextPosition = new Point2D(x, y) .multiply(speed * elapsed / 1000) - .add(this.pixelPosition); - this.pixelPosition = nextPosition; + .add(this.getExactPosition()); + + this.setExactPosition(nextPosition); } public void setRightPressed(boolean rightPressed) { @@ -89,12 +84,10 @@ public void setGameObjectView(GameObjectView gameObjectView) { public void render() { if (gameObjectView != null) { - gameObjectView.setX(this.pixelPosition.getX()); - gameObjectView.setY(this.pixelPosition.getY()); + Point2D pos = this.getExactPosition(); + gameObjectView.setX(pos.getX()); + gameObjectView.setY(pos.getY()); } } - public void setPosition(Position position) { - pixelPosition = new Point2D(position.col, position.row); - } } From 07ab5520491744c24f1c730b1707904ac4b777ed Mon Sep 17 00:00:00 2001 From: co012 Date: Mon, 9 May 2022 20:30:03 +0200 Subject: [PATCH 10/18] feat: Bounds are working --- .../io/rpg/controller/PlayerController.java | 1 + .../io/rpg/model/location/LocationModel.java | 8 ++++++ .../java/io/rpg/model/object/GameObject.java | 28 +++++++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/rpg/controller/PlayerController.java b/src/main/java/io/rpg/controller/PlayerController.java index cab82897..73f6713a 100644 --- a/src/main/java/io/rpg/controller/PlayerController.java +++ b/src/main/java/io/rpg/controller/PlayerController.java @@ -53,6 +53,7 @@ public void teleportTo(LocationModel model, LocationView view, Position playerPo onChangeLocation.run(); updateOnChangeLocation(model, view); + player.setPositionBounds(model.getBounds()); player.setPosition(playerPosition); model.setPlayer(player); view.addChild(playerView); diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 5b2db102..369f0a3c 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -5,6 +5,7 @@ import io.rpg.model.object.Player; import io.rpg.model.object.GameObject; import io.rpg.util.Result; +import javafx.geometry.Point2D; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -20,6 +21,8 @@ public class LocationModel implements LocationModelStateChange.Emitter { private List gameObjects; private Player player; + public final Point2D bounds; + private final Set locationModelStateChangeObservers; public LocationModel(@NotNull String tag, @NotNull List gameObjects) { @@ -30,6 +33,7 @@ public LocationModel(@NotNull String tag, @NotNull List gameObjects) private LocationModel() { this.locationModelStateChangeObservers = new LinkedHashSet<>(); + bounds = new Point2D(9.5, 9.5); // TODO: 09.05.2022 Implement loading from config } public void setPlayer(@NotNull Player player) { @@ -44,6 +48,9 @@ public Player getPlayer() { return player; } + public Point2D getBounds() { + return bounds; + } public GameObject getObject(int row, int column) { GameObject object = gameObjects.stream().filter(gameObject -> gameObject.getPosition() @@ -70,6 +77,7 @@ public GameObject getObject(int row, int column) { */ private void setGameObjects(List gameObjects) { this.gameObjects = gameObjects; + gameObjects.forEach(go -> go.setPositionBounds(bounds)); } @Override diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index b4dd07c2..c13bbf89 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -40,6 +40,8 @@ public String getTag() { return tag; } + private Point2D positionBounds; + /** * Position of game object in model's representation of location. * @@ -52,8 +54,24 @@ public Position getPosition() { } public void setExactPosition(Point2D position) { - emitPositionChangeEvent(this.exactPosition, position); - this.exactPosition = position; + Point2D boundPosition = accountForBounds(position); + if (!boundPosition.equals(position)) { + emitBoundCrossedEvent(position.subtract(boundPosition)); + } + + emitPositionChangeEvent(this.exactPosition, boundPosition); + this.exactPosition = boundPosition; + } + + private void emitBoundCrossedEvent(Point2D crossedBy) { + // TODO: 09.05.2022 + } + + // TODO: 09.05.2022 I need a better name for this method + private Point2D accountForBounds(Point2D pos) { + double x = Math.max(0, Math.min(positionBounds. getX(), pos.getX())); + double y = Math.max(0, Math.min(positionBounds. getY(), pos.getY())); + return new Point2D(x, y); } private void emitPositionChangeEvent(Point2D oldPosition, Point2D newPosition) { @@ -115,6 +133,12 @@ public void setPosition(Position playerPosition) { setExactPosition(new Point2D(playerPosition.col, playerPosition.row)); } + public void setPositionBounds(Point2D bounds) { + this.positionBounds = bounds; + } + + + public enum Type { NAVIGABLE("navigable"), DIALOG("dialog"), From 308bb952f5a74d71b7edacf2753ed3cbcb4450c6 Mon Sep 17 00:00:00 2001 From: co012 Date: Tue, 10 May 2022 14:14:55 +0200 Subject: [PATCH 11/18] chore: made position observable --- .../io/rpg/controller/PlayerController.java | 3 +- .../io/rpg/model/location/LocationModel.java | 48 +++++++++++++++--- .../java/io/rpg/model/object/GameObject.java | 50 ++++++------------- 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/main/java/io/rpg/controller/PlayerController.java b/src/main/java/io/rpg/controller/PlayerController.java index 73f6713a..4e2f6d4e 100644 --- a/src/main/java/io/rpg/controller/PlayerController.java +++ b/src/main/java/io/rpg/controller/PlayerController.java @@ -53,8 +53,8 @@ public void teleportTo(LocationModel model, LocationView view, Position playerPo onChangeLocation.run(); updateOnChangeLocation(model, view); - player.setPositionBounds(model.getBounds()); player.setPosition(playerPosition); + model.registerGameObject(player); model.setPlayer(player); view.addChild(playerView); view.addKeyboardEventObserver(this); @@ -64,6 +64,7 @@ private void updateOnChangeLocation(LocationModel model, LocationView view) { this.onChangeLocation = () -> { view.removeKeyboardEventObserver(this); view.removeChild(this.playerView); + model.unRegisterGameObject(player); }; } } diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 369f0a3c..ae071c1a 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -5,6 +5,8 @@ import io.rpg.model.object.Player; import io.rpg.model.object.GameObject; import io.rpg.util.Result; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; import javafx.geometry.Point2D; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -19,8 +21,8 @@ public class LocationModel implements LocationModelStateChange.Emitter { private String tag; private List gameObjects; + private HashMap> boundsCorrectors; private Player player; - public final Point2D bounds; private final Set locationModelStateChangeObservers; @@ -29,10 +31,12 @@ public LocationModel(@NotNull String tag, @NotNull List gameObjects) this(); this.tag = tag; this.gameObjects = gameObjects; + } private LocationModel() { this.locationModelStateChangeObservers = new LinkedHashSet<>(); + this.boundsCorrectors = new HashMap<>(); bounds = new Point2D(9.5, 9.5); // TODO: 09.05.2022 Implement loading from config } @@ -48,10 +52,6 @@ public Player getPlayer() { return player; } - public Point2D getBounds() { - return bounds; - } - public GameObject getObject(int row, int column) { GameObject object = gameObjects.stream().filter(gameObject -> gameObject.getPosition() .equals(new Position(row, column))) @@ -77,7 +77,43 @@ public GameObject getObject(int row, int column) { */ private void setGameObjects(List gameObjects) { this.gameObjects = gameObjects; - gameObjects.forEach(go -> go.setPositionBounds(bounds)); + gameObjects.forEach(this::registerGameObject); + gameObjects.forEach(g -> checkAndCorrectGameObjectPosition(g, g.getExactPosition(), g.getExactPosition())); + } + + public void registerGameObject(GameObject gameObject) { + ChangeListener boundCorrector = + (observable, oldValue, newValue) -> checkAndCorrectGameObjectPosition(gameObject, oldValue, newValue); + gameObject.getExactPositionProperty().addListener(boundCorrector); + boundsCorrectors.put(gameObject, boundCorrector); + } + + public void unRegisterGameObject(GameObject gameObject) { + ChangeListener boundCorrector = boundsCorrectors.remove(gameObject); + gameObject.getExactPositionProperty().removeListener(boundCorrector); + } + + private void checkAndCorrectGameObjectPosition(GameObject gameObject, Point2D oldPosition, Point2D newPosition) { + Point2D boundPosition = getBoundPosition(newPosition); + if (boundPosition.equals(newPosition)) { + return; + } + + gameObject.setExactPosition(boundPosition); + Point2D boundsCrossedDirection = newPosition.subtract(boundPosition).normalize(); + + emitBoundCrossedEvent(boundsCrossedDirection); + } + + private void emitBoundCrossedEvent(Point2D boundsCrossedDirection) { + // TODO: 10.05.2022 Bound crossed action + System.out.println(boundsCrossedDirection); + } + + private Point2D getBoundPosition(Point2D pos) { + double x = Math.max(0, Math.min(bounds.getX(), pos.getX())); + double y = Math.max(0, Math.min(bounds.getY(), pos.getY())); + return new Point2D(x, y); } @Override diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index c13bbf89..fac0c28f 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -6,6 +6,9 @@ import java.util.LinkedHashSet; import java.util.Optional; import java.util.Set; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.value.ObservableValue; import javafx.geometry.Point2D; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,8 +22,7 @@ public class GameObject implements GameObjectStateChange.Emitter { /** * Position of game object in model's representation of location. */ - @Nullable - protected Point2D exactPosition; + private final SimpleObjectProperty exactPositionProperty; /** * Unique identifier of this game object. @@ -40,7 +42,12 @@ public String getTag() { return tag; } - private Point2D positionBounds; + + public GameObject(@NotNull String tag, @NotNull Position position) { + this.tag = tag; + this.stateChangeObservers = new LinkedHashSet<>(); + this.exactPositionProperty = new SimpleObjectProperty<>(new Point2D(position.col, position.row)); + } /** * Position of game object in model's representation of location. @@ -49,43 +56,20 @@ public String getTag() { */ @Nullable public Position getPosition() { - assert exactPosition != null; + Point2D exactPosition = getExactPosition(); return new Position((int) Math.round(exactPosition.getY()), (int) Math.round(exactPosition.getX())); } public void setExactPosition(Point2D position) { - Point2D boundPosition = accountForBounds(position); - if (!boundPosition.equals(position)) { - emitBoundCrossedEvent(position.subtract(boundPosition)); - } - - emitPositionChangeEvent(this.exactPosition, boundPosition); - this.exactPosition = boundPosition; - } - - private void emitBoundCrossedEvent(Point2D crossedBy) { - // TODO: 09.05.2022 - } - - // TODO: 09.05.2022 I need a better name for this method - private Point2D accountForBounds(Point2D pos) { - double x = Math.max(0, Math.min(positionBounds. getX(), pos.getX())); - double y = Math.max(0, Math.min(positionBounds. getY(), pos.getY())); - return new Point2D(x, y); - } - - private void emitPositionChangeEvent(Point2D oldPosition, Point2D newPosition) { - // TODO: 08.05.2022 + exactPositionProperty.setValue(position); } public Point2D getExactPosition() { - return exactPosition; + return exactPositionProperty.getValue(); } - public GameObject(@NotNull String tag, @NotNull Position position) { - this.tag = tag; - this.exactPosition = new Point2D(position.col, position.row); - this.stateChangeObservers = new LinkedHashSet<>(); + public ObservableValue getExactPositionProperty() { + return exactPositionProperty; } @Override @@ -133,10 +117,6 @@ public void setPosition(Position playerPosition) { setExactPosition(new Point2D(playerPosition.col, playerPosition.row)); } - public void setPositionBounds(Point2D bounds) { - this.positionBounds = bounds; - } - public enum Type { From 54cfa72b21d215af23829975eb9f455c5a66639f Mon Sep 17 00:00:00 2001 From: co012 Date: Fri, 13 May 2022 18:07:37 +0200 Subject: [PATCH 12/18] chore: bound Player and PlayerView positions --- build.gradle | 10 +++++ src/main/java/io/rpg/Initializer.java | 1 + src/main/java/io/rpg/Main.java | 4 -- .../java/io/rpg/controller/Controller.java | 7 ++-- .../io/rpg/controller/PlayerController.java | 1 + .../io/rpg/model/location/LocationModel.java | 4 -- src/main/java/io/rpg/model/object/Player.java | 8 ---- src/main/java/io/rpg/view/DiscretePane.java | 3 +- src/main/java/io/rpg/view/GameObjectView.java | 37 +++++++++++++++---- 9 files changed, 46 insertions(+), 29 deletions(-) diff --git a/build.gradle b/build.gradle index c4c14252..3168ec83 100644 --- a/build.gradle +++ b/build.gradle @@ -61,6 +61,16 @@ test { useJUnitPlatform() } +compileJava { + options.compilerArgs += ["--add-exports=javafx.graphics/com.sun.javafx.scene=io.rpg"] + +} + +run { + + jvmArgs = ['--add-exports=javafx.graphics/com.sun.javafx.scene=io.rpg'] +} + jlink { imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip") options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'] diff --git a/src/main/java/io/rpg/Initializer.java b/src/main/java/io/rpg/Initializer.java index 9e03aa2c..91a2c66e 100644 --- a/src/main/java/io/rpg/Initializer.java +++ b/src/main/java/io/rpg/Initializer.java @@ -128,6 +128,7 @@ public static void registerGameObjectViewsToModel(List gameObjects, // registration gameObject.addGameObjectStateChangeObserver(gameObjectView); + gameObjectView.bindToGameObject(gameObject); } } diff --git a/src/main/java/io/rpg/Main.java b/src/main/java/io/rpg/Main.java index c497e85c..5924d456 100644 --- a/src/main/java/io/rpg/Main.java +++ b/src/main/java/io/rpg/Main.java @@ -50,10 +50,6 @@ public void handle(long now) { float difference = (now - lastUpdate) / 1e6f; game.getController().getCurrentModel().update(difference); - Player player = game.getController().getCurrentModel().getPlayer(); - if (player != null) { - player.render(); - } } lastUpdate = now; } diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index 27ef0bd0..a5b8170d 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -135,7 +135,7 @@ else if (tagToLocationViewMap.size() != tagToLocationModelMap.size()) @Override public void onKeyboardEvent(KeyboardEvent event) { // TODO: implement event handling - logger.info("Controller notified on key pressed from " + event.source()); + logger.trace("Controller notified on key pressed from " + event.source()); //TODO: call Player::set...Pressed depending on keyCode and whether the key was pressed or released KeyEvent payload = event.payload(); @@ -165,8 +165,8 @@ private int getWindowCenterY() { public void onMouseClickedEvent(MouseClickedEvent event) { Point2D playerPos = currentModel.getPlayer().getExactPosition(); GameObjectView objectView = event.source(); - GameObject object = currentModel.getObject((int) objectView.getY(), (int) objectView.getX()); - double distance = playerPos.distance(objectView.getX(), objectView.getY()); + GameObject object = currentModel.getObject((int) objectView.getPosition().getY(), (int) objectView.getPosition().getX()); + double distance = playerPos.distance(objectView.getPosition()); if (distance < 1.5) { if (object instanceof InteractiveGameObject) { ((InteractiveGameObject) object).onAction(); @@ -177,6 +177,7 @@ public void onMouseClickedEvent(MouseClickedEvent event) { objectView.setVisible(false); } } + logger.info("Controller notified on click from " + event.source()); } diff --git a/src/main/java/io/rpg/controller/PlayerController.java b/src/main/java/io/rpg/controller/PlayerController.java index 4e2f6d4e..b3f50b21 100644 --- a/src/main/java/io/rpg/controller/PlayerController.java +++ b/src/main/java/io/rpg/controller/PlayerController.java @@ -16,6 +16,7 @@ public class PlayerController implements KeyboardEvent.Observer { public PlayerController(Player player, GameObjectView playerView) { this.player = player; this.playerView = playerView; + playerView.bindToGameObject(player); this.onChangeLocation = () -> {}; player.addGameObjectStateChangeObserver(playerView); diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index ae071c1a..04585a05 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -172,10 +172,6 @@ public LocationModel build() { } } - 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/Player.java b/src/main/java/io/rpg/model/object/Player.java index cbb35bee..9a0a9771 100644 --- a/src/main/java/io/rpg/model/object/Player.java +++ b/src/main/java/io/rpg/model/object/Player.java @@ -82,12 +82,4 @@ public void setGameObjectView(GameObjectView gameObjectView) { this.gameObjectView = gameObjectView; } - public void render() { - if (gameObjectView != null) { - Point2D pos = this.getExactPosition(); - gameObjectView.setX(pos.getX()); - gameObjectView.setY(pos.getY()); - } - } - } diff --git a/src/main/java/io/rpg/view/DiscretePane.java b/src/main/java/io/rpg/view/DiscretePane.java index b5e6a222..37e368c8 100644 --- a/src/main/java/io/rpg/view/DiscretePane.java +++ b/src/main/java/io/rpg/view/DiscretePane.java @@ -61,8 +61,7 @@ private Point2D calcLayoutPosition(Node child) { double y; if (child instanceof GameObjectView gameObjectView) { - x = gameObjectView.getX() * FIELD_SIZE; - y = gameObjectView.getY() * FIELD_SIZE; + return gameObjectView.getPosition().multiply(FIELD_SIZE); } else { x = child.getLayoutX(); y = child.getLayoutY(); diff --git a/src/main/java/io/rpg/view/GameObjectView.java b/src/main/java/io/rpg/view/GameObjectView.java index f84fe71e..5aad20e4 100644 --- a/src/main/java/io/rpg/view/GameObjectView.java +++ b/src/main/java/io/rpg/view/GameObjectView.java @@ -1,33 +1,46 @@ package io.rpg.view; +import com.sun.javafx.scene.ImageViewHelper; import io.rpg.model.data.GameObjectStateChange; import io.rpg.model.data.MouseClickedEvent; import io.rpg.model.data.Position; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import org.jetbrains.annotations.NotNull; - +import io.rpg.model.object.GameObject; import java.nio.file.Path; import java.util.HashSet; +import java.util.Objects; import java.util.Set; +import javafx.beans.property.SimpleObjectProperty; +import javafx.geometry.Point2D; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import org.jetbrains.annotations.NotNull; public class GameObjectView extends ImageView implements MouseClickedEvent.Emitter, GameObjectStateChange.Observer { private Path path; private final Set onClickedObservers; + private final SimpleObjectProperty position; public GameObjectView(@NotNull Path assetPath, @NotNull Position position) { this.path = assetPath; this.setImage(new Image(resolvePathToJFXFormat(path.toString()))); - // todo: better position class - this.setX(position.col); - this.setY(position.row); - + this.position = new SimpleObjectProperty<>(new Point2D(position.col, position.row)); + setLayoutUpdateOnPositionChange(); this.onClickedObservers = new HashSet<>(); this.setOnMouseClicked(event -> emitOnMouseClickedEvent(new MouseClickedEvent(this, event))); } + private void setLayoutUpdateOnPositionChange() { + this.position.addListener((observable, oldValue, newValue) -> { + if (Objects.equals(oldValue, newValue)) { + return; + } + + ImageViewHelper.geomChanged(this); + }); + } + public static String resolvePathToJFXFormat(String path) { return "file:" + path; } @@ -39,6 +52,14 @@ public void emitOnMouseClickedEvent(MouseClickedEvent event) { onClickedObservers.forEach(listener -> listener.onMouseClickedEvent(event)); } + public void bindToGameObject(GameObject gameObject) { + this.position.bind(gameObject.getExactPositionProperty()); + } + + public Point2D getPosition() { + return position.get(); + } + @Override public void addOnClickedObserver(MouseClickedEvent.Observer observer) { onClickedObservers.add(observer); From 5bbc25027ad462f77ca7aaa8c6f1e46e9f11a1c1 Mon Sep 17 00:00:00 2001 From: co012 Date: Fri, 13 May 2022 18:45:47 +0200 Subject: [PATCH 13/18] chore: remove Plyer field fromm LocationModel --- build.gradle | 2 -- src/main/java/io/rpg/Main.java | 2 +- .../java/io/rpg/controller/Controller.java | 6 +++- .../io/rpg/controller/PlayerController.java | 9 +++-- .../io/rpg/model/location/LocationModel.java | 33 +++++++++---------- 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index 3168ec83..78531794 100644 --- a/build.gradle +++ b/build.gradle @@ -63,11 +63,9 @@ test { compileJava { options.compilerArgs += ["--add-exports=javafx.graphics/com.sun.javafx.scene=io.rpg"] - } run { - jvmArgs = ['--add-exports=javafx.graphics/com.sun.javafx.scene=io.rpg'] } diff --git a/src/main/java/io/rpg/Main.java b/src/main/java/io/rpg/Main.java index 5924d456..ece22952 100644 --- a/src/main/java/io/rpg/Main.java +++ b/src/main/java/io/rpg/Main.java @@ -49,7 +49,7 @@ public void handle(long now) { if (lastUpdate != -1) { float difference = (now - lastUpdate) / 1e6f; - game.getController().getCurrentModel().update(difference); + game.getController().getPlayerController().getPlayer().update(difference); } lastUpdate = now; } diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index a5b8170d..85791c37 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -163,7 +163,7 @@ private int getWindowCenterY() { @Override public void onMouseClickedEvent(MouseClickedEvent event) { - Point2D playerPos = currentModel.getPlayer().getExactPosition(); + Point2D playerPos = playerController.getPlayer().getExactPosition(); GameObjectView objectView = event.source(); GameObject object = currentModel.getObject((int) objectView.getPosition().getY(), (int) objectView.getPosition().getX()); double distance = playerPos.distance(objectView.getPosition()); @@ -181,6 +181,10 @@ public void onMouseClickedEvent(MouseClickedEvent event) { logger.info("Controller notified on click from " + event.source()); } + public PlayerController getPlayerController() { + return playerController; + } + public static class Builder { private final Controller controller; diff --git a/src/main/java/io/rpg/controller/PlayerController.java b/src/main/java/io/rpg/controller/PlayerController.java index b3f50b21..c3f5a8b2 100644 --- a/src/main/java/io/rpg/controller/PlayerController.java +++ b/src/main/java/io/rpg/controller/PlayerController.java @@ -55,8 +55,7 @@ public void teleportTo(LocationModel model, LocationView view, Position playerPo updateOnChangeLocation(model, view); player.setPosition(playerPosition); - model.registerGameObject(player); - model.setPlayer(player); + model.addGameObject(player); view.addChild(playerView); view.addKeyboardEventObserver(this); } @@ -65,7 +64,11 @@ private void updateOnChangeLocation(LocationModel model, LocationView view) { this.onChangeLocation = () -> { view.removeKeyboardEventObserver(this); view.removeChild(this.playerView); - model.unRegisterGameObject(player); + model.removeGameObject(player); }; } + + public Player getPlayer() { + return player; + } } diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 04585a05..316a71db 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -22,7 +22,7 @@ public class LocationModel implements LocationModelStateChange.Emitter { private String tag; private List gameObjects; private HashMap> boundsCorrectors; - private Player player; + private HashMap point2DGameObjectHashMap; public final Point2D bounds; private final Set locationModelStateChangeObservers; @@ -37,21 +37,14 @@ public LocationModel(@NotNull String tag, @NotNull List gameObjects) private LocationModel() { this.locationModelStateChangeObservers = new LinkedHashSet<>(); this.boundsCorrectors = new HashMap<>(); + this.point2DGameObjectHashMap = new HashMap<>(); bounds = new Point2D(9.5, 9.5); // TODO: 09.05.2022 Implement loading from config } - public void setPlayer(@NotNull Player player) { - this.player = player; - } - 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))) @@ -81,14 +74,25 @@ private void setGameObjects(List gameObjects) { gameObjects.forEach(g -> checkAndCorrectGameObjectPosition(g, g.getExactPosition(), g.getExactPosition())); } - public void registerGameObject(GameObject gameObject) { + public void addGameObject(GameObject gameObject) { + gameObjects.add(gameObject); + registerGameObject(gameObject); + checkAndCorrectGameObjectPosition(gameObject, gameObject.getExactPosition(), gameObject.getExactPosition()); + } + + private void registerGameObject(GameObject gameObject) { ChangeListener boundCorrector = (observable, oldValue, newValue) -> checkAndCorrectGameObjectPosition(gameObject, oldValue, newValue); gameObject.getExactPositionProperty().addListener(boundCorrector); boundsCorrectors.put(gameObject, boundCorrector); } - public void unRegisterGameObject(GameObject gameObject) { + public void removeGameObject(GameObject gameObject) { + gameObjects.remove(gameObject); + unRegisterGameObject(gameObject); + } + + private void unRegisterGameObject(GameObject gameObject) { ChangeListener boundCorrector = boundsCorrectors.remove(gameObject); gameObject.getExactPositionProperty().removeListener(boundCorrector); } @@ -133,6 +137,7 @@ public void emitLocationModelStateChange(LocationModelStateChange event) { }); } + public Result validate() { if (tag == null || gameObjects == null) { return Result.error(null); @@ -172,10 +177,4 @@ public LocationModel build() { } } - public void update(float elapsed) { - if (player != null) { - player.update(elapsed); - } - } - } From 29381a3b97c9a9848c9aa81632c7a1232964bbfd Mon Sep 17 00:00:00 2001 From: co012 Date: Fri, 13 May 2022 19:01:46 +0200 Subject: [PATCH 14/18] chore: new constructor from Point2D --- src/main/java/io/rpg/model/data/Position.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/rpg/model/data/Position.java b/src/main/java/io/rpg/model/data/Position.java index 928ca2a0..8ca050f1 100644 --- a/src/main/java/io/rpg/model/data/Position.java +++ b/src/main/java/io/rpg/model/data/Position.java @@ -1,13 +1,14 @@ package io.rpg.model.data; import java.util.Objects; +import javafx.geometry.Point2D; /** * Represents current position by holding row / col values. * This class can NOT be record due to some issues with * Gson library. */ -public class Position { +public final class Position { public final int row; public final int col; @@ -16,6 +17,10 @@ public Position(int row, int col) { this.col = col; } + public Position(Point2D point2D) { + this((int) Math.round(point2D.getY()), (int) Math.round(point2D.getX())); + } + public int getRow() { return row; } From 6e335eac3c796379488d0ca0e949c45d6ef28964 Mon Sep 17 00:00:00 2001 From: co012 Date: Fri, 13 May 2022 19:36:36 +0200 Subject: [PATCH 15/18] chore: object collisions --- .../io/rpg/model/location/LocationModel.java | 71 +++++++++++++------ .../java/io/rpg/model/object/GameObject.java | 2 +- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 316a71db..694221e5 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -2,18 +2,17 @@ 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; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.geometry.Point2D; 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.*; /** * Represents single location in our game. @@ -21,8 +20,8 @@ public class LocationModel implements LocationModelStateChange.Emitter { private String tag; private List gameObjects; - private HashMap> boundsCorrectors; - private HashMap point2DGameObjectHashMap; + private final HashMap> positionListeners; + private final HashMap positionGameObjectMap; public final Point2D bounds; private final Set locationModelStateChangeObservers; @@ -36,8 +35,8 @@ public LocationModel(@NotNull String tag, @NotNull List gameObjects) private LocationModel() { this.locationModelStateChangeObservers = new LinkedHashSet<>(); - this.boundsCorrectors = new HashMap<>(); - this.point2DGameObjectHashMap = new HashMap<>(); + this.positionListeners = new HashMap<>(); + this.positionGameObjectMap = new HashMap<>(); bounds = new Point2D(9.5, 9.5); // TODO: 09.05.2022 Implement loading from config } @@ -56,11 +55,6 @@ public GameObject getObject(int row, int column) { } -// @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. @@ -71,33 +65,64 @@ public GameObject getObject(int row, int column) { private void setGameObjects(List gameObjects) { this.gameObjects = gameObjects; gameObjects.forEach(this::registerGameObject); - gameObjects.forEach(g -> checkAndCorrectGameObjectPosition(g, g.getExactPosition(), g.getExactPosition())); + gameObjects.forEach(g -> checkAndCorrectBoundsCrossing(g, g.getExactPosition())); + gameObjects.forEach(g -> positionGameObjectMap.put(g.getPosition(), g)); } public void addGameObject(GameObject gameObject) { gameObjects.add(gameObject); + positionGameObjectMap.put(gameObject.getPosition(), gameObject); registerGameObject(gameObject); - checkAndCorrectGameObjectPosition(gameObject, gameObject.getExactPosition(), gameObject.getExactPosition()); + checkAndCorrectBoundsCrossing(gameObject, gameObject.getExactPosition()); } private void registerGameObject(GameObject gameObject) { - ChangeListener boundCorrector = - (observable, oldValue, newValue) -> checkAndCorrectGameObjectPosition(gameObject, oldValue, newValue); - gameObject.getExactPositionProperty().addListener(boundCorrector); - boundsCorrectors.put(gameObject, boundCorrector); + ChangeListener positionListener = + (observable, oldValue, newValue) -> onGameObjectPositionChange(gameObject, oldValue, newValue); + gameObject.getExactPositionProperty().addListener(positionListener); + positionListeners.put(gameObject, positionListener); } public void removeGameObject(GameObject gameObject) { gameObjects.remove(gameObject); + positionGameObjectMap.remove(gameObject.getPosition()); unRegisterGameObject(gameObject); } private void unRegisterGameObject(GameObject gameObject) { - ChangeListener boundCorrector = boundsCorrectors.remove(gameObject); - gameObject.getExactPositionProperty().removeListener(boundCorrector); + ChangeListener positionListener = positionListeners.remove(gameObject); + gameObject.getExactPositionProperty().removeListener(positionListener); } - private void checkAndCorrectGameObjectPosition(GameObject gameObject, Point2D oldPosition, Point2D newPosition) { + private void onGameObjectPositionChange(GameObject gameObject, Point2D oldPosition, Point2D newPosition) { + checkAndCorrectBoundsCrossing(gameObject, newPosition); + + Position newPos = new Position(newPosition); + Position oldPos = new Position(oldPosition); + if(newPos.equals(oldPos)) { + return; + } + + // Collision check + if(positionGameObjectMap.containsKey(newPos) && !positionGameObjectMap.get(newPos).equals(gameObject)) { + gameObject.setExactPosition(oldPosition); + return; + } + + if (gameObject.equals(positionGameObjectMap.get(oldPos))) { + changeField(gameObject, oldPos, newPos); + } + + + } + + private void changeField(GameObject gameObject, Position oldPos, Position newPos) { + positionGameObjectMap.remove(oldPos); + positionGameObjectMap.put(newPos, gameObject); + } + + + private void checkAndCorrectBoundsCrossing(GameObject gameObject, Point2D newPosition) { Point2D boundPosition = getBoundPosition(newPosition); if (boundPosition.equals(newPosition)) { return; diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index fac0c28f..6aff9210 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -57,7 +57,7 @@ public GameObject(@NotNull String tag, @NotNull Position position) { @Nullable public Position getPosition() { Point2D exactPosition = getExactPosition(); - return new Position((int) Math.round(exactPosition.getY()), (int) Math.round(exactPosition.getX())); + return new Position(exactPosition); } public void setExactPosition(Point2D position) { From c7d12c47b1ecb356c658c3c664c68946801ff42d Mon Sep 17 00:00:00 2001 From: co012 Date: Fri, 13 May 2022 21:23:37 +0200 Subject: [PATCH 16/18] chore: better LocationModel.getObject function --- .../java/io/rpg/controller/Controller.java | 7 ++++- .../io/rpg/model/location/LocationModel.java | 26 +++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index 85791c37..551c3395 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.LocationView; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.function.Supplier; import javafx.geometry.Point2D; import javafx.scene.Scene; import javafx.scene.input.KeyEvent; @@ -165,7 +166,10 @@ private int getWindowCenterY() { public void onMouseClickedEvent(MouseClickedEvent event) { Point2D playerPos = playerController.getPlayer().getExactPosition(); GameObjectView objectView = event.source(); - GameObject object = currentModel.getObject((int) objectView.getPosition().getY(), (int) objectView.getPosition().getX()); + Position position = new Position(objectView.getPosition()); + GameObject object = currentModel.getObject(position) + .orElseThrow(() -> new RuntimeException("No object present at position " + position)); + double distance = playerPos.distance(objectView.getPosition()); if (distance < 1.5) { if (object instanceof InteractiveGameObject) { @@ -175,6 +179,7 @@ public void onMouseClickedEvent(MouseClickedEvent event) { if (object instanceof CollectibleGameObject) { popupController.openTextImagePopup("Picked up an item!", objectView.getImage(), getWindowCenterX(), getWindowCenterY()); objectView.setVisible(false); + currentModel.removeGameObject(object); } } diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 694221e5..5bbaefe7 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import javafx.beans.value.ChangeListener; import javafx.geometry.Point2D; @@ -44,17 +45,10 @@ public String getTag() { return tag; } - 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; + public Optional getObject(Position position) { + return Optional.ofNullable(positionGameObjectMap.get(position)); } - /** * Private setter for Builder usage only. Notice that ownership of {@link GameObject}s is not * transferred to LocationModel. @@ -79,7 +73,8 @@ public void addGameObject(GameObject gameObject) { private void registerGameObject(GameObject gameObject) { ChangeListener positionListener = (observable, oldValue, newValue) -> onGameObjectPositionChange(gameObject, oldValue, newValue); - gameObject.getExactPositionProperty().addListener(positionListener); + gameObject.getExactPositionProperty() + .addListener(positionListener); positionListeners.put(gameObject, positionListener); } @@ -91,7 +86,8 @@ public void removeGameObject(GameObject gameObject) { private void unRegisterGameObject(GameObject gameObject) { ChangeListener positionListener = positionListeners.remove(gameObject); - gameObject.getExactPositionProperty().removeListener(positionListener); + gameObject.getExactPositionProperty() + .removeListener(positionListener); } private void onGameObjectPositionChange(GameObject gameObject, Point2D oldPosition, Point2D newPosition) { @@ -99,12 +95,13 @@ private void onGameObjectPositionChange(GameObject gameObject, Point2D oldPositi Position newPos = new Position(newPosition); Position oldPos = new Position(oldPosition); - if(newPos.equals(oldPos)) { + if (newPos.equals(oldPos)) { return; } // Collision check - if(positionGameObjectMap.containsKey(newPos) && !positionGameObjectMap.get(newPos).equals(gameObject)) { + if (positionGameObjectMap.containsKey(newPos) && !positionGameObjectMap.get(newPos) + .equals(gameObject)) { gameObject.setExactPosition(oldPosition); return; } @@ -129,7 +126,8 @@ private void checkAndCorrectBoundsCrossing(GameObject gameObject, Point2D newPos } gameObject.setExactPosition(boundPosition); - Point2D boundsCrossedDirection = newPosition.subtract(boundPosition).normalize(); + Point2D boundsCrossedDirection = newPosition.subtract(boundPosition) + .normalize(); emitBoundCrossedEvent(boundsCrossedDirection); } From 9d71bbecd5e791ef16a164e28ff494a4226115d5 Mon Sep 17 00:00:00 2001 From: co012 Date: Sat, 14 May 2022 18:57:40 +0200 Subject: [PATCH 17/18] Update src/main/java/io/rpg/model/location/LocationModel.java Co-authored-by: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> --- src/main/java/io/rpg/model/location/LocationModel.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index 5bbaefe7..cddd9097 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -109,8 +109,6 @@ private void onGameObjectPositionChange(GameObject gameObject, Point2D oldPositi if (gameObject.equals(positionGameObjectMap.get(oldPos))) { changeField(gameObject, oldPos, newPos); } - - } private void changeField(GameObject gameObject, Position oldPos, Position newPos) { From 7fe8105ffd6fa0bcfc837fb1d6ae461e3313c372 Mon Sep 17 00:00:00 2001 From: co012 Date: Sat, 14 May 2022 21:56:18 +0200 Subject: [PATCH 18/18] chore: better bounds --- src/main/java/io/rpg/model/location/LocationModel.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/rpg/model/location/LocationModel.java b/src/main/java/io/rpg/model/location/LocationModel.java index cddd9097..73237b17 100644 --- a/src/main/java/io/rpg/model/location/LocationModel.java +++ b/src/main/java/io/rpg/model/location/LocationModel.java @@ -31,14 +31,13 @@ public LocationModel(@NotNull String tag, @NotNull List gameObjects) this(); this.tag = tag; this.gameObjects = gameObjects; - } private LocationModel() { this.locationModelStateChangeObservers = new LinkedHashSet<>(); this.positionListeners = new HashMap<>(); this.positionGameObjectMap = new HashMap<>(); - bounds = new Point2D(9.5, 9.5); // TODO: 09.05.2022 Implement loading from config + bounds = new Point2D(10, 10); // TODO: 09.05.2022 Implement loading from config } public String getTag() { @@ -136,8 +135,9 @@ private void emitBoundCrossedEvent(Point2D boundsCrossedDirection) { } private Point2D getBoundPosition(Point2D pos) { - double x = Math.max(0, Math.min(bounds.getX(), pos.getX())); - double y = Math.max(0, Math.min(bounds.getY(), pos.getY())); + double offset = 0.3; // it should be less than 0.5 + double x = Math.max(-offset, Math.min(bounds.getX() - 1 + offset, pos.getX())); + double y = Math.max(-offset, Math.min(bounds.getY() - 1 + offset, pos.getY())); return new Point2D(x, y); }