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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#
.gradle/
build/
bin/

# Explicitly specifed as local
#
Expand Down
Binary file added assets/map.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/map10x10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/map20x20.bmp
Binary file not shown.
Binary file added assets/point-popup-bg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/someDude.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/someDudeButGreen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/stone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ dependencies {
implementation('org.kordamp.ikonli:ikonli-javafx:12.3.0')
implementation('org.kordamp.bootstrapfx:bootstrapfx-core:0.4.0')

implementation('com.google.code.gson:gson:2.9.0')

implementation('org.jetbrains:annotations:23.0.0')

implementation('org.apache.logging.log4j:log4j-api:2.17.2')
implementation('org.apache.logging.log4j:log4j-core:2.17.2')

testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}
Expand All @@ -59,4 +66,4 @@ jlink {

jlinkZip {
group = 'distribution'
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tag": "location-1",
"objects": [
{ "tag": "object-1", "position": { "row": 0, "col": 5 }, "type": "collectible" },
{ "tag": "object-2", "position": { "row": 1, "col": 3 }, "type": "interactive" }
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tag": "object-1",
"assetPath": "/path/to/the/asset",
"type": ""
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tag": "location-2",
"objects": [
{ "tag": "object-1", "position": { "row": 0, "col": 0 } },
{ "tag": "object-3", "position": { "row": 0, "col": 1 } }
]
}
Empty file.
Empty file.
7 changes: 7 additions & 0 deletions configurations/config-1/root.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tag": "GameByConfig1",
"locations": [
"location-1",
"location-2"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tag": "location-1",
"objects": [
{ "tag": "object-1", "position": { "row": 0, "col": 5 } },
{ "tag": "object-2", "position": { "row": 1, "col": 3 } }
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tag": "location-2",
"objects": [
{ "tag": "object-1", "position": { "row": 0, "col": 0 } },
{ "tag": "object-3", "position": { "row": 0, "col": 1 } }
]
}
7 changes: 7 additions & 0 deletions configurations/unit-test-configuration/root.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tag": "test-tag",
"locations": [
"location-1",
"location-2"
]
}
9 changes: 9 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Game configuration

Configuration directory should include:

1. `root.json` file
2. `locations` subdirectory

e.g.

61 changes: 52 additions & 9 deletions src/main/java/io/rpg/HelloApplication.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,66 @@
package io.rpg;

import io.rpg.config.ConfigLoader;
import io.rpg.gui.DisplayLayer;
import io.rpg.model.GameObjectStandIn;
import io.rpg.gui.LocationController;
import io.rpg.gui.model.LocationModel;
import io.rpg.model.*;
import io.rpg.model.GameObject;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configurator;
import javafx.util.Pair;

import java.io.IOException;
import java.net.URL;

public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
Image someMap = new Image("file:assets/map.png");
Image someMap10x10 = new Image("file:assets/map10x10.png");
Image someDude1 = new Image("file:assets/someDude.png");
Image someDude2 = new Image("file:assets/someDudeButGreen.png");
Image player = new Image("file:assets/stone.png");
Game game=new Game();
DisplayLayer displayLayer = new DisplayLayer(stage);
LocationModel locationModel=displayLayer.showLocation();
LocationController locationController=displayLayer.getLocationController();
locationController.setGame(game);
try{
game.addGameObject(new GameObject(new Vector(0,0), someDude1));
game.addGameObject(new GameObject(new Vector(0,5), someDude2));
game.addGameObject(new GameObject(new Vector(5,5), someDude2));
game.addGameObject(new Player(new Vector(7,7), player));
// locationModel=displayLayer.showLocation();
locationModel.setBackgroundImage(someMap);
locationModel.setGame(game);
}catch(Exception e){
e.printStackTrace();
}
AnimationTimer animationTimer=new AnimationTimer() {
long lastUpdate=-1;
@Override
public void handle(long now) {
if(lastUpdate!=-1){
float difference=(now-lastUpdate)/1e6f;
game.update(difference);
locationModel.update(difference);
}
lastUpdate=now;
}

};

public static void main(String[] args) {
launch();
animationTimer.start();
}
}
}
8 changes: 8 additions & 0 deletions src/main/java/io/rpg/config/ConfigConstants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.rpg.config;

final public class ConfigConstants {
public static final String ROOT = "root.json";
public static final String LOCATIONS_DIR = "locations";
public static final String OBJECTS_DIR = "objects";
public static final String ASSETS_DIR = "resources";
}
165 changes: 165 additions & 0 deletions src/main/java/io/rpg/config/ConfigLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package io.rpg.config;

import com.google.gson.Gson;

import io.rpg.model.GameWorldConfig;
import io.rpg.model.location.LocationConfig;

import io.rpg.model.object.GameObjectConfig;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.jetbrains.annotations.NotNull;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.nio.file.Files;
import java.nio.file.Path;

