From b7ed44756a1834cf0875a30f125b7e3e2a56dd91 Mon Sep 17 00:00:00 2001 From: zamojtel <56871145+zamojtel@users.noreply.github.com> Date: Tue, 24 May 2022 12:55:15 +0200 Subject: [PATCH] feat: add equipment * chore: add simple equipment system for the player Collected collectibles are now displayed if we click on a non-collectible item * feat: Improve equipment system * add InventoryPopup * Update src/main/java/io/rpg/controller/PopupController.java Co-authored-by: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> * Update src/main/java/io/rpg/model/data/Inventory.java Co-authored-by: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> * Update src/main/java/io/rpg/model/object/CollectibleGameObject.java Co-authored-by: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> * Update src/main/java/io/rpg/view/InventoryPopup.java Co-authored-by: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> * Update src/main/java/io/rpg/viewmodel/InventoryPopupViewModel.java Co-authored-by: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> * Update src/main/java/io/rpg/view/InventoryGameObjectView.java Co-authored-by: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> * fix: make equipment work on current arch Co-authored-by: Marcin Hawryluk <70582973+mhawryluk@users.noreply.github.com> Co-authored-by: Kacper Kafara --- .../location-1/objects/object-2.json | 2 +- .../rpg/config/model/ActionConfigBundle.java | 4 + .../java/io/rpg/controller/Controller.java | 20 ++++- .../io/rpg/controller/PopupController.java | 15 ++++ .../java/io/rpg/model/actions/ActionType.java | 6 +- .../io/rpg/model/actions/CollectAction.java | 16 ++++ .../java/io/rpg/model/data/Inventory.java | 19 +++++ .../model/object/CollectibleGameObject.java | 4 +- .../java/io/rpg/model/object/GameObject.java | 1 + .../model/object/InteractiveGameObject.java | 3 + src/main/java/io/rpg/model/object/Player.java | 9 +++ src/main/java/io/rpg/util/ActionFactory.java | 7 ++ .../java/io/rpg/util/GameObjectFactory.java | 7 ++ .../io/rpg/view/InventoryGameObjectView.java | 16 ++++ src/main/java/io/rpg/view/InventoryPopup.java | 78 +++++++++++++++++++ src/main/java/io/rpg/view/LocationView.java | 2 +- .../viewmodel/InventoryPopupViewModel.java | 42 ++++++++++ 17 files changed, 242 insertions(+), 9 deletions(-) create mode 100644 src/main/java/io/rpg/model/actions/CollectAction.java create mode 100644 src/main/java/io/rpg/model/data/Inventory.java create mode 100644 src/main/java/io/rpg/view/InventoryGameObjectView.java create mode 100644 src/main/java/io/rpg/view/InventoryPopup.java create mode 100644 src/main/java/io/rpg/viewmodel/InventoryPopupViewModel.java diff --git a/configurations/demo-config-1/locations/location-1/objects/object-2.json b/configurations/demo-config-1/locations/location-1/objects/object-2.json index 03164a34..e5bce821 100644 --- a/configurations/demo-config-1/locations/location-1/objects/object-2.json +++ b/configurations/demo-config-1/locations/location-1/objects/object-2.json @@ -1,4 +1,4 @@ { "tag": "object-2", - "onLeftClick": {"tag": "dialogue-action", "type": "dialogue", "statements": ["A key.,A, keyA, key.A, key.A, key.A, key.A, key.A, key.A key."], "assetPath": "assets/key.png"} + "onLeftClick": {"tag": "dialogue-action", "type": "collect"} } diff --git a/src/main/java/io/rpg/config/model/ActionConfigBundle.java b/src/main/java/io/rpg/config/model/ActionConfigBundle.java index 0bc1efdc..d596f637 100644 --- a/src/main/java/io/rpg/config/model/ActionConfigBundle.java +++ b/src/main/java/io/rpg/config/model/ActionConfigBundle.java @@ -252,6 +252,10 @@ Result validateForBattle() { return Result.ok(); } + Result validateForCollectAction() { + return Result.ok(); + } + Result validateBasic() { ErrorMessageBuilder builder = new ErrorMessageBuilder(); if (tag == null) { diff --git a/src/main/java/io/rpg/controller/Controller.java b/src/main/java/io/rpg/controller/Controller.java index e4f5c299..5770152a 100644 --- a/src/main/java/io/rpg/controller/Controller.java +++ b/src/main/java/io/rpg/controller/Controller.java @@ -5,6 +5,7 @@ import io.rpg.model.data.MouseClickedEvent; import io.rpg.model.data.Position; import io.rpg.model.location.LocationModel; +import io.rpg.model.object.CollectibleGameObject; import io.rpg.model.object.GameObject; import io.rpg.model.object.Player; import io.rpg.model.object.Question; @@ -12,16 +13,22 @@ import io.rpg.util.Result; import io.rpg.view.GameEndView; import io.rpg.view.GameObjectView; +import io.rpg.view.InventoryPopup; import io.rpg.view.LocationView; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedHashMap; import java.util.List; + import javafx.geometry.Point2D; import javafx.scene.Scene; +import javafx.scene.image.Image; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseButton; import javafx.stage.Stage; +import javafx.stage.StageStyle; +import io.rpg.view.popups.TextPopup; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -36,10 +43,8 @@ public class Controller implements KeyboardEvent.Observer, MouseClickedEvent.Obs private PlayerController playerController; private Stage mainStage; - public Controller() { logger = LogManager.getLogger(Controller.class); - tagToLocationModelMap = new LinkedHashMap<>(); tagToLocationViewMap = new LinkedHashMap<>(); } @@ -168,7 +173,13 @@ private void onAction(BattleAction action) { } popupController.openTextPopup(result.getMessage(), getWindowCenterX(), getWindowCenterY()); } - + + private void onAction(CollectAction action) { + popupController.openTextImagePopup("Picked up an item!", new Image("file:assets/key.png"), getWindowCenterX(), getWindowCenterY()); +// objectView.setVisible(false); + playerController.getPlayer().getInventory().add(action.getOwner()); + } + public Scene getView() { return currentView; } @@ -215,6 +226,7 @@ public void onKeyboardEvent(KeyboardEvent event) { case Q -> popupController.openQuestionPopup(new Question("How many bits are there in one byte?", new String[]{"1/8", "1024", "8", "256"}, 'C'), getWindowCenterX(), getWindowCenterY()); case L -> consumeAction(new LocationChangeAction("location-2", new Position(1, 2))); case U -> consumeAction(new GameEndAction("You have pressed the forbidden button")); + case E -> popupController.openInventoryPopup(playerController.getPlayer().getInventory(), getWindowCenterX(), getWindowCenterY()); } } // } else if (payload.getEventType() == KeyEvent.KEY_RELEASED) { @@ -236,7 +248,7 @@ public void onMouseClickedEvent(MouseClickedEvent event) { GameObjectView objectView = event.source(); Position position = new Position(objectView.getPosition()); GameObject object = currentModel.getObject(position) - .orElseThrow(() -> new RuntimeException("No object present at position " + position)); + .orElseThrow(() -> new RuntimeException("No object present at position " + position)); double distance = playerPos.distance(objectView.getPosition()); diff --git a/src/main/java/io/rpg/controller/PopupController.java b/src/main/java/io/rpg/controller/PopupController.java index 1aa3e67b..832e47be 100644 --- a/src/main/java/io/rpg/controller/PopupController.java +++ b/src/main/java/io/rpg/controller/PopupController.java @@ -3,6 +3,8 @@ import io.rpg.model.object.Question; import io.rpg.view.popups.DialoguePopup; import io.rpg.view.popups.QuestionPopup; +import io.rpg.model.data.Inventory; +import io.rpg.view.InventoryPopup; import io.rpg.view.popups.TextImagePopup; import io.rpg.view.popups.TextPopup; import javafx.scene.image.Image; @@ -50,6 +52,19 @@ public void openTextImagePopup(String text, Image image, int x, int y){ public void openPointsPopup(int pointsCount, int x, int y) { openTextImagePopup("You earned " + pointsCount + " points!", coinImage, x, y); } + public void openInventoryPopup(Inventory inventory,int x, int y) { +// InventoryPopup inventoryPopup=new InventoryPopup(); +// final Stage popupStage = new Stage(StageStyle.TRANSPARENT); + + InventoryPopup popupScene = new InventoryPopup(inventory); + popupStage.setScene(popupScene); + + popupStage.show(); + + popupStage.setX(x - popupScene.getWidth() / 2); + popupStage.setY(y - popupScene.getHeight() / 2); + + } public void openQuestionPopup(Question question, int x, int y, Runnable successCallback, Runnable failureCallback) { QuestionPopup popupScene = new QuestionPopup(question); diff --git a/src/main/java/io/rpg/model/actions/ActionType.java b/src/main/java/io/rpg/model/actions/ActionType.java index e67e1023..b18b6989 100644 --- a/src/main/java/io/rpg/model/actions/ActionType.java +++ b/src/main/java/io/rpg/model/actions/ActionType.java @@ -21,7 +21,10 @@ public enum ActionType { Dialogue("dialogue"), @SerializedName("battle") - Battle("battle"); + Battle("battle"), + + @SerializedName("collect") + Collect("collect"); private final String asString; @@ -41,6 +44,7 @@ public static Optional fromString(String action) { case "show-description" -> { return Optional.of(ShowDescription); } case "dialogue" -> { return Optional.of(Dialogue); } case "battle" -> { return Optional.of(Battle); } + case "collect" -> { return Optional.of(Collect); } default -> { return Optional.empty(); } } } diff --git a/src/main/java/io/rpg/model/actions/CollectAction.java b/src/main/java/io/rpg/model/actions/CollectAction.java new file mode 100644 index 00000000..82178564 --- /dev/null +++ b/src/main/java/io/rpg/model/actions/CollectAction.java @@ -0,0 +1,16 @@ +package io.rpg.model.actions; + +import io.rpg.model.object.GameObject; + +public class CollectAction implements Action { + private GameObject owner; + + public void setOwner(GameObject owner) { + this.owner = owner; + } + + public GameObject getOwner() { + return owner; + } +} + diff --git a/src/main/java/io/rpg/model/data/Inventory.java b/src/main/java/io/rpg/model/data/Inventory.java new file mode 100644 index 00000000..483a6264 --- /dev/null +++ b/src/main/java/io/rpg/model/data/Inventory.java @@ -0,0 +1,19 @@ +package io.rpg.model.data; + +import io.rpg.model.object.GameObject; + +import java.util.ArrayList; +import java.util.List; + +public class Inventory { + + public List items; + + public Inventory() { + items = new ArrayList<>(); + } + + public void add(GameObject object) { + items.add(object); + } +} diff --git a/src/main/java/io/rpg/model/object/CollectibleGameObject.java b/src/main/java/io/rpg/model/object/CollectibleGameObject.java index f00bf2e5..a63b5c5e 100644 --- a/src/main/java/io/rpg/model/object/CollectibleGameObject.java +++ b/src/main/java/io/rpg/model/object/CollectibleGameObject.java @@ -4,8 +4,8 @@ import org.jetbrains.annotations.NotNull; public final class CollectibleGameObject extends InteractiveGameObject { - public CollectibleGameObject(@NotNull String tag, @NotNull Position position) { - super(tag, position); + public CollectibleGameObject(@NotNull String tag, @NotNull Position position, String assetPath) { + super(tag, position, assetPath); } @Override diff --git a/src/main/java/io/rpg/model/object/GameObject.java b/src/main/java/io/rpg/model/object/GameObject.java index 290ff360..415eecbc 100644 --- a/src/main/java/io/rpg/model/object/GameObject.java +++ b/src/main/java/io/rpg/model/object/GameObject.java @@ -130,4 +130,5 @@ public void onLeftClick() { public int getStrength() { return strength; } + } diff --git a/src/main/java/io/rpg/model/object/InteractiveGameObject.java b/src/main/java/io/rpg/model/object/InteractiveGameObject.java index c1be7799..5c0ad3cd 100644 --- a/src/main/java/io/rpg/model/object/InteractiveGameObject.java +++ b/src/main/java/io/rpg/model/object/InteractiveGameObject.java @@ -4,6 +4,9 @@ import org.jetbrains.annotations.NotNull; public abstract class InteractiveGameObject extends GameObject { + public InteractiveGameObject(@NotNull String tag, @NotNull Position position,String assetPath) { + super(tag, position); + } public InteractiveGameObject(@NotNull String tag, @NotNull Position position) { super(tag, position); } diff --git a/src/main/java/io/rpg/model/object/Player.java b/src/main/java/io/rpg/model/object/Player.java index b6578d0d..0ee51b01 100644 --- a/src/main/java/io/rpg/model/object/Player.java +++ b/src/main/java/io/rpg/model/object/Player.java @@ -1,10 +1,13 @@ package io.rpg.model.object; +import io.rpg.model.data.Inventory; import io.rpg.model.data.Position; import io.rpg.view.GameObjectView; import javafx.geometry.Point2D; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class Player extends GameObject { private int strength; @@ -15,6 +18,7 @@ public class Player extends GameObject { private boolean downPressed; private GameObjectView gameObjectView; private int points; + Inventory inventory; public Player(@NotNull String tag, @NotNull Position position, @NotNull String assetPath) { @@ -25,6 +29,7 @@ public Player(@NotNull String tag, @NotNull Position position, @NotNull String a this.upPressed = false; this.downPressed = false; this.strength = 0; + this.inventory = new Inventory(); } public void updateStrength(int value) { @@ -93,5 +98,9 @@ public void addPoints(int value) { public int getStrength() { return strength; + } + + public Inventory getInventory() { + return inventory; } } diff --git a/src/main/java/io/rpg/util/ActionFactory.java b/src/main/java/io/rpg/util/ActionFactory.java index 0385eac1..07bbc1c2 100644 --- a/src/main/java/io/rpg/util/ActionFactory.java +++ b/src/main/java/io/rpg/util/ActionFactory.java @@ -34,6 +34,9 @@ public static Action fromConfig(ActionConfigBundle config) { case Battle -> { return battleActionFromConfig(config); } + case Collect -> { + return collectActionFromConfig(config); + } default -> { throw new IllegalArgumentException("Unexpected action type!"); } @@ -66,4 +69,8 @@ private static ShowDescriptionAction showDescriptionActionFromConfig(ActionConfi private static BattleAction battleActionFromConfig(ActionConfigBundle config) { return new BattleAction(config.getRewardPoints()); } + + private static CollectAction collectActionFromConfig(ActionConfigBundle config) { + return new CollectAction(); + } } diff --git a/src/main/java/io/rpg/util/GameObjectFactory.java b/src/main/java/io/rpg/util/GameObjectFactory.java index e27c0725..59294e28 100644 --- a/src/main/java/io/rpg/util/GameObjectFactory.java +++ b/src/main/java/io/rpg/util/GameObjectFactory.java @@ -4,6 +4,7 @@ import io.rpg.config.model.PlayerConfig; import io.rpg.model.actions.Action; import io.rpg.model.actions.BattleAction; +import io.rpg.model.actions.CollectAction; import io.rpg.model.actions.ShowDescriptionAction; import io.rpg.model.object.GameObject; import io.rpg.model.object.Player; @@ -56,9 +57,15 @@ public static GameObject fromConfig(GameObjectConfig config) { if (onLeftClickAction instanceof BattleAction) { ((BattleAction) onLeftClickAction).setOpponent(gameObject); } + if (onLeftClickAction instanceof CollectAction) { + ((CollectAction) onLeftClickAction).setOwner(gameObject); + } if (onRightClickAction instanceof BattleAction) { ((BattleAction) onRightClickAction).setOpponent(gameObject); } + if (onRightClickAction instanceof CollectAction) { + ((CollectAction) onRightClickAction).setOwner(gameObject); + } // TODO: Create ActionFactory & inflate the actions return gameObject; diff --git a/src/main/java/io/rpg/view/InventoryGameObjectView.java b/src/main/java/io/rpg/view/InventoryGameObjectView.java new file mode 100644 index 00000000..69a3abd3 --- /dev/null +++ b/src/main/java/io/rpg/view/InventoryGameObjectView.java @@ -0,0 +1,16 @@ +package io.rpg.view; + +import io.rpg.model.object.CollectibleGameObject; +import io.rpg.model.object.GameObject; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class InventoryGameObjectView extends ImageView { + GameObject collectibleGameObject; + + public InventoryGameObjectView(GameObject collectibleGameObject) { + this.collectibleGameObject = collectibleGameObject; + Image image = new Image(GameObjectView.resolvePathToJFXFormat("assets/key.png")); + setImage(image); + } +} diff --git a/src/main/java/io/rpg/view/InventoryPopup.java b/src/main/java/io/rpg/view/InventoryPopup.java new file mode 100644 index 00000000..cc416920 --- /dev/null +++ b/src/main/java/io/rpg/view/InventoryPopup.java @@ -0,0 +1,78 @@ +package io.rpg.view; + +import io.rpg.model.data.Inventory; +import io.rpg.model.data.Position; +import io.rpg.model.object.Player; +import io.rpg.viewmodel.InventoryPopupViewModel; +import io.rpg.viewmodel.TextPopupViewModel; +import javafx.event.EventHandler; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Group; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class InventoryPopup extends Scene { + final int PADDING_LEFT = 25; + final int PADDING_TOP = 20; + @FXML + private Label label; + + public InventoryPopup(Inventory inventory) { + + super(new Group(), Color.TRANSPARENT); + Group group = new Group(); + //TODO: load asset path from config + ImageView imageView = new ImageView(GameObjectView.resolvePathToJFXFormat("assets/popup-background.png")); + imageView.setX(0); + imageView.setY(0); + label = new Label(); + label.setLayoutX(300); + label.setLayoutY(100); + label.setStyle("-fx-font-family: Monospaced; -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: " + 18); + group.getChildren().add(imageView); + group.getChildren().add(label); + for (int i = 0; i < inventory.items.size(); i++) { +// String assetPath=inventory.items.get(i).getAssetPath(); +// to display objects in the menu +// wrapperClass to store information about object which we display + InventoryGameObjectView imageGameObjectView = new InventoryGameObjectView(inventory.items.get(i)); + + imageGameObjectView.setX(i * 50 + PADDING_LEFT); + imageGameObjectView.setY(0 + PADDING_TOP); + imageGameObjectView.setOnMouseEntered(event -> { + InventoryGameObjectView src = (InventoryGameObjectView) event.getSource(); +// System.out.println("over the item "+src.collectibleGameObject.getAssetPath()); + label.setText("stub description"); + }); + + imageGameObjectView.setOnMouseExited(event -> { + label.setText(""); + }); + + imageGameObjectView.setOnMouseClicked(event -> { + + System.out.println("Object clicked"); + InventoryGameObjectView src = (InventoryGameObjectView) event.getSource(); + System.out.println(); + }); + group.getChildren().add(imageGameObjectView); + + } + this.setRoot(group); + this.setFill(Color.TRANSPARENT); + } + +} diff --git a/src/main/java/io/rpg/view/LocationView.java b/src/main/java/io/rpg/view/LocationView.java index 7a343efe..43fd570e 100644 --- a/src/main/java/io/rpg/view/LocationView.java +++ b/src/main/java/io/rpg/view/LocationView.java @@ -3,6 +3,7 @@ import io.rpg.model.data.KeyboardEvent; import io.rpg.model.data.LocationModelStateChange; import io.rpg.model.location.LocationModel; +import io.rpg.model.object.CollectibleGameObject; import io.rpg.model.object.GameObject; import io.rpg.viewmodel.LocationViewModel; import io.rpg.config.model.LocationConfig; @@ -101,7 +102,6 @@ public void onLocationModelStateChange(LocationModelStateChange event) { List gameObjectViews = new ArrayList<>(); - public void removeChild(GameObjectView view) { viewModel.getForegroundPane().getChildren().remove(view); } diff --git a/src/main/java/io/rpg/viewmodel/InventoryPopupViewModel.java b/src/main/java/io/rpg/viewmodel/InventoryPopupViewModel.java new file mode 100644 index 00000000..89953c95 --- /dev/null +++ b/src/main/java/io/rpg/viewmodel/InventoryPopupViewModel.java @@ -0,0 +1,42 @@ +package io.rpg.viewmodel; + +import javafx.event.EventHandler; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Pane; + +public class InventoryPopupViewModel { + @FXML private Label label; + @FXML private Pane backgroundPane; + @FXML private ImageView backgroundImage; + @FXML private Button okButton; + + public void setText(String text) { + if (text.length() < 50) setTextSize(25); + else if (text.length() < 190) setTextSize(19); + else setTextSize(13); + label.setText(text); + } + + public void setTextSize(int size) { + label.setStyle("-fx-font-family: Monospaced; -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: " + size); + } + + public void setBackgroundImage(String url) { + Image image = new Image(url); + backgroundImage.setImage(image); + } + + public void setOkButtonImage(String url) { + ImageView imageView = new ImageView(url); + okButton.setGraphic(imageView); + } + + public void setButtonOnClick(EventHandler callback) { + okButton.setOnMouseClicked(callback); + } +}