-
Notifications
You must be signed in to change notification settings - Fork 7
Save Load game
If you are failing the tests in EntityType.java please read the section "Making Your Own Savable Object" towards the bottom of the page
To save simply bring up the menu screen (press escape [Esc]) and click 'Save', the rest will take of it self!
(the in-game terminal may also be used, simply press the F1 key and type 'save')
To load the game simply click the 'continue' button on the main menu or 'load' on the pause screen, this should load you into where you left off!
(the in-game terminal may also be used, simply press the F1 key and type 'load')
The design of the same save/load system involves serialising all important game components and saving them to a file. To achieve this, a GameState class was defined which stores all the key game attributes. This class can be serialised and deserialised using set and get methods in the SaveGame class. In addition to this, all attributes (in the GameState) must implement a serialisable/deserialisable method in order for this system to work. The following class diagram highlights key methods and attributes.
While many file formats exist and can be used for saving the game state, JSON was chosen due to its compatibility with the built-in libgdx functions and it's human readability. The save format can take the form of something like this:
{
"player":{
"Entity":"Player",
"x":11.179355,
"y":21.544378,
"components":{
"InventoryDisplay":{
},
"PlayerActions":{
},
"PlayerAnimationController":{
},
"ColliderComponent":{
},
"InventoryComponent":{
"inventory":{
"item":{
"name":"hoe",
"count":1
}
}
},
"InteractionColliderComponent":{
},
"HitboxComponent":{
},
"AnimationRenderComponent":{
},
"PhysicsComponent":{
}
}
}
}
While many objects have a default serialisation method, the save/load system uses the libgdx JSON functionality. This means that these objects must implement the "serializable" interface (write and read methods). For each game object that needed to be saved, the corresponding read/write methods were implemented accordingly. For example, the entity class requires saving the position vector and array of all the associated components. This meant the write method was required to export this information to the JSON file.
public void write(Json json) {
json.writeValue("Entity", getType());
float posX = position.x;
float posY = position.y;
json.writeValue("x", posX);
json.writeValue("y", posY);
json.writeObjectStart("components");
for (Component c : createdComponents) {
c.write(json);
}
json.writeObjectEnd();
}
This code creates new attributes for Entity type, x position and y position. It then iterates through the entity's components and writes them to the file (according to their implementation of the write method).
Easy Access to Game State
One of the primary design choices made in the development of the save/load system for this game is the decision to keep the save file unobfuscated. This means that the save file is human-readable and easily accessible. Development and Testing: During the game's development phase, having easy access to the game state in a clear and readable format is invaluable. It allows developers to troubleshoot issues, inspect the current state of the game, and customize test cases with ease. This transparency accelerates the debugging and testing process, ultimately leading to a more stable and polished game.
To make a new object savable, it must implement the "Serializable" interface which consists of a read and write method. The specifics are outlined in the libgdx documentation https://libgdx.com/wiki/utils/reading-and-writing-json. From here, any state values (which are to be restored on load) need to specify how they are written to the JSON file in the write method. The corresponding read method restores the state of the object from the given input JSON.
-
For adding new EntityType into the game. Ensure it is added to the below removeLoadableEntities function in GameArea.java. The below function removes these items during the load process before recreating them.
-
The entity type must also be added to the below FactoryService in the appropriate section (e.g. itemFactories or npcFactories or plantFactories)
-
Any new components that have values you need loaded in must also implement the write function. Just view other files for examples on how to accomplish this (e.g. InventoryComponent.java in the public write(Json json) function
-
If you have an entityType that is not being made in the NPC factory you must also add your EntityType to the filterEntities function in SaveGame.java to be filtered out.
-
After making the above correct changes go to EntityTypeTest.java and add your now approved EntityType enum to the list of approvedEnumNames in the unit test testEnumValuesFollowedProcedure().
If you are failing the tests in EntityType.java please read the section "Making Your Own Savable Object" just above this