英文原文:https://www.smashingmagazine.com/2018/12/multiplayer-text-adventure-engine-node-js/
摘要
听说过文字冒险游戏吗? 如果你的年龄足够大的话(就像我一样),那么你可能听说过、甚至玩过“back in the day”。在本文中,我将向你展示编写的整个过程。这不仅仅是一个文本冒险游戏,而是一个能让你和你的朋友们一起玩的,可以进行任何剧情的文本冒险游戏引擎。 没错,我们将通过在添加多人游戏功能来增加它的趣味性。
文字冒险是最早的 RPG 形式的游戏之一,回到还没有图形画面的时代,你只能通过阅读 CRT 显示器上黑色背景下的描述,并且依赖自己的想象力来推动游戏剧情的发展。
如果要怀旧的话,可能世界上第一个文字冒险游戏名叫 Colossal Cave Adventure(也许是叫 Adventure)。
文字冒险游戏 back in the day 的画面
上图是你实际看到的游戏画面,这与我们现在的顶级 AAA 冒险游戏相差甚远。 尽管如此,但是他们玩起来却很有趣,并会很容易的消磨你几百个小时的时间,因为只有你自己自己坐在显示器前,试图找到打穿它的途径。
可以理解的是,多年以来,文字冒险已经被更好的视觉效果所取代,特别是在过去几年里,游戏的协作性越强,你可以和朋友们一起玩。 这是原始的文字冒险游戏所缺少的,同时也是我想在本文中提到的功能。
我们的目标
可能你已经从标题中猜到了,本文的重点在于创建一个文字冒险引擎,并且让你和朋友们一起玩,使你能够与他们进行协作,就像在玩“龙与地下城”这个游戏一样。
在创建引擎时,聊天服务器和客户端的工作了相当大。 在本文中,我将向你展示设计思路、解释引擎背后的架构、客户端如何与服务器交互以及这个游戏的规则。
为了让你对我的目标又一个直观的感受,先上一张图:
游戏客户端的 UI 设计
这就是我们的目标。 一旦达成这个目标,将会得到截图而不是简单和肮脏的模型。 所以,需要了解这个过程。首先要介绍的就是整体设计;然后介绍我将用来编码的相关工具;最后我将向你展示一些核心代码(当然,还有指向完整代码库的链接)。
希望到最后,你能够自己创造一个新的文字冒险游戏,并与朋友一起乐在其中!
设计阶段
在设计阶段,我将描述这个游戏的整体蓝图。 我会尽力不让你觉得无聊,不过我认为在给你展示第一行代码之前,很有必要先搞清楚幕后的一些工作。
我想接下来介绍的这四个组件能够提供相当多的细节:
- 引擎
这将成为游戏的主服务器。游戏规则会在这里实现,它将为任何类型的客户端提供技术无关接口。本项目中我们将实现终端类型的客户端,但是你可以用Web客户端或者你喜欢的任何其他类型。 - 聊天服务器
因为它的复杂性足以再写一篇文章了,所以这项服务也会拥有自己的模块。聊天服务器负责让玩家在游戏的过程中彼此通信。 - 客户端
如前文所述,这将是一个终端类型的客户端,在理想情况下,它看起来与之前的模型类似。它将利用引擎和聊天服务器所提供的服务。 - 游戏( JSON文件 )
最后,我将介绍实际游戏的定义。这部分的重点是创建一个可以运行任何游戏的引擎,只要你的游戏文件符合引擎的要求即可。所以,即使这不需要编码,我也将解释如何构建冒险文件以便将来编写我们自己的冒险规则。
引擎
游戏引擎或游戏服务器将会是REST API,并提供所有必需的功能。
我选择REST API只是因为(对于这种类型的游戏)HTTP造成的延迟以及他的异步特性不会造成任何麻烦。 但是,我们必须为聊天服务器采用不同的路线。 在开始定义 API 之前,先需要定义引擎的功能。 所以,让我们来看看吧。
特性 | 描述 |
---|---|
加入游戏 | 玩家可以通过指定的游戏ID来加入游戏。 |
创建一个新游戏 | 玩家还可以创建新的游戏实例。 引擎应该返回一个ID,以便其他人可以使它来加入游戏。 |
返回场景 | 此功能应返回玩家所在的当前场景。 基本上,它将返回描述,包含所有相关信息(可能的操作、其中的对象等)。 |
与场景互动 | 这将是最复杂的一个,因为它将从客户端获取命令并执行该操作——例如移动,攻击,获取,查看,读取等等。 |
检查库存 | 虽然这是与游戏互动的一种方式,但它与场景并没有直接关系。 因此,检查每个玩家的库存将被视为不同的操作。 |
关于移动
我们需要一种用来测量游戏中距离的方法,因为在游戏中玩家可以采取的核心行动之一就是移动。 我们需要用这个数字作为时间的衡量标准,来简化游戏的玩法。 考虑到这一类型的游戏具有基于回合的动作,例如战斗,使用实际时钟对时间进行测量可能不是最好的。 所以我们将使用距离来测量时间(意味着距离为 8 比距离为 2 将需要更多的时间,从而允许我们做一些事情,例如为持续一定数量的“距离点”的玩家添加效果)。
考虑运动的另一个原因是不是一个人在玩这个游戏。 为简单起见,引擎不会让玩家随意组队(虽然这对未来可能是一个有趣的改进)。 该模块的初始版本只允许个人朝着大多数参与者决定的地方移动。因此,必须以协商一致的方式进行移动,这意味着每一步行动都将等待大多数人在行动之前提出请求。
战斗
战斗是这种游戏另一个非常重要的方面,我们不得不考虑将它添加到引擎中,否则我们最终会失去一些乐趣。
说实话,这并不需要重新发明轮子。基于回合制的组队对战已经存在了几十年,所以在这里只实现这个机制的一个简单版本。我们将把它与“龙与地下城”中的“主动性”这个概念混合起来,产生一个随机数使战斗更有活力。
换句话说,就是参与战斗的每个人的行动顺序将会被随机化,其中包括敌人。
最后(虽然我将在下面详细介绍这一点),你可以用设置的“攻击力”值的物品。这些是你在战斗中可以使用的道具;如果一个道具没有这个属性的话只能对敌人造成 0 点伤害。当你试图用这样的道具进行战斗时,我们可能会添加一条消息,这样你就能知道自己要做的事情是毫无意义的。
客户端 - 服务器交互
现在来看看客户端怎样基