快捷搜索:  汽车  科技

适合初学者的5款游戏引擎:如何从零开始用 C 开发一款游戏引擎

适合初学者的5款游戏引擎:如何从零开始用 C 开发一款游戏引擎动画组件:跟踪实体的动画速度,以及动画帧如何随时间变化。精灵组件:通常存储我们应该为特定实体渲染.jpg图像。我们可以选择附加到实体的一些组件,例如下面这些:位置组件:跟踪实体在世界坐标系中的x-y位置坐标(或3D中的x-y-z)。速度组件:跟踪实体在x-y轴(或3D中的x-y-z)上移动的速度。

如想学习更多关于算法和数据结构的知识,建议尝试实现这些数据结构。如果你使用的是C ,一个选项是使用STL(标准模板库),并利用它附带的许多数据结构(向量、列表、队列、堆栈、映射、集合等)。C STL在很大程度上依赖于模板,因此这是一个练习使用模板的好机会,同时可以在实际项目中看到它们发挥的作用。

在阅读过一些游戏引擎架构的内容后,你会发现游戏使用的最流行的设计模式之一是基于实体和组件。实体组件设计将游戏场景中的对象组织为实体(Unity引擎中称之为“游戏对象”,而Unreal引擎中则称之为“角色”)和组件(我们可以添加或附加到实体的数据)。

要了解实体和组件是如何协同工作的,请考虑一个简单的游戏场景。此例中,实体将是我们的主要游戏玩家,还包括敌人、地板、投射物等,而组件将是我们“附加”到实体上的重要数据块,如位置、速度、刚体碰撞器等。

适合初学者的5款游戏引擎:如何从零开始用 C 开发一款游戏引擎(1)

一种流行的游戏引擎设计模式是将游戏元素组织为实体和组件

我们可以选择附加到实体的一些组件,例如下面这些:

位置组件:跟踪实体在世界坐标系中的x-y位置坐标(或3D中的x-y-z)。

速度组件:跟踪实体在x-y轴(或3D中的x-y-z)上移动的速度。

精灵组件:通常存储我们应该为特定实体渲染.jpg图像。

动画组件:跟踪实体的动画速度,以及动画帧如何随时间变化。

碰撞器组件:这通常与刚体的物理特性有关,并定义实体的碰撞形状(边界框、边界圆、网格碰撞器等)。

健康组件:存储实体的当前健康值。这通常只是一个数字,或者在某些情况下是一个百分比值(例如,健康进度条)。

脚本组件:有时我们可以在实体上附加一个脚本组件,它可能是一个外部脚本文件(Lua、Python等),我们的引擎必须在后台解释和执行该文件。

上面给出的是一种非常流行的表示游戏对象和重要游戏数据的方法。如今,我们已经有了实体,然后我们就可以将这些不同的组件“插入”到实体中。

目前,市场上已有诸多书籍和文章探讨了实现实体组件设计的方式,以及在这个实现中应该使用什么样的数据结构。我们使用的数据结构和访问它们的方式对我们的游戏性能有直接的影响。开发人员经常会提到诸如面向数据的设计、实体组件系统(ECS)、数据局部性等想法,这些想法与我们的游戏数据在内存中的存储方式以及有效访问数据方式都有密切的关系。

在内存中表示和访问游戏对象可能是一个复杂的主题。根据我的经验,你可以手动编写一个简单的实体组件来实现,也可以简单地使用现有的第三方ECS库(Entity-Component-System,即“实体-组件-系统”的缩写。此模式遵循组合优于继承原则,游戏内的每一个基本单元都是一个实体,每个实体又由一个或多个组件构成,每个组件仅仅包含代表其特性的数据)。

当前市场上,有一些流行的现成的ECS库可供选用,我们可以将它们包含在C 项目中,开始创建实体和附加组件,而不必担心它们是如何在后台实现的。C ECS库的一些例子是EnTT和Flecs。

我个人建议那些认真对待编程的学生至少尝试一次手动实现一个非常简单的ECS。我的理由是,即使你的实现并不完美,从头开始编写ECS系统也会迫使你考虑底层数据结构以及相应的性能。

一旦完成了定制的临时ECS实现,我建议你只使用一些流行的第三方ECS库(EnTT、Flecs等),因为这些都是经过行业多年开发和测试的专业的游戏开发库,它们可能比我们自己从零开始编写的要好得多。

总之,一个专业的ECS很难仅凭个人力量从零开始实现。选择一个经过良好测试的第三方ECS库,并将其添加到游戏引擎代码中即可完成你的游戏作品。

6 . 渲染

游戏引擎的复杂性正在慢慢提升。前文已讨论了在内存中存储和访问游戏对象的方法,接下来我们需要讨论如何在屏幕上渲染对象的问题。

