重构游戏引擎。 ARTris-第4部分

本文是有关 ARTris 的一系列文章的 一部分 使用ARKit,Node.js和Firebase构建的多人实时3D AR Tetris游戏。 如果您是本系列的新手,我们建议您从 介绍 开始 分叉 iOS客户端和游戏引擎存储库以开始实验。

今天,我们将开始谈论引擎。 我们将iOS客户端设计为无状态,并与Firebase数据库保持同步,Firebase数据库是我们架构中唯一的事实来源。 每次滴答之后,引擎都会更新此真相来源,以反映玩家的行为和重力。

ARTris游戏引擎的核心是基于Sebastian Poreba的作品。 它是作为无服务器3D俄罗斯方块游戏的一部分而设计的,我们对其进行了修改以使其成为我们的游戏引擎。 我们决定在时间长短中使用Sebastian的工作是因为时间和压力有限,但是即使在重构代码库后,它仍然存在。 到目前为止,我们还没有遇到阻塞问题,这要求我们从头开始重新设计引擎。 但是我们对其进行了重构,以使其更容易识别对象依赖性并将其集成到我们的堆栈中。

该游戏使用名为Tetris的全局根对象来注入依赖关系并共享上下文。 所有其他对象和函数都以树状结构添加到根中。 通过从根对象开始遍历树可访问所有对象和功能。 例如,要找到当前下降块在x轴上的位置,请使用Tetris.Block.position.x

这种树状结构和访问模式使得很难理解每个对象所依赖的对象以及每个函数调用后状态如何改变。 例如,只有在重构之后,我们才意识到-相对于最初的假设-Block对象依赖于Board,而不是相反。

重构

我们对代码库的主要关注是全局根节点(Tetris)的使用以及通过全局根节点的隐式共享上下文。 大多数函数不带任何参数,而是通过方法链(例如违反Demeter定律的访问模式)遍历根节点来访问所需的参数。

原始码

我们对引擎进行了重构,以删除全局根节点,并将依赖项显式传递给每个函数和模块。 这分两个步骤完成:

步骤1

我们逐步修改了代码,以确保应用程序在每次更改后仍能正常工作。

  1. 创建了帮助程序函数,这些函数吸收了所有依赖项来完成实际工作,并在旧函数中对其进行了调用。 在下面的示例中, testCollision调用其辅助函数_testCollision ,该函数包含实际逻辑。
  2. 通过取消引用并将它们作为参数传递给帮助器函数,删除了访问对象的引用链
  3. 添加了一些ES6语法以进一步简化代码
在第一步更改后

在这一点上,代码库更具可读性。 识别每个功能所依赖的功能以及共享共同依赖关系的功能变得更加容易。 但是,在不破坏代码库的情况下仍然很难修改它。

第2步

我们将所有内容移到一个文件中,以便所有功能和对象在相同的词法范围内可用。 然后,我们开始提取具有明确定义的依赖关系的工厂函数,这些依赖关系封装了它们的私有函数并公开了一个狭窄的API。 mpj在Fun Fun Function中可以最好地解释工厂功能。

  1. 将工厂中的函数共享的对象定义为其依赖项,并将其从函数参数中删除。
  2. 确保模块之间没有循环依赖关系。
明确将依赖项传递给每个模块

这导致了一个简单的初始化步骤

重构代码库后游戏引擎初始化

下一个

明天在本周的上一篇文章中,我们将讨论用户操作如何在引擎中传播并如何进入新的游戏状态。

更新游戏状态并处理用户操作