在服务器端为Java多层自上而下的游戏存储数据的最佳方式



我和一些朋友正在用Java制作一个自上而下的射击游戏,并希望使其在线,我们已经设置了一个UDP套接字连接,该连接工作良好,但我们不确定如何存储我们从客户端收到的数据。

目前我们正在使用一些哈希映射来存储数据,例如我们有三个哈希映射用于玩家跟踪,游戏信息(玩家数量等)和子弹(子弹位置,谁开火等)。

但我确信一定有更好更安全的方式来存储这些数据,而不是hashmap,但不确定是什么。

编辑谢谢Philipp(很抱歉花了这么长时间才提出一个像样的问题)

我对使用哈希映射来存储这些数据的担忧是,有相当多的数据要放入其中,我们目前使用单行来存储对象的所有数据,例如,玩家哈希映射中的一行将以玩家id为键,用字符串值来存储其他任何东西,如"hp,xloc,yloc"。然后我们分开使用。我似乎不认为这是最有效的方式来存储和检索数据。

如果你还是不明白的话,很抱歉。

我想我真正的问题是有没有更有效的替代方案,或者如果哈希映射是最好的方法?

谢谢

正如你自己发现的那样,将游戏中每个实体的数据存储在字符串中并不是一个好主意。

当你需要一些关于字符串的信息时,你必须解析字符串,字符串解析不是很快,当每个实体的数据变得更复杂时,字符串解析很容易变得相当复杂。

一个更好的方法是为每个实体类型创建一个类,并使用一组类变量来存储每个实体的数据:

class Player {
    public: 
         int positionX;
         int positionY;
         int lifes;
         String name;
         //...
}

(顺便说一下:经验丰富的面向对象程序员会将这些变量声明为私有变量,并使用getter和setter方法来更改它们,但现在我们不走那么远)

你的哈希映射将存储这个类的实例:

 HashMap<Integer, Player> players;

设置这些很容易:

 Player p = new Player();
 p.positionX = 200;
 p.positionY = 400;
 p.lifes = 3;
 p.name = "Ford Prefect";
 players.put(42, p);

(顺便说一下:有经验的OOP程序员会使用构造函数)

你可以通过访问哈希图来设置和获取每个玩家的变量:

 players.get(42).positionX += 10; // move player 42 10 pixels to the right

内存可以。除非需要持久化数据,否则不用担心

然而,"我们然后分割使用"是不是。这是一个微"优化",实际上会更慢/效率更低:这条路除了痛苦和浪费的时间之外什么都没有。

我不知道你的具体设置,但考虑一下:

class Player {
   public Player (int playerId) {
      this.playerId = playerId;
   }
   // ID during game - not permanent; for link-back to Hash key
   public final int playerId;
   // Add methods and fields as appropriate
   String name;
   int health;
   // position, armour color, fairy dust, etc.
}
// How ids are "connected" to players:
//   playerId -> Player
Map<Integer,Player> players = new HashMap..;
// When a player "connects"
int playerId = getUniqueIdForGameInstance();
Player player = new Player(playerId); // setup other information as required
players.add(player.playerId, player);
// On attack ..
int attackerId = getAttackerFromClient();
int targetId = getTargetFromClient();
Player attacker = players.get(attackerId);
Player target = players.get(targetId);
target.getWumped(attacker.wumpStength());

同样也适用于游戏中的其他实体。注意,Map用于查找给定特定ID的玩家,但是player类的实例保存有关玩家的信息。

查看跨线序列化的协议缓冲区。

hashmap是一个好的解决方案-它们是线程安全的,所以假设你没有10,000个用户同时访问你的网站,它们应该为你工作。

然而,目前你所有的数据都存储在内存中。如果程序终止,这是一个问题。

我能给出的最简单的建议是将HashMaps写入文件。这在Java中是通过在类声明中添加Serializable接口来实现的——但是对于HashMap不需要这样做,因为它已经是可序列化的。(您只需要为存储在HashMap中的您编写的类执行此操作。)

则只需在main()方法中添加以下代码(用于从文件中读取):

try {
  FileInputStream fis = new FileInputStream("Game.sav");
  ObjectInputStream ois = new ObjectInputStream(fis);
  HashMap<K,V> loadedGame = (HashMap<K,V>) ois.readObject();
} catch (Exception e) {
       // Create new hash maps (no HashMap files found)
}

和这个saveGame()方法,可以在你的判断调用

try {
  FileOutputStream fos = new FileOutputStream("Game.sav");
  ObjectOutputStream oos = new ObjectOutputStream(fos);
  o.writeObject(hashmapGameVariable);
  o.close();
} catch (IOException ioe) {
  ioe.printStackTrace(); // something went wrong, you may not have write premissions
}

最新更新