第一步是考虑用引擎创建的游戏的性质。我们创建的游戏引擎是否只用来开发2D游戏?如果是这样,我们需要考虑渲染精灵、纹理、管理层,并可能利用图形卡加速。2D游戏通常比3D游戏简单,因为2D数学比3D数学要简单得多。

适合初学者的5款游戏引擎:如何从零开始用 C 开发一款游戏引擎(2)

如果目标是开发2D引擎,则可以使用SDL帮助进行多平台渲染。SDL抽象了加速的GPU硬件,可以解码和显.jpg图像,绘制精灵,并在我们的游戏窗口中渲染纹理。

如果目标是开发一个3D引擎,那么则需要定义将一些额外的3D信息(顶点、纹理、着色器等)发送到GPU的方式。如果你想使用对图形硬件软件抽象,最流行的选择方案就是OpenGL、Direct3D、Vulkan和Metal。当然,使用哪种API的决定可能取决于自身的目标平台。例如,Direct3D会为微软平台的应用程序提供支持,而Metal则只适合与苹果的产品配合使用。

3D应用程序通过图形管道处理3D数据。该管道将规定引擎必须如何向GPU发送图形信息(顶点、纹理坐标、法线等)。图形API和管道还将规定我们应该如何编写可编程着色器来变换和修改3D场景的顶点和像素。

适合初学者的5款游戏引擎:如何从零开始用 C 开发一款游戏引擎(3)

可编程着色器规定GPU应如何处理和显示3D对象

每个顶点和每个像素(片段)可以有不同的脚本,它们分别用于控制反射、平滑度、颜色、透明度等。

至于3D对象和顶点,最好将读取和解码不同网格格式的任务委托给一些第三方库来实现。大多数第三方3D引擎都应该了解许多流行的3D模型格式,例如OBJ、Collada、FBX和DAE等一些文件格式。我的建议是首选.OBJ文件格式,因为有不少测试和支持力度良好的库可以用C 处理OBJ加载。这方面,TinyOBJLoader和AssImp就是许多游戏引擎使用的上佳选择。

7 . 物理引擎

当我们向引擎中添加实体时,我们可能还希望它们在场景中移动、旋转和反弹。

游戏引擎的这个子系统称为物理模拟。这可以手动创建,也可以从现有的现成的物理引擎导入。

在这里,我们还需要考虑想要模拟的物理类型。2D物理通常比3D简单,但物理模拟的底层部分对2D和3D引擎都非常相似。

如果你只想在项目中包含一个物理库,那么已有几个很好的物理引擎可供选择。对于2D物理引擎,我建议调研一下Box2D和Chipmunk2D这两款产品。对于专业且稳定的三维物理模拟引擎,品牌相当不错的包括PhysX和Bullet之类的库。如果物理稳定性和开发速度对项目至关重要,那么使用第三方物理引擎总是一个不错的选择。

适合初学者的5款游戏引擎:如何从零开始用 C 开发一款游戏引擎(4)

BOX2D是一个非常受欢迎的物理库选项,可以与游戏引擎一起使用

你不需要编写一个完美的物理模拟,但要确保物体能够正确加速,并且不同类型的力可以应用到你的游戏物体上。一旦实现基本的物体移动效果,接下来你也可以继续考虑实现一些简单的碰撞检测和碰撞解析。

对于2D刚体物理可参考Box2D源代码和来自Erin Catto的介绍。如果想寻找一门关于游戏物理的综合课程可参看《从零开始编写2D游戏物理》)。

如果想学习3D物理以及物理模拟实现,可参阅大卫·埃伯里(David Eberly)编写的图书《游戏物理》(Game Physics)。

8 . 用户界面设计

一提到Unity或Unreal等现代游戏引擎,我们会想到复杂的用户界面,其中包含许多面板、滑块、拖放选项和其他漂亮的UI元素,可以帮助用户自定义游戏场景。UI允许开发者添加和删除实体,动态更改组件值,并轻松修改游戏变量。

为了明确起见,我们讨论的是用于开发工具的游戏引擎UI,而不是我们向游戏用户显示的用户界面(如对话框屏幕和菜单)。

游戏引擎不一定需要嵌入编辑器,但由于游戏引擎通常用于提高生产力,友好的用户界面将帮助你和团队快速自定义游戏场景的关卡等其他方面。

对于初学者来说,从头开始开发UI框架可能是游戏引擎制作中最烦人的任务之一。你必须创建按钮、面板、对话框、滑块、单选按钮、管理颜色,还需要正确处理UI的事件并始终保持其状态。向引擎中添加UI工具会增加应用程序的复杂性,并给源代码管理带来大量麻烦。

如果你的目标是为引擎创建UI工具,那么我建议使用现有的第三方UI库,热门UI备选工具有Dear ImGui、Qt和Nuklear等。

适合初学者的5款游戏引擎:如何从零开始用 C 开发一款游戏引擎(5)

猜您喜欢: