几个月前,我用React和Redux制作了一个俄罗斯方块游戏。 这学期我参加了CSC591游戏引擎开发课程。 以前,我一直从事前端开发工作,但是游戏设计方面的经验确实使我受益匪浅。 在学期末,我发布了自己的画布游戏引擎/框架Zion ,并在其之上构建了一些游戏演示。 因此,我想写一篇有关游戏(引擎)开发的文章,以分享我在此过程中学到的知识。
让我们考虑一下大多数游戏共有的功能。 通常,它们具有在屏幕上显示的场景( 图形/ 渲染 )。 有些具有先进的渲染技术( 粒子系统 )来渲染烟雾,雾气等。您可以使用鼠标或键盘与游戏进行交互并获得声音( I / O )。 有些游戏带有WarCraft 3这样的机器人( AI )。 并且它们还支持多人在线同时玩在线( 网络 )游戏,例如Counter-Strike Source等。
您可能仍会继续提出越来越多的功能。 现在您已经越来越接近游戏引擎的核心。 游戏引擎将提供一组抽象的实用程序,以实现我们在上一段中讨论的功能。 它是用特定编程语言编写的综合建筑环境。 并非特定于游戏的所有内容。
为了更进一步,从基本到高级,这个游戏开发路线图可能会帮助您理解: Bare Metal(Game Arduino)=>操作系统(Windows)=>库=>框架(PyGame)=>游戏引擎(Unity3D )=>制造者=>向导。
您可能已经使用canvas编写了一些代码。 由于HTML5,它变得栩栩如生并得到广泛使用。 这样做的好处是您不必从头开始构建所有内容,因为canvas本身已经提供了一些API供您构建游戏。 因此,这与从头开始为使用C ++的Unity3D之类的工具构建GUI接口不同。
但是,可以说,canvas提供了丰富的API,但是由于以下原因,它远远不够或完整:
- API是一堆分散的实用程序。 功能实用程序太灵活了,因为它们无法提供游戏运行的典型流程或限制。
- canvas API不能为您提供足够的抽象。 假设您要绘制旋转的精灵,则可能要结合多个API编写10行以上的代码。 这将需要您编写5行代码来画一条线。 那是违反直觉的,为什么事情不那么容易?
- 同时考虑浏览器功能,DOM功能和画布功能是很痛苦的。 例如,在I / O中,您需要的不是画布功能,例如DOM Event。
考虑到以上所有和潜在的原因,构建画布引擎/框架更像是将所有分散的问题组合在一起,连续构建实用程序以消耗我们的游戏并修复容易出现错误的问题,同时隐藏实现细节。
首先,您可能会包装一些功能,这些功能可以在canvas API的基础上提供更高级别的抽象,例如drawLine(),从一开始就很不错。 但是在这一点上,您实际上是在建立一个 库,而不是一个引擎 。 框架当然可以包含一组类似库的实用程序。 但是要制作一个真正的引擎/框架,您确实需要花精力思考如何处理模块化,界面设计,最重要的是, 什么是游戏流程以及如何“让框架调用您的代码”。

幸运的是,通过讲课和做作业,我得到了很多想法。 简而言之,让我们将游戏视为无限状态机。 (这是从JSON和Redux借用的。)一切都存储在一个大的JSON对象中,您与游戏的交互只是修改状态树。
因此,游戏的全部内容是“更新状态”和“渲染状态” 。 并用“ setInterval”之类的计时器包装这两件事,就完成了游戏的结构,如下所示。 在锡安,我们提供了一个称为 游戏 用于基于类的扩展。 这是起点,也是Zion对游戏流程的限制。
我从Redux的设计哲学中得到了很大的启发。 因为如果我们将游戏视为状态机 ,那么redux可能是状态管理器的理想选择。 好消息是Redux本身不是特定于框架的,因此您不需要其他任何东西即可在项目中使用它。 好处是游戏状态的更改变得更易于管理,更易于跟踪或调试,而代价是代码量必须显着增加,并且在大多数情况下,带来的意义不大因此,我没有将它与Zion合并,以防万一它变得自以为是。
构建框架需要对一些设计模式,模块化等有很好的理解。好处是,如果您已经对JavaScript或前端开发有一定的了解和经验,则不必担心语法或语言大惊小怪。 那给了我足够的精力去专注于GAME本身,而不是被JavaScript等古怪的部分所分散。
基本思想是在浏览器API的基础上为游戏引擎添加每个功能的更多抽象层。 我不会深入了解实现细节,因为您可以随时在此处检查Zion的源代码和文档。 在这里,我想谈谈我在构建锡安(Zion)的过程中吸取的一些教训。
我个人认为构建工具的理想方案是这样的:您首先遇到一个问题 。 您可以对StackOverflow或Github等进行一些研究 。然后使用独立的库或实用程序来抽象解决方案 。
锡安就是用这种方式建造的。 我们不是首先构建引擎,而是以实现拖放游戏为目标开始。 为了在画布中实现DnD,我结合了一些事件侦听器,并将DnD组件添加到Zion。 这样,在构建了五款游戏之后,锡安已成为一个框架,几乎具有典型游戏框架应具备的所有组件。
另一个更具体的示例是渲染期间的闪烁问题。 我在第三局遇到了这个问题。 每次调用render时,如果从头开始创建过多的图像实例,则会给您留出一定的时间间隙,在图像全部加载完毕之前,画布是空白的。 这会使屏幕急剧闪烁。 我从https://stackoverflow.com/questions/17261080/html5-canvas-blinking-on-drawing获得了解决方案的想法。 但这并没有为我提供良好的抽象,也没有提供干净的代码。 因此,我自己构建了一个独立的基于诺言的实用程序canvas-image-cache,后来又将其添加到Zion。 另一个类似的示例是KeyBus,它处理同时键盘处理程序。
因此,我了解到的是,您在一开始就没有建立一些完美的东西。 我从我以前读过的一篇博客文章中回想到: “如果您等到您觉得产品足够好才发布,那么为时已晚。”您的应用程序也是如此。 刚开始时它是破旧不完整的,这完全可以。 罗马不是一天建成的,软件需要迭代。 即使是拥有大量专职维护人员和超过一千名积极贡献者的React,也每天都在收到错误报告和出现的问题。 正是迭代使优质软件变得更好并脱颖而出。
因此,这可能是我发布Zion的第一个版本(v0.1.0)的原因。 几天前,我们完成了其文档,在此过程中,我思考了很多内容,以了解如何进行良好而友好的界面设计,并且学到了很多东西。 我们已经在其之上构建了五个游戏演示,证明了它的良好开端。 现在,我需要更多的迭代,并听取您对如何使其更好的意见。
如果您喜欢开源,请不要错过这次参与这个未开发领域的机会。 欢迎发布问题,错误报告,请求请求,建议!
游戏频谱, 亚当·史密斯 ( Adam M. Smith) , 加州大学圣克鲁斯分校
Zion —基于HTML5画布的暂定的轻量级2D游戏框架。 支持渲染,I / O,网络,AI等