1

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

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

但我确信除了哈希图之外,必须有一种更好更安全的方式来存储这些数据,但不确定是什么。

编辑thx- Philipp (对不起,一个半体面的问题花了这么长时间)

我对使用哈希图存储这些数据的担忧是,有很多数据要放入其中,我们目前使用单行来存储对象的所有数据,例如播放器哈希图中的一行将有播放器id 作为键,带有一个字符串值来存储任何其他内容,例如“hp,xloc,yloc”。然后我们拆分使用。我似乎认为这是存储和检索数据的最有效方式。

对不起,如果这仍然没有意义。

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

谢谢

4

3 回答 3

1

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

每当您需要有关它的一些信息时,您都必须解析字符串,并且字符串解析不是很快,并且当有关每个实体的数据变得更加复杂时,很容易变得非常复杂。

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

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
于 2013-03-21T21:30:10.170 回答
1

内存很好。除非您需要持久化数据,否则不要担心

但是,“我们然后拆分使用”并不好。这是一个微“优化”,实际上会更慢/效率更低:这条路线只有痛苦和浪费的时间。

我不知道您的特定设置,但请考虑一下:

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());

这同样适用于游戏中的其他实体。请注意,地图用于能够找到给定特定 ID 的玩家,但 Player 类的实例包含有关玩家的信息。

查看ProtocolBuffers以进行跨网络的序列化。

于 2013-03-21T21:38:38.557 回答
0

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
}
于 2013-03-21T21:26:21.827 回答