Algunas pruebas más con JSON y el BackEnd.

Se han creado algunas de las clases que conformarán el Backend del juego.
Estas clases no están completas en cuanto a funcionalidad, pero sí los datos.
Se continúa con las pruebas para cargar y guardar todos estos datos en archivos JSON.
This commit is contained in:
2022-05-18 23:18:15 +02:00
parent c652a36ec6
commit 8341662e3d
10 changed files with 538 additions and 112 deletions
+5 -2
View File
@@ -1,3 +1,6 @@
# LibGDX Test Stuff # LibGDX Test Stuff
Repositorio para hacer pruebas del framework LibGDX... Repositorio utilizado para realizar pruebas de LibGDX.
Poca cosa.
Actualmente, se están probando los varios sistemas del BackEnd de un juego. Gestión de los objetos sus datos, así como la carga y guardado de estos mediante JSON.
Poco a poco.
+24
View File
@@ -0,0 +1,24 @@
[
{
"class": "uberelectron.gameSystems.Machine",
"machineID": "base_raspi_mk1",
"attributes": {
"Test": 5,
"Otro": -2
},
"esDeRecursos": true,
"tileSetID": "Machine_Set",
"tilePos": 3
},
{
"class": "uberelectron.gameSystems.Machine",
"machineID": "test_mach2",
"attributes": {
"Otro": -6,
"Test2": 3
},
"esDeRecursos": false,
"tileSetID": "Machine_Set",
"tilePos": 4
}
]
+66
View File
@@ -0,0 +1,66 @@
{
"RoomName": "testRoom",
"RoomSize": {
"x": 8,
"y": 5
},
"BackgroundData": [
[ 2, 2, 2, 2, 2, 2, 2, 2 ],
[ 2, 3, 3, 3, 3, 3, 3, 2 ],
[ 2, 3, 3, 3, 3, 3, 3, 2 ],
[ 2, 3, 3, 3, 3, 3, 3, 2 ],
[ 2, 2, 2, 2, 2, 2, 2, 2 ]
],
"MaquinasData": [
[
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
"base_raspi_mk1",
"test_mach2",
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null
]
]
}
+34 -6
View File
@@ -4,6 +4,20 @@ import com.badlogic.gdx.utils.Null;
import java.util.HashMap; import java.util.HashMap;
/*
ToDo:
- Sistema de Atributos.
- Revisar constructores y sus parámetros.
- Revisar Getters/Setters y privacidad de variables.
- ¿Mover variables arriba?
- ¿?
*/
/***
* Almacena los datos relativos a una máquina.
* @author Daniel García
*/
public class Machine public class Machine
{ {
/*------------- /*-------------
@@ -23,6 +37,11 @@ public class Machine
this.attributes = new HashMap<>(); this.attributes = new HashMap<>();
} }
private Machine(Machine machine)
{
//Privatizamos el constructor de copia.
//No debería ser necesario (Java no hace copias de objetos). Pero por si acaso.
}
/*---------------- /*----------------
* Getters/Setters * Getters/Setters
* -------------*/ * -------------*/
@@ -33,6 +52,14 @@ public class Machine
public boolean isEsDeRecursos() { return esDeRecursos; } public boolean isEsDeRecursos() { return esDeRecursos; }
public void setEsDeRecursos(boolean esDeRecursos) { this.esDeRecursos = esDeRecursos; } public void setEsDeRecursos(boolean esDeRecursos) { this.esDeRecursos = esDeRecursos; }
public HashMap<String, Integer> getAttributes() { return attributes; }
public String getTileSetID() { return tileSetID; }
public void setTileSetID(String tileSetID) { this.tileSetID = tileSetID; }
public int getTilePos() { return tilePos; }
public void setTilePos(int tilePos) { this.tilePos = tilePos; }
/*------------- /*-------------
* Methods * Methods
* -------------*/ * -------------*/
@@ -66,13 +93,14 @@ public class Machine
String machineID; String machineID;
public HashMap<String, Integer> attributes; public HashMap<String, Integer> attributes;
/*
Permite a la room saber si se debe realizar comprobación con la capacidad máxima...
Lo sé, es muy cutre, pero te callas.
Piensa en algo mejor, no te jode...
*/
boolean esDeRecursos; boolean esDeRecursos;
/*
Permiten una asociación sencilla con los datos para el renderizado.
Es más cómodo que usar Enums en código o hardcodear estos valores.
De nada, equipo de frontend.
*/
String tileSetID;
int tilePos;
} }
@@ -1,9 +1,24 @@
package uberelectron.gameSystems; package uberelectron.gameSystems;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
/*
ToDo:
- Comprobar que los archivos (los paths) existen.
*/
/*** /***
* Esta clase carga los datos de las máquinas desde el JSON de datos y almacena los "prefabs" de las mismas. * Carga los datos de las máquinas desde el JSON de datos y almacena los "prefabs" de las mismas.
*
* @author Daniel García
*/ */
public class MachineLoader public class MachineLoader
{ {
@@ -21,26 +36,75 @@ public class MachineLoader
* -------------*/ * -------------*/
/** /**
* Carga del archivo JSON indicado con los datos de cada máquina. * Carga una lista de máquinas desde el archivo JSON.
* @param path Ubicación del JSON * @param path Ubicación del JSON (Path interno).
*/ */
public void LoadFile(String path) public void LoadFromJSON(String path)
{ {
//TODO: Itera por las máquinas, cargándolas. //Cargamos las máquinas en un ArrayList.
Json json = new Json();
FileHandle file = Gdx.files.internal(path);
ArrayList<Machine> list = json.fromJson(ArrayList.class, file);
//Iteramos y añadimos las máquinas al mapa identificadas por su ID.
for(Machine mc : list)
{
machineMap.put(mc.getMachineID(), mc);
} }
//Limpiamos.
list.clear();
}
/***
* Permite guardar el estado del machineLoader (las máquinas del mapa) a un JSON.
* Utilizado para debug o herramientas de desarrollo.
* @param path Ubicación en que guardar el JSON (Path local).
*/
public void SaveToJSON(String path)
{
//Creamos y configuramos el serializador.
Json json = new Json();
json.setOutputType(JsonWriter.OutputType.json);
json.setUsePrototypes(false);
//Obtenemos una lista de las máquinas almacenadas y las convertimos en JSON.
Collection<Machine> mcList = machineMap.values();
String jsonData = json.toJson(mcList);
//Abrimos el archivo y escribimos los datos.
FileHandle file = Gdx.files.local(path);
file.writeString(json.prettyPrint(jsonData), false);
}
/***
* Añade al mapa la máquina pasada por parámetro. Utiliza el ID de la máquina como Key.
* @param machineToAdd Máquina que añadir al mapa.
*/
public void AddMachine(Machine machineToAdd) public void AddMachine(Machine machineToAdd)
{ {
machineMap.put(machineToAdd.machineID, machineToAdd); machineMap.put(machineToAdd.machineID, machineToAdd);
} }
/***
* Permite obtener un puntero a una máquina dado su ID.
* @param machineID ID de la máquina a obtener.
* @return Puntero a la máquina pedida.
*/
public Machine GetMachine(String machineID) public Machine GetMachine(String machineID)
{ {
Machine mc = machineMap.get(machineID); Machine mc = machineMap.get(machineID);
if(mc == null) if(mc == null)
{ {
System.err.println("El mapa no contiene una máquina de ID: " + machineID); System.out.println("El mapa no contiene una máquina de ID: " + machineID);
} }
if(!mc.getMachineID().equals(machineID))
{
System.err.println("Hay una inconsistencia en los IDs de máquina: "
+ mc.getMachineID() + "!=" + machineID);
}
return mc; return mc;
} }
@@ -49,6 +113,6 @@ public class MachineLoader
/*------------- /*-------------
* Variables * Variables
* -------------*/ * -------------*/
HashMap<String, Machine> machineMap; private HashMap<String, Machine> machineMap;
} }
+10 -83
View File
@@ -10,8 +10,12 @@ import java.util.HashMap;
de esta forma, si no quedan huecos, ComprobarMaquina() retorna false. No es necesario serializarlo. de esta forma, si no quedan huecos, ComprobarMaquina() retorna false. No es necesario serializarlo.
*/ */
/***
public class Room implements Json.Serializable * Clase que contiene los datos de la Sala y realiza permite interactuar con ellos.
*
* @author Daniel García.
*/
public class Room
{ {
/*------------- /*-------------
* Constructors * Constructors
@@ -68,6 +72,7 @@ public class Room implements Json.Serializable
public void AddMachine(int x, int y, Machine machineToAdd) public void AddMachine(int x, int y, Machine machineToAdd)
{ {
//Comprobamos si tenemos los recursos suficientes para añadir la máquina. //Comprobamos si tenemos los recursos suficientes para añadir la máquina.
if(!ComprobarMaquina(machineToAdd)) if(!ComprobarMaquina(machineToAdd))
{ {
@@ -92,7 +97,6 @@ public class Room implements Json.Serializable
// Con unos if-else comprobamos/añadimos en el que corresponda según sea la máquina. // Con unos if-else comprobamos/añadimos en el que corresponda según sea la máquina.
public boolean ComprobarCapacidad(String attribute, int valorComprobar) public boolean ComprobarCapacidad(String attribute, int valorComprobar)
{ {
Integer max = recursosMaximos.get(attribute); Integer max = recursosMaximos.get(attribute);
if(max == null) if(max == null)
{ {
@@ -135,11 +139,13 @@ public class Room implements Json.Serializable
// int height; // int height;
Vector2 roomSize; Vector2 roomSize;
//Permite saber de qué tileSet son los ints de bgData.
String tileSetID;
int[][] bgData; int[][] bgData;
Machine[][] machineData; Machine[][] machineData;
//Únicamente, para probar la serialización como array. //Únicamente, para probar la serialización como array.
String[][] machineData_Test; //String[][] machineData_Test;
//Atributos de la sala. //Atributos de la sala.
@@ -149,83 +155,4 @@ public class Room implements Json.Serializable
HashMap<String, Integer> recursosMaximos; HashMap<String, Integer> recursosMaximos;
boolean esOnline = false; boolean esOnline = false;
//ToDo: Esto hay que moverlo a RoomLoader y ponerlo como Json.Serializer<Room> pues en RoomLoader tenemos un ptr a Game.MachineLoader
// y por tanto podemos pedir las máquinas directamente. La otra forma es que Game sea un Singleton...
@Override
public void write(Json json)
{
//Crearlo como un objeto puede venir bien si lo vamos a tener junto a otros datos externos.
// Hay que tener cuidado no rompamos el Read.
//json.writeObjectStart("Room");
json.writeValue("RoomName", roomName);
json.writeValue("RoomSize", roomSize);
json.writeValue("BackgroundData", bgData);
//Datos de máquinas.
json.writeArrayStart("MaquinasData");
for(int y = 0; y < machineData.length; y++)
{
json.writeArrayStart();
for(int x = 0; x < machineData[y].length; x++)
{
//Sólo nos interesa el ID de la máquina,
Machine mc = machineData[y][x];
if(mc == null)
{
json.writeValue(null);
} else {
json.writeValue(mc.machineID);
}
}
json.writeArrayEnd();
}
json.writeArrayEnd();
//json.writeObjectEnd();
//En principio, los recursos ocupados/disponibles los podemos reconstruir al cargar a
// partir de las máquinas que haya.
}
@Override
public void read(Json json, JsonValue jsonData)
{
//jsonData = jsonData.child();
roomName = jsonData.get("RoomName").asString();
roomSize = new Vector2();
roomSize.x = jsonData.get("RoomSize").get("x").asFloat();
roomSize.y = jsonData.get("RoomSize").get("y").asFloat();
//ToDo: En principio, bgData es el tamaño de la sala (el grid de máquinas) + 2 (para paredes).
bgData = new int[(int)roomSize.y][(int)roomSize.x];
for(int y = 0; y < bgData.length; y++)
{
bgData[y] = jsonData.get("BackgroundData").get(y).asIntArray();
}
machineData = new Machine[(int)roomSize.y][(int)roomSize.x];
machineData_Test = new String[(int)roomSize.y][(int)roomSize.x];
//ToDO: Revisar si el bucle de JsonValue.java es más eficiente.
for (int y = 0; y < machineData.length; y++)
{
//Obtenemos el array de esta "y".
JsonValue yData = jsonData.get("MaquinasData").get(y);
// yData = yData.child;
//
// for (; yData != null; yData = yData.next)
// {
// String val = yData.asString();
// }
for(int x = 0; x < machineData[y].length; x++)
{
//ToDo: En vez de guardar al String, se debería obtener un ptr a la máquina en cuestión desde MachineLoader.
machineData_Test[y][x] = yData.get(x).asString();
}
}
//Luego cargamos el resto... Si es que lo hay.
}
} }
@@ -0,0 +1,258 @@
package uberelectron.gameSystems;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonValue;
import com.badlogic.gdx.utils.JsonWriter;
import java.util.HashMap;
/*
ToDo:
- Cuestiones de "Privacidad" de variables.
- Revisar que los Ptrs son Ptrs.
- Comprobar que los archivos (los paths) existen.
*/
/***
* Clase encargada de gestionar las diferentes salas:
* Cargarlas, guardarlas, almacenarlas, ...
* Cada sala está guardada en su propio JSON.
*
* @author Daniel García.
*/
public class RoomLoader
{
public RoomLoader()
{
currentRoom = null;
loadedRooms = new HashMap<>();
mcLoader = null;
loaderJson = new Json();
loaderJson.setSerializer(Room.class, roomSerializer);
}
public RoomLoader(MachineLoader mcLoader)
{
currentRoom = null;
loadedRooms = new HashMap<>();
this.mcLoader = mcLoader;
loaderJson = new Json();
loaderJson.setSerializer(Room.class, roomSerializer);
}
/***
* Carga una Room desde un archivo.
* @param path Ubicación del archivo JSON de datos de la Room.
*/
public void LoadRoomFromJSON(String path)
{
FileHandle file = Gdx.files.internal(path);
Room r = loaderJson.fromJson(Room.class, file);
loadedRooms.put(r.roomName, r);
System.out.println("Se ha cargado la Room " + r.roomName + " correctamente.");
}
/***
* Guarda la Room indicada al archivo indicado.
* @param roomID ID de la Room a guardar.
* @param path Ubicación del archivo JSON de destino.
*/
public void SaveRoomToJSON(String roomID, String path)
{
Room rSave = loadedRooms.get(roomID);
if(rSave == null)
{
System.err.println("No es posible guardar la Room: " + roomID +
"; ¿Está cargada?");
return;
}
String data = loaderJson.toJson(rSave);
FileHandle file = Gdx.files.local(path);
file.writeString(loaderJson.prettyPrint(data), false);
System.out.println("Se ha guardado la room " + roomID + " en " + path);
}
/***
* Descarga una Room dado su ID.
* @param roomID ID de la Room a descargar.
*/
public void UnloadRoom(String roomID)
{
loadedRooms.remove(roomID);
//¿Habría que matar al objeto manualmente?
//¿Quizás debamos hacerlo un recurso de LibGDX para poder matarlo?
}
/***
* Permite saber si una Room está cargada.
* @param roomID ID de la Room a comprobar.
* @return True si está cargada, False si no lo está.
*/
public boolean isRoomLoader(String roomID)
{
return loadedRooms.containsKey(roomID);
}
/***
* Establece la Room activa.
* La Room debe estar cargada para poder ser la activa.
* @param roomID ID de la Room Activa.
*/
public void SetCurrentRoom(String roomID)
{
Room r = loadedRooms.get(roomID);
if(r == null)
{
System.err.println("No se puede activar la room " + roomID + " ; No está cargada.");
}
currentRoom = r;
}
/***
* Devuelve la Room actualmente activa.
* @return Ptr a la Room actualmente activa.
*/
public Room GetCurrentRoom()
{
return currentRoom;
}
//DEBUG: Para hacer pruebas desde BackEndTest.java.
public void AddRoom(Room rToAdd)
{
loadedRooms.put(rToAdd.roomName, rToAdd);
}
/*-------------
* Variables
* -------------*/
Room currentRoom;
HashMap<String, Room> loadedRooms;
//ToDo: Revisar si lo dejamos así o lo sacamos directamente desde Game.
MachineLoader mcLoader;
Json loaderJson;
Json.Serializer<Room> roomSerializer = new Json.Serializer<Room>()
{
@Override
public void write(Json json, Room object, Class knownType)
{
//Crearlo como un objeto puede venir bien si lo vamos a tener junto a otros datos externos.
// Hay que tener cuidado no rompamos el Read.
json.setOutputType(JsonWriter.OutputType.json);
json.writeObjectStart();
json.writeValue("RoomName", object.roomName);
json.writeValue("RoomSize", object.roomSize);
json.writeValue("BackgroundData", object.bgData);
//Datos de máquinas. Creamos un JSON array bidimensional.
json.writeArrayStart("MaquinasData");
for(int y = 0; y < object.machineData.length; y++)
{
json.writeArrayStart();
for(int x = 0; x < object.machineData[y].length; x++)
{
//Almacenamos el ID de la máquina.
Machine mc = object.machineData[y][x];
if(mc == null)
{
//Si no hay máquina será un Null.
json.writeValue(null);
} else
{
json.writeValue(mc.machineID);
}
}
json.writeArrayEnd();
}
json.writeArrayEnd();
json.writeObjectEnd();
//En principio, los recursos ocupados/disponibles los podemos reconstruir al cargar a
// partir de las máquinas que haya en la sala.
// Quizás habría que crear un método en Room que hiciera eso.
}
@Override
public Room read(Json json, JsonValue jsonData, Class type)
{
//Instanciamos la nueva sala y modificaremos sus variables.
Room room = new Room();
//jsonData = jsonData.child();
room.roomName = jsonData.get("RoomName").asString();
room.roomSize = new Vector2();
room.roomSize.x = jsonData.get("RoomSize").get("x").asFloat();
room.roomSize.y = jsonData.get("RoomSize").get("y").asFloat();
//ToDo: En principio, bgData debería ser el tamaño de la sala (el grid de máquinas) + 2 (para paredes).
room.bgData = new int[(int)room.roomSize.y][(int)room.roomSize.x];
for(int y = 0; y < room.bgData.length; y++)
{
room.bgData[y] = jsonData.get("BackgroundData").get(y).asIntArray();
}
/*
Cargamos los datos relativos a las máquinas.
Únicamente guardamos su ID, pues lo que nos interesa guardar en la sala es un ptr.
Las máquinas reales viven dentro del mcLoader.
*/
room.machineData = new Machine[(int)room.roomSize.y][(int)room.roomSize.x];
//room.machineData_Test = new String[(int)room.roomSize.y][(int)room.roomSize.x];
//ToDO: Revisar si el bucle de JsonValue.java es más eficiente.
for (int y = 0; y < room.machineData.length; y++)
{
//Obtenemos el array de esta "y".
JsonValue yData = jsonData.get("MaquinasData").get(y);
for(int x = 0; x < room.machineData[y].length; x++)
{
//ToDo: Revisar el acceso al mcLoader....
String mcName = yData.get(x).asString();
//En caso de que no haya máquina (en el JSON haya null) -> Establecemos Null.
// TODO: Recuerda que los null de JSON devuelven un objeto null.
if(mcName == null)
{
//Nos podemos saltar la asignación... (Java por defecto establece null al crear el Array).
room.machineData[y][x] = null;
continue;
}
//Obtenemos un ptr a la máquina que corresponda.
room.machineData[y][x] = mcLoader.GetMachine(mcName);
//room.machineData_Test[y][x] = yData.get(x).asString();
}
}
// ToDo: Los atributos de la sala se generan al cargar la sala contando las máquinas que haya.
return room;
}
};
}
@@ -0,0 +1,19 @@
package uberelectron.gameSystems;
import java.util.HashMap;
/***
* Clase contenedora para los datos de guardado de la partida.
*
* @author Daniel García.
*/
public class Save
{
int dinero;
/*
Indica si el jugador tiene comprada esa sala y, por tanto, ha de aparecer/cargarse.
*/
HashMap<String, Boolean> ownedRoom;
}
+51 -14
View File
@@ -3,12 +3,20 @@ package uberelectron.testgame;
import com.badlogic.gdx.Screen; import com.badlogic.gdx.Screen;
import com.badlogic.gdx.utils.Json; import com.badlogic.gdx.utils.Json;
import uberelectron.gameSystems.Machine; import uberelectron.gameSystems.Machine;
import uberelectron.gameSystems.MachineLoader;
import uberelectron.gameSystems.Room; import uberelectron.gameSystems.Room;
import uberelectron.gameSystems.RoomLoader;
public class BackEndTest implements Screen public class BackEndTest implements Screen
{ {
final testGame game; final testGame game;
public static MachineLoader mcLoader = new MachineLoader();
/***
* Clase para la realización de pruebas del BackEnd.
* Carga, guardado y gestión de los diversos datos.
* @param game Ptr a la clase Game.
*/
public BackEndTest(final testGame game) public BackEndTest(final testGame game)
{ {
this.game = game; this.game = game;
@@ -18,28 +26,57 @@ public class BackEndTest implements Screen
testMach.AddAtribute("Test", 5); testMach.AddAtribute("Test", 5);
testMach.AddAtribute("Otro", -2); testMach.AddAtribute("Otro", -2);
testMach.setEsDeRecursos(true); testMach.setEsDeRecursos(true);
testMach.setTileSetID("Machine_Set");
testMach.setTilePos(3);
Json json = new Json(); Machine mach2 = new Machine();
String text = json.toJson(testMach); mach2.setMachineID("test_mach2");
mach2.AddAtribute("Test2", 3);
mach2.AddAtribute("Otro", -6);
mach2.setEsDeRecursos(true);
mach2.setTileSetID("Machine_Set");
mach2.setTilePos(4);
System.out.println(json.prettyPrint(text)); /*
---- MachineLoader Tests.
*/
Machine mkLoad = json.fromJson(Machine.class, text); //mcLoader = new MachineLoader();
mcLoader.AddMachine(testMach);
mcLoader.AddMachine(mach2);
Room testRoom = new Room("testRoom", 8, 5); // mcLoader.SaveToJSON("assets/data/testMachines.json");
testRoom.LoadRoom(); // mcLoader.LoadFromJSON("data/testMachines.json");
testRoom.AddMachine(5,3, testMach); //
testRoom.AddMachine(6,3, mkLoad); // Machine recuperar = mcLoader.GetMachine("base_raspi_mk1");
// System.out.println("Pues eso...");
String textRoom = json.toJson(testRoom); /*
System.out.println(json.prettyPrint(textRoom)); ------ RoomLoader Tests
*/
Room loadedRoom = json.fromJson(Room.class, textRoom); RoomLoader rmLoader = new RoomLoader(mcLoader);
rmLoader.LoadRoomFromJSON("data/testRoom.json");
System.out.println("Pues eso...");
// Room testRoom = new Room("testRoom", 8, 5);
// testRoom.LoadRoom();
// testRoom.AddMachine(3,2, testMach);
// testRoom.AddMachine(4,2, mach2);
//
// rmLoader.AddRoom(testRoom);
// rmLoader.SaveRoomToJSON("testRoom", "assets/data/testRoom.json");
//
// String textRoom = json.toJson(testRoom);
// System.out.println(json.prettyPrint(textRoom));
//
// Room loadedRoom = json.fromJson(Room.class, textRoom);
//
// System.out.println("Pues eso...");
System.out.println("Prueba completada.");
} }