public class ConfigLoader {
@NotNull
private final Gson gson;

@NotNull
private final Path pathToConfigDir;

@NotNull
private final Path pathToRootFile;

@NotNull
private final Path pathToLocationsDir;

public static final String ERR_INVALID_CFG_DIR_PATH = "Could not resolve config directory." +
" Make sure that the config dir path is correct";

public static final String ERR_ROOT_FNF = ConfigConstants.ROOT +
" file was not found inside config directory. Make sure that the file exists and is named properly";

public static final String ERR_LOCATIONS_DIR_FNF = ConfigConstants.LOCATIONS_DIR +
" directory was not found inside configuration directory";

public static final String ERR_LOCATION_DIR_FNF_FOR_TAG =
"Directory was not found for location with tag: ";

public static final String ERR_LOCATION_CFG_NR_FOR_TAG =
"Configuration file was not found for location: ";

@NotNull
private final Logger logger;

public ConfigLoader(@NotNull String configDirPath) {
logger = LogManager.getLogger(ConfigLoader.class);

logger.info("Initializing");

pathToConfigDir = Path.of(configDirPath);
pathToRootFile = pathToConfigDir.resolve(ConfigConstants.ROOT);
pathToLocationsDir = pathToConfigDir.resolve(ConfigConstants.LOCATIONS_DIR);
gson = new Gson();

validate();
}

public void load() {
logger.info("Load");

GameWorldConfig config;
try {
config = loadGameWorldConfig();

logger.info("GameWorldConfig loaded");
logger.info(config.toString());

} catch (FileNotFoundException e) {
throw new RuntimeException(ERR_ROOT_FNF);
}

assert config.getLocations().size() > 0 : "Configuration must specify locations";

for (String locationTag : config.getLocations()) {
try {
logger.info("Loading location config for tag: " + locationTag);

LocationConfig locationConfig = loadLocationConfig(locationTag);

// todo: this should be called in loadLocationConfig method?
// locationConfig.validate();

logger.info("Location config loaded for tag: " + locationTag);
logger.info(locationConfig.toString());


assert locationConfig.getPath() != null : "Path to location dir must be set in its loader";
Path objectsDir = locationConfig.getPath().resolve(ConfigConstants.OBJECTS_DIR);

for (GameObjectConfig gameObjectConfig : locationConfig.getObjects()) {
try {
gameObjectConfig.validate();
} catch (Exception ex) {
String exceptionMessage = ex.getMessage();

logger.warn("Validation for game object config with tag: " +
gameObjectConfig.getTag() + " failed." +
(exceptionMessage != null ? "Reason: " + exceptionMessage : "No reason provided"));
}

// Path GameObjectConfig

}

} catch (FileNotFoundException e) {
logger.warn("Failed to load location config for tag: " + locationTag);
e.printStackTrace();
}
}
}

@NotNull
GameWorldConfig loadGameWorldConfig() throws FileNotFoundException {
logger.info("Loading game world config");
BufferedReader reader = new BufferedReader(new FileReader(pathToRootFile.toString()));
GameWorldConfig config = gson.fromJson(reader, GameWorldConfig.class);

// todo: validate input
// config.validate();

return config;
}

LocationConfig loadLocationConfig(@NotNull String locationTag) throws FileNotFoundException {
logger.info("Loading location: " + locationTag);

Path locationDir = pathToLocationsDir.resolve(locationTag);

if (!Files.isDirectory(locationDir)) {
logger.error(ERR_LOCATION_DIR_FNF_FOR_TAG + locationTag);
throw new FileNotFoundException(ERR_LOCATION_DIR_FNF_FOR_TAG + locationTag);
}

Path locationConfigJson = locationDir.resolve(locationTag + ".json");

if (!Files.isReadable(locationConfigJson)) {
logger.error(ERR_LOCATION_CFG_NR_FOR_TAG + locationTag);
throw new RuntimeException(ERR_LOCATION_DIR_FNF_FOR_TAG + locationTag);
}

BufferedReader reader = new BufferedReader(new FileReader(locationConfigJson.toString()));
LocationConfig config = gson.fromJson(reader, LocationConfig.class);
config.setPath(locationDir);
return config;
}

public void validate() {
if (!Files.isDirectory(pathToConfigDir)) {
logger.error(ERR_INVALID_CFG_DIR_PATH);
throw new IllegalArgumentException(ERR_INVALID_CFG_DIR_PATH);
} else if (!Files.isReadable(pathToRootFile)) {
logger.error(ERR_ROOT_FNF);
throw new IllegalArgumentException(ERR_ROOT_FNF);
} else if (!Files.isDirectory(pathToLocationsDir)) {
logger.error(ERR_LOCATIONS_DIR_FNF);
throw new IllegalArgumentException(ERR_LOCATIONS_DIR_FNF);
}
}
}
Empty file.
32 changes: 32 additions & 0 deletions src/main/java/io/rpg/gui/DisplayLayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.rpg.gui;

import io.rpg.gui.model.LocationModel;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class DisplayLayer {
private final Stage mainStage;
private final LocationController locationController;

public DisplayLayer(Stage mainStage) throws IOException {
this.mainStage = mainStage;
mainStage.show();
locationController = LocationController.load();
}


public LocationModel showLocation(){
// maybe initialize the scene only once
mainStage.setScene(locationController.getScene());
return locationController.getModel().clear();
}

public LocationController getLocationController(){
return locationController;
}
}
Loading