Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ dependencies {

testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
testImplementation("org.junit.jupiter:junit-jupiter-params:${junitVersion}")
testImplementation("org.mockito:mockito-core:3.+")
}

test {
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/io/rpg/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import io.rpg.controller.Controller;
import io.rpg.model.actions.Action;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Game {
Expand All @@ -20,7 +19,7 @@ public void setController(Controller controller) {
public void start(Stage stage) {
stage.show();
controller.setMainStage(stage);
controller.onAction(onStart);
controller.consumeAction(onStart);
}

public static class Builder {
Expand Down
31 changes: 16 additions & 15 deletions src/main/java/io/rpg/controller/Controller.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.rpg.controller;

import io.rpg.model.actions.Action;
import io.rpg.model.actions.ActionConsumer;
import io.rpg.model.actions.LocationChangeAction;
import io.rpg.model.data.KeyboardEvent;
import io.rpg.model.data.MouseClickedEvent;
Expand All @@ -12,10 +13,10 @@
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;
import javafx.scene.input.MouseButton;
import javafx.stage.Stage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand All @@ -24,7 +25,7 @@
import java.util.LinkedHashMap;
import java.util.List;

public class Controller implements KeyboardEvent.Observer, MouseClickedEvent.Observer {
public class Controller implements KeyboardEvent.Observer, MouseClickedEvent.Observer, ActionConsumer {
private Scene currentView;
private LinkedHashMap<String, LocationModel> tagToLocationModelMap;
private LocationModel currentModel;
Expand Down Expand Up @@ -68,7 +69,8 @@ public void setView(Scene currentView) {
this.currentView = currentView;
}

public void onAction(Action action) {
@Override
public void consumeAction(Action action) {
Class<?>[] args = {action.getClass()};
Method onSpecificAction;

Expand Down Expand Up @@ -146,7 +148,7 @@ public void onKeyboardEvent(KeyboardEvent event) {
case F -> popupController.openPointsPopup(5, getWindowCenterX(), getWindowCenterY());
case G -> popupController.openTextPopup("Hello!", getWindowCenterX(), getWindowCenterY());
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 -> onAction((Action) new LocationChangeAction("location-2", new Position(1, 2)));
case L -> consumeAction((Action) new LocationChangeAction("location-2", new Position(1, 2)));
}
}
// } else if (payload.getEventType() == KeyEvent.KEY_RELEASED) {
Expand All @@ -171,15 +173,13 @@ public void onMouseClickedEvent(MouseClickedEvent event) {
.orElseThrow(() -> new RuntimeException("No object present at position " + position));

double distance = playerPos.distance(objectView.getPosition());
if (distance < 1.5) {
if (object instanceof InteractiveGameObject) {
((InteractiveGameObject) object).onAction();
}

if (object instanceof CollectibleGameObject) {
popupController.openTextImagePopup("Picked up an item!", objectView.getImage(), getWindowCenterX(), getWindowCenterY());
objectView.setVisible(false);
currentModel.removeGameObject(object);
if (distance < 1.5) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the distance measured by squares? if yes, then 1.5 squares means i can pick up an item that is not adjacent to my square and this should not happen

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into it

MouseButton button = event.payload().getButton();
if (button.equals(MouseButton.PRIMARY)) {
object.onLeftClick();
} else if (button.equals(MouseButton.SECONDARY)) {
object.onRightClick();
}
}

Expand All @@ -190,6 +190,7 @@ public PlayerController getPlayerController() {
return playerController;
}


public static class Builder {
private final Controller controller;

Expand All @@ -203,6 +204,9 @@ public Controller build() {
throw new IllegalStateException(validationResult.getErrorValue());
}

controller.tagToLocationModelMap.values().forEach(location -> location.setActionConsumer(controller));
controller.playerController.getPlayer().setActionConsumer(controller);

return controller;
}

Expand All @@ -228,7 +232,4 @@ public void setPlayerController(PlayerController playerController) {
controller.playerController = playerController;
}
}
public LocationModel getCurrentModel() {
return currentModel;
}
}
1 change: 1 addition & 0 deletions src/main/java/io/rpg/model/actions/Action.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
* A marker interface for action classes.
*/
public interface Action {
Action VOID = new Action() {};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should other types of actions be initiated here or is that just for VOID?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only for VOID

}
5 changes: 5 additions & 0 deletions src/main/java/io/rpg/model/actions/ActionConsumer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.rpg.model.actions;

public interface ActionConsumer {
void consumeAction(Action action);
}
5 changes: 5 additions & 0 deletions src/main/java/io/rpg/model/actions/ActionEmitter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.rpg.model.actions;

public interface ActionEmitter {
void setActionConsumer(ActionConsumer actionConsumer);
}
14 changes: 14 additions & 0 deletions src/main/java/io/rpg/model/actions/BaseActionEmitter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.rpg.model.actions;

public abstract class BaseActionEmitter implements ActionEmitter {
private ActionConsumer consumer = (a) -> {};

protected void emitAction(Action action) {
consumer.consumeAction(action);
}

@Override
public void setActionConsumer(ActionConsumer actionConsumer) {
this.consumer = actionConsumer;
}
}
11 changes: 9 additions & 2 deletions src/main/java/io/rpg/model/location/LocationModel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.rpg.model.location;

import io.rpg.model.actions.ActionConsumer;
import io.rpg.model.actions.BaseActionEmitter;
import io.rpg.model.data.LocationModelStateChange;
import io.rpg.model.data.Position;
import io.rpg.model.object.GameObject;
Expand All @@ -18,15 +20,15 @@
/**
* Represents single location in our game.
*/
public class LocationModel implements LocationModelStateChange.Emitter {
public class LocationModel extends BaseActionEmitter implements LocationModelStateChange.Emitter {
private String tag;
private List<GameObject> gameObjects;
private final HashMap<GameObject, ChangeListener<Point2D>> positionListeners;
private final HashMap<Position, GameObject> positionGameObjectMap;
public final Point2D bounds;

private final Set<LocationModelStateChange.Observer> locationModelStateChangeObservers;


public LocationModel(@NotNull String tag, @NotNull List<GameObject> gameObjects) {
this();
this.tag = tag;
Expand Down Expand Up @@ -158,6 +160,11 @@ public void emitLocationModelStateChange(LocationModelStateChange event) {
});
}

@Override
public void setActionConsumer(ActionConsumer actionConsumer) {
super.setActionConsumer(actionConsumer);
gameObjects.forEach((g) -> g.setActionConsumer(actionConsumer));
}

public Result<Void, Void> validate() {
if (tag == null || gameObjects == null) {
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/io/rpg/model/object/GameObject.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package io.rpg.model.object;

import io.rpg.model.actions.Action;
import io.rpg.model.actions.BaseActionEmitter;
import io.rpg.model.data.GameObjectStateChange;
import io.rpg.model.data.Position;
import java.lang.reflect.Field;
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;
Expand All @@ -17,12 +18,14 @@
* Class representing common state properties for all
* objects appearing in the game.
*/
public class GameObject implements GameObjectStateChange.Emitter {
public class GameObject extends BaseActionEmitter implements GameObjectStateChange.Emitter {

/**
* Position of game object in model's representation of location.
*/
private final SimpleObjectProperty<Point2D> exactPositionProperty;
private Action onRightClickAction;
private Action onLeftClickAction;

/**
* Unique identifier of this game object.
Expand All @@ -47,6 +50,8 @@ 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));
this.onLeftClickAction = Action.VOID;
this.onRightClickAction = Action.VOID;
}

/**
Expand Down Expand Up @@ -117,7 +122,21 @@ public void setPosition(Position playerPosition) {
setExactPosition(new Point2D(playerPosition.col, playerPosition.row));
}

public void setOnRightClickAction(Action onRightClickAction) {
this.onRightClickAction = onRightClickAction;
}

public void setOnLeftClickAction(Action onLeftClickAction) {
this.onLeftClickAction = onLeftClickAction;
}

public void onRightClick() {
emitAction(onRightClickAction);
}

public void onLeftClick() {
emitAction(onLeftClickAction);
}

public enum Type {
NAVIGABLE("navigable"),
Expand Down
47 changes: 47 additions & 0 deletions src/test/java/io/rpg/model/location/LocationModelTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.rpg.model.location;

import io.rpg.model.actions.Action;
import io.rpg.model.actions.ActionConsumer;
import io.rpg.model.data.Position;
import io.rpg.model.object.GameObject;
import java.util.ArrayList;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

class LocationModelTest {

private LocationModel locationModel;

@BeforeEach
void setUp() {
LocationModel.Builder builder = new LocationModel.Builder();
locationModel = builder
.setGameObjects(new ArrayList<>())
.setTag("test")
.build();
}


@Test
void whenCallingSetActionConsumer_shouldSetActionConsumerForGameObjects() {
GameObject object1 = new GameObject("obj1", new Position(1,1));
GameObject object2 = new GameObject("obj2", new Position(2,1));

locationModel.addGameObject(object1);
locationModel.addGameObject(object2);

ActionConsumer consumer = Mockito.mock(ActionConsumer.class);
locationModel.setActionConsumer(consumer);

Action action = Action.VOID;

object1.setOnRightClickAction(action);
object1.onRightClick();
Mockito.verify(consumer, Mockito.times(1)).consumeAction(action);

object2.setOnRightClickAction(action);
object2.onRightClick();
Mockito.verify(consumer, Mockito.times(2)).consumeAction(action);
}
}