【问题标题】:node.js storing gamestate, how?node.js 存储游戏状态,如何?
【发布时间】:2011-01-15 20:04:27
【问题描述】:

我正在用 javascript 编写一个游戏,为了防止作弊,我让游戏在服务器上玩(这是一个棋盘游戏,就像一个更复杂的跳棋)。由于游戏相当复杂,我需要存储游戏状态以验证客户端操作。

是否可以将游戏状态存储在内存中?这很聪明吗?我应该这样做吗?如果是这样,怎么做?我不知道那会怎样。

我也可以存储在redis中。这种事情对我来说很熟悉,不需要解释。但是如果我确实存储在 redis 中,问题是在每一步中,游戏都需要从 redis 获取数据并解释和解析这些数据,以便从头开始重新创建游戏状态。但是由于动作频繁发生,这对我来说似乎很愚蠢。

我该怎么办?

【问题讨论】:

  • 这与 JavaScript 没有任何关系。您基本上只需要一个可以处理所有不同连接客户端的服务器,并且由于程序在内存中执行,它会很快!仅当您需要“保存”游戏时,才将游戏状态保存到数据库中。用代码表示你的游戏状态!
  • @Marcus 谢谢,我正在寻求有关实施的建议,因为这对我来说并不那么明显。如何在代码中表示游戏状态?
  • @expressnoob 变量和类。这些是工具,使用它们来表示游戏中的对象,例如GamePlayerPiece 等。设计取决于您并针对您的游戏。
  • @Marcus 如何让它们在每个单独游戏的服务器上持久存在?
  • @expressnoob 为服务器可能正在编排的每个游戏创建一个单独的Thread,并为每个游戏提供一个Game 的实例,然后如果持久性意味着在服务器关闭后,您可以序列化您所有的对象并将它们保存到文件(或数据库)或以更定制的方式将其转换为数据库表。

标签: javascript database node.js


【解决方案1】:

如果您真的不想要 I/O 的开销,那么只需将游戏状态存储在由游戏 id 键入的全局对象中:

var global_gamesate = {}

然后在每个连接上检查游戏 ID 以检索他的游戏状态:

var gamestate = global_gamestate[game_id];

大概您已经有了一种将客户端会话映射到游戏 ID 的机制。

通常,游戏状态很小,几乎不会占用太多 RAM。让我们悲观一点,假设每个游戏状态占用 500K。然后,您可以为服务器上的每 GB RAM 提供两 百万 千游戏(如果我们假设每个游戏有两个用户,则为四个 百万 千用户)。


但是,我想指出,像 MySQL 这样的数据库已经实现了缓存(这是可配置的),因此加载最常用的数据基本上是从 RAM 加载的,而套接字 I/O 开销很小。数据库的优点是您可以拥有比 RAM 更多的数据,因为它们将其余部分存储在磁盘上。

如果您的程序达到您开始考虑编写自己的磁盘序列化算法来实现交换文件的负载,那么您基本上是在重新发明轮子。在这种情况下,我会说使用数据库。

【讨论】:

  • 并发呢?如果两个客户端要同时改变同一个全局游戏状态,会不会互相干扰,搞砸状态?
  • Javascript 没有线程,因此不支持“真正的”并发。所有代码都是原子的,进程边界正在进入事件循环(在脚本的最后一行之后,进入 setTimeout/setInterval,ajax 回调等)。较新的 javascript 解释器支持工作线程,但在该模型中,所有线程只能通过事件循环进行交互,因此不会出现并发问题,因为不允许线程共享全局变量(每个线程都有自己的全局范围)
  • 例如,在重新加载时保存服务器状态(所有游戏的进度及其用户)的好方法是什么?
  • @Herokiller:如果您希望在重新启动服务器时保持状态,请使用数据库。或者,如果您坚持不使用数据库,请使用 JSON.stringify()。但我仍然鼓励您查看数据库
  • @slebetman 我的意思是,在任何游戏中的每一步之后都可以更新数据库吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-08
  • 1970-01-01
  • 2011-03-22
  • 2021-06-27
  • 1970-01-01
相关资源
最近更新 更多