Game Engine 0 to 1 (00): Nothing's Here
[00] Nothing's Here
“Everything is created twice, first in the mind and then in reality.”
— Robin Sharma
你可以在 🏷️Game Engine 0 to 1 标签下浏览该系列的所有文章。😉
写在前面
开始之前,还是有一些话想说。当我刚入门 C 语言时,迫不及待写的第一个“项目”就是游戏。随着经验不断丰富,游戏体量也逐渐增大,但同时我也发现自己正在失去对“庞大”(现在看来当然不算什么)代码库的掌控。正如 Frederick P. Brooks Jr. 在他的软件工程著作《人月神话》(The Mythical Man-Month)中提到的:
“The general tendency of a first system is to be excessively ambitious in scope and functionality. The first system is usually built with a certain naivety and enthusiasm, where all the desired features and capabilities are included. However, due to time constraints, limited resources, and a lack of experience, the first system often falls short of expectations. It may be late, over budget, and contain numerous defects.”
虽然我写出了上万行的代码,但是最终的效果不尽人意,很多设想的功能都没有实现,还存在许多 BUG🐛。更为严重的是,这一项目可以说是无法维护的。不过,通过这个“失败”的项目,我也开始意识到一些问题,尤其是针对游戏开发。
- 一个良好的项目结构是怎样的?
- 如何更好地管理游戏对象?
- 对于多个游戏,能否有一个公共的框架?
- 如何使代码更加灵活?
从更宏观的角度来讲,当一件事物的规模逐渐变大时,这些问题都会出现,不过这里我们主要讨论的,还是游戏开发。
抱着这些问题,我思考了许久,当然结果也是显而易见的,我们需要游戏引擎(Game Engine)。当时已经有 Unity 这样成熟的商业化引擎了,但是我觉得这样会剥夺亲自动手实现的乐趣。因此我最终决定亲手实现一个游戏引擎,对那个“失败”的项目进行完全的重写。说到这里,你可能意识到了我为什么引用《人月神话》中的内容,因为它下一段便提到了这一“陷阱”:
“However, the trap lies not in the failure of the first system itself, but in the reaction to that failure. The natural inclination is to start afresh and build a second system, believing that the lessons learned from the first system will lead to a better and more perfect result. This is where the second-system effect comes into play. The engineers tend to overcompensate for the perceived shortcomings of the first system and include excessive features, complexity, and unnecessary embellishments in the second system.”
这次重写的产物,你或许在博客里已经见过了,那就是 Dungeon,其中实现了游戏引擎 Dungine,算是弥补了之前的遗憾。从某种程度上来说,它避开了所谓的 second-system effect,毕竟它做到了它该做的事情,甚至歪打正着为另一门课程设计提供了可视化支持,证明了它的可扩展性。然而,它仍然难以避免地落入 second-system effect 的陷阱,正如《人月神话》中提到的,它过于臃肿和繁琐,而且代码不够“漂亮”。
C++ 是我最喜欢的编程语言,然而平日的项目却更多用 Python、Java、C# 这样的语言,甚至最近又开始在跨平台应用中使用 TypeScript,唯有编写自己的游戏时,能有机会与 C++ 相遇。现在,距离 Dungeon 发布已经过去了三年,我的 C++ 水平应该说有了很大的长进。我想,是时候继续下去了。
在一切开始之前
当然,我喜欢写游戏,但我对如何写游戏更加感兴趣,以至于编写自己的游戏引擎似乎已经成为了一种执念。而且趁现在还没有工作,可以抓紧时间满足一下自己。当然,我指的是实现一个游戏引擎。
需要说明的是,这一想法一定程度上来自于 The Cherno 的 Game Engine Series,他曾经是 EA 的 Frostbite Engine 开发工程师,现在主导编写了 Hazel Engine,这真的很酷。
在此之前,我曾写过 Introduction to C++ Game Development,并配套了相关视频。虽然是作为课程的教程,但一定程度上也启发我继续写下去。作为一个业余项目,我觉得我有时间把自己的开发过程和心路历程记录下来,也算是一种特别的回忆吧。
在这一系列文章里,我会记录我从零开始编写游戏引擎的整个过程,包括其中的设计考量、项目管理、代码实现等,所以这更偏向开发日记,而不是技术教程。这也是我第一次尝试这一风格,希望会很有趣。最终,我也会基于它实现一个具体的游戏案例。当然,所有代码都会开源。
Due to my personal affection, sometimes I just like to write things in English, especially code related stuffs. So I may write English wherever I want.
Managing the Complexity
对于游戏引擎来说,这是我的 second system,所以有必要给予一定的重视。所以在开始前,还是需要进行一些思考,想清楚自己究竟要做什么。其实不久之前,我已经有所尝试,所以这严格来说是 third system,从 EasyX 过渡到 OpenGL,并添加物理引擎支持。然而,这二者的复杂程度超出我的预期,使我无法专注于引擎本身。
你可以在这里找到这一失败的尝试。
因此,首先需要想清楚自己真正要做什么。一个游戏引擎?游戏引擎是一个非常宏大的概念,包括资源管理、图像渲染、物理模拟等等,目前看来,仅凭我一人自然是难以兼顾,因此需要做出一些妥协,所以在这次的实现中,我想将重心放在引擎流程的实现上,使用一些成熟的第三方库暂时屏蔽这些细节问题。
此外,一些其他依赖就视需求而定了。当然,核心要实现的游戏引擎流程还是得从零开始。
一些期望
在这里,我还是想提出一些对最终引擎的期望吧,也是在之后设计中需要认真思考的问题。
首先,还是我一贯的风格,这不仅是游戏引擎,更是一次编码实践。既然是一个项目,那么就应该力求规范、整洁,正好作为一次项目管理的实践。
其次,需要具备良好的可扩展性。刚刚提到,为了屏蔽技术细节,暂时选用了第三方库,但如果日后能够将其替换,那自然是再好不过了。
最后,游戏引擎也是十分注重性能的。虽然在体量小的游戏中并不明显,但我觉得还是可以适当做一些优化。不过当然,前提自然是功能的完备性。
当然,最重要的,是要让用户便于使用。这里我并不追求“零成本”,或是“低成本”,但还是希望最终用户能够以相对优雅的方式进行使用和集成,甚至是拓展。
Ready?
In memory of all my works before, I shall name this new engine DungineX.
Welcome back commander, prepare for battle control. ᓚᘏᗢ