我无法将GameState保存为JSON。
最初我将GameState保存为JSON,如下所示:
Json json = new JSON();
String save = json.prettyPrint(state);
我按如下方式加载它:
json.fromJson(GameState.class, save);
然而,国家没有正确加载,所以我进行了一些测试。我做了以下事情:
class Car
{
public int id;
public Color color;
public Speed speed;
public Car(int id, Color color, Speed speed)
{
this.color = color;
this.id = id;
this.speed = speed;
}
}
class Speed
{
enum ASpeed
{
FAST, MEDIUM, SLOW;
}
ASpeed speed;
public Speed()
{
speed = ASpeed.FAST;
}
}
并在create
@Override
public void create()
{
Json json = new Json();
Car car = new Car(1, Color.RED, new Speed());
String carSave = json.prettyPrint(car);
System.out.println(carSave);
}
我得到的结果是:
{
id:1
color:{
r:1
a:1
}
speed:{}
}
我知道为什么我的游戏没有正确加载;它没有正确序列化。我的GameState
几乎是一个包含3 Array
个数据的类,需要在游戏之间进行。我有常规的getter和setter方法以及几十种实用方法来访问相关数据,如下所示:
//TODO: Possibly add an Array of Event instances to fire for each player when certain circumstances are met as well as a string-based flagging system that can be used in the events.
//TODO: Research threading API in libGdx and see about moving the game logic over to a seperate thread - since this class is used for game logic, consider moving this with it.
public class GameState
{
private Array<Player> players;
private Array<Planet> planets;
private Array<Fleet> fleets;
public GameState(Array<Player> players, Array<Planet> planets, Array<Fleet> fleets)
{
this.players = players;
this.planets = planets;
this.fleets = fleets;
}
public Fleet getFleet(int id)
{
if(id <= fleets.size)
{
return fleets.get(id);
}
return null;
}
public Planet getPlanet(int id)
{
if(id <= planets.size)
{
return planets.get(id);
}
return null;
}
public Player getPlayer(int id)
{
if(id <= players.size)
{
return players.get(id);
}
return null;
}
当然,这不是最好的方法,但我每个字段只有大约100个,并且不打算添加更多,所以这个方法很好用。每个播放器都包含一个Integer
数组,用于获取相关数据。一个例子;
public class Player
{
private final int id;
//libGdx Color used by ShapeRenderer to display planets in the right political color
private Color color;
//Things that the game logic demands be accessible from each Player instance
//TODO: Move these over to the libGdx IntegerArray when you have the time - this will avoid the boxing/unboxing penalty when accessing members.
Array<Integer> allies;
Array<Integer>desiredAllies;
Array<Integer> enemies:
Array<Integer> neutrals;
Array<Integer> planets;
Array<Integer> fleets;
public Player(int id, Color color)
{
this.id = id;
this.color = color;
allies = new Array<Integer>();
planets = new Array<Integer>();
fleets = new Array<Integer>();
neutrals = new Array<Integer>();
enemies = new Array<Integer>();
}
//Getters, Setters, and many, many utility methods.
}
Planet,Player和Fleet类都具有类似的结构,甚至可以实现相同的接口:
public interface IndexedGameObject extends GameObject
{
int getID();
}
我的游戏设计和结构很有效,直到序列化。我专门学习了Json来保存我的游戏,我可能错过了一些东西。 为什么序列化时此设计不起作用?有没有办法让它发挥作用?如果没有,除了编写自己的保存格式外,哪些可能的解决方案可能有用?我在XML方面经验不足,会有用吗?
注意:
我愿意并且能够编写自己的保存格式,但是以一致的,可读的人眼方式这样做会增加大量的开销和维护,并且会浪费时间(因为它类似于写一个非常小的,不是完全功能的语言,我需要做很多一般的测试,以确保它正常工作)和能量,更好地开发和维护一个更直观的用户界面。如果JSON无法满足我的目的,那么还有什么可以吗?
我基本上必须修改我的整个日程安排(是的,我保留了我需要做的事情清单以及我应该做的事情,例如;星期二 - 修复那个烦人的,几乎不可能重新创建按钮消失后学校和家庭作业)。
我的JSON理论上应该有这样的结构;
GameState ->
fleets ->
fleet ->
owner: integer id of the player that owns this fleet.
id: the index of this fleet in the Array
locationID: integer id of the province this fleet is located in.
originalTransports: final integer used for reinforcing.
originalFighters: final integer used for reinforcing.
originalFrigates: final integer used for reinforcing.
originalDreadnaughts: final integer used for reinforcing.
transports: number of troop transports currently in the fleet.
fighters: the number of fighters currently in fleet.
frigates: the number of frigates in this fleet.
dreadnaughts: number of dreadnaughts in the fleet.
players ->
player ->
id: int representing the index of this player in the GameState
provinces: Integer Array representing the provinces owned by this player.
allies: Integer Array representing the index of the other Players allied to this one.
enemies: Integer Array representing the indices of the other players at war with this one.
neutrals: Integer Array representing the players whom this player is neutral to
desiredAllies: Integer Array representing the players who this player desires for allies - used mainly by the ai to determine who to send alliance offers to and who to accept them from.
fleets: Integer Array representing the indices of the fleets of this player
provinces ->
province ->
id: int representing the index of this province
owner: int id of the owning player in the GameState
name: String value. Text displayed on the screen when province selected.
isUnderSiege: boolean. Read the variable name.
colonies ->
colony ->
name: String value. Displayed in the menu when the city is selected from the province info screen that pops up when the province is selected.
controller: The index of the controlling Player in the GameState.
population: int number of people who reside here. Used to calculate things such as how many ships this planet provides, or how much tax it gives to the player.
fortLevel: double representing the amount of organized military resistance this colony will give an attacker before surrendering.
growthRate: the number of births occurring in this colony every 60 ticks.
玩家阵列和舰队正常工作。当我到达省数组时,事情变得奇怪;
{
planets:[
//There should be 300 provinces. Instead 300 of these
colonies: [ {},{},{},{},{},{},{} ]
]
}
我的相关领域的课程看起来像这样;
public class Planet implements IndexedGameObject, Modifier
{
private int id;
private Array<Colony> colonies;
public Planet(int id, Array<Colony> colonies)
{
this.id = id;
this.colonies = colonies;
}
//Utility methods + Getters/Setters
}
class Colony
{
private int parentProvinceID;
private ColonyType type;
public Colony(int parentProvinceID, ColonyType type)
{
this.parentProvinceID = parentProvinceID;
this.type = type;
}
//Some more irrelevant methods
}
enum ColonyType
{
ADMINISTRATIVE, MILITARY, POPULATION;
}
答案 0 :(得分:1)
您的问题是由通用阵列引起的。我想JSON不可能序列化,例如Array<Player>
。
解决方案是包装通用数组 - take a look at this thread或在可能的地方使用非通用数组(例如 FloatArray 而不是数组)。< / p>
另一方面,你的逻辑结构似乎就像关系一样 - meybe使用一些SQL技术而不是将它保存在对象中并序列化/反序列化会更方便吗? Here you have some nutshell info
答案 1 :(得分:0)
我通过创建枚举字段public static
并将它们移动到父类中来解决这个问题 - 我已经忽略了这一点,正如@Barodapride和@ TenFour04指出的那样。
public class Planet
{
private Array<Colony> colonies;
public static class Colony
{
private ColonyType type;
private int parentProvinceID;
public static enum ColonyType
{
ADMINISTRATIVE, MILITARY, POPULATION;
}
}
}
正确序列化。