电子游戏设计/章节/实施
在考虑实施你的设计之前,你应该思考一下实施的成本,包括时间和金钱。你可以通过将你的游戏设计(概念)出售给游戏制作工作室来将其货币化,或者你可以为开放式实施创建一个开源项目。
在考虑做什么时,也请考虑你创建的游戏的可营销性以及你的目标。它将是免费的吗?还是你要出售它?如果你要出售它,人们会想要购买它吗?人们将如何听到关于它的消息?你愿意在营销这款游戏上花多少钱和多少资源?你有吗?它们值得吗?
实施也应该被视为一个沙盒,在那里将尝试和修剪事物以满足所需的目标。你只应该在实施的后期阶段感到担忧,因为在某个时候,人们必须接受过多的更改可能会破坏项目。
如果你的实施过程在某个部分停滞,请回到你的设计参考,看看以前的人如何处理这些问题。你可以,也应该,有创造力,但你应该期望有人已经找到至少一个可行的解决方案来解决每个问题,使用你的创造性资源来建立在这个解决方案的基础上,而不是重新创建与以前已经完成的事情相等的东西。
在你开始开发之前,请记住要区分你想要做什么和你能做什么。弄清楚你拥有的资源,并将它们与项目所需的资源进行比较,并相应地进行调整。如果你拥有大量资源,但你的概念很简单,也许你可以扩展它。如果你有一个复杂的概念,但资源很简单,也许你需要扩展你的资源。
在你完成了所有这些考虑之后,概述项目,首先是如何游戏的工作方式以及它的排列方式,然后按时间顺序排列你将如何完成这些事情 - 为自己设定一个截止日期可能会有所帮助。
考虑你的资源,你个人有哪些能力?你会编程、画画、渲染多边形吗?你有多少钱,你打算花多少时间在这上面?你是否有开发游戏的技术,还是需要去获取?你知道你需要什么吗?
团队合作
[edit | edit source]开发一款视频游戏对于一个人来说是一个非常大的项目,尤其是一个人独自完成。将项目作为一个团队来做,将所有需要的资源整合在一起,共同打造一款优秀的视频游戏,或许是一个更好的主意。仅仅靠一个人几乎不可能创作出人们真正喜欢的游戏。游戏开发需要良好的社交技能,因为 99% 的时间你都将与一个设计师团队一起工作。与你的游戏设计同事建立良好的关系非常重要,这样才能取得项目最佳效果。
开发阶段
[edit | edit source]测试和开发阶段是游戏真正被创建出来的阶段。当你进行编程、制作图形、作曲并协作这些资源时,你会进行大量的测试和调试工作。请考虑以下部分。
测试
[edit | edit source] 一位维基编者建议将The Computer Revolution/Software/Graphics合并到本章节中。 在讨论页面上讨论是否应该进行合并。 |
概念艺术
[edit | edit source]在游戏实施的早期阶段拥有良好的概念艺术作品集非常重要,这不仅可以使概念更加直观,还可以协调整个开发团队的开发工作。
概念艺术在实施之前就提高了游戏设计本身的价值。
内容创作
[edit | edit source]游戏内容可以是静态的,也可以是动态的,与移动有关,并取决于它是如何创建的(设置或程序化),甚至两者兼而有之,生成也可以是实时进行的,也可以来自存储数据,这主要取决于交互程度或硬件能力。
演示
[edit | edit source]演示在游戏中,就像在现实生活中的大多数事物中一样,非常重要。震撼效果、将简单平庸的事物以创意的方式改变,让玩家沉浸在作品中,是游戏成功的关键因素之一。
演示涵盖了游戏中所有视觉元素的利用方式,从在2D 或 3D实现之间进行选择,到所有游戏艺术作品的质量,从游戏内物品到现实生活中的营销宣传、曝光和游戏盒设计。
有许多免费许可内容的资源库,不仅可以用于游戏原型设计,甚至可以用来构建完整的成熟游戏实现。
- OpenGameArt.org (http://opengameart.org/) - 一个包含各种类型媒体的资源库,具有不同的版权许可状态,旨在用于自由软件游戏项目。
- ccMixter (http://ccmixter.org/) - 一个促进混音文化的社区音乐网站,提供 Creative Commons 许可的样本、混音和人声伴奏轨道供下载和在创意作品中重复使用。
- The Freesound Project (http://www.freesound.org/) - 一个 Creative Commons 许可的音频样本资源库。该网站的用户上传的声音涵盖了广泛的主题,从实地录音到合成音效。
构图
[edit | edit source]游戏构图与电影摄影和动画有很多共同点。就像电影一样,大多数游戏都倾向于讲述一个故事,即使是以互动的方式。如今,任何制作 3D 游戏的人都应该学习如何正确地进行镜头切换、广角镜头和蒙太奇。理解焦点与零平面之间的关系。
艺术作品
[edit | edit source]游戏的每一个视觉方面都需要某种形式的艺术作品。
动画
[edit | edit source]动画是动态内容的一个例子,它们可能在游戏中是必要的,用于情节推进或提供背景信息。制作的复杂程度也可能需要更复杂的员工,作家、导演和动画师经常被使用。由于电影的使用,使用电影技巧;制作出能够有效地进行电影观看的素材将非常重要。
在任何类型的动画场景中,理解物体是如何移动的,每个身体如何行动以及如何与周围环境互动都非常重要。
动作捕捉
[edit | edit source]动作捕捉演员的表演正在成为近年来游戏中逼真角色动画的要求,尤其是如果现实主义确实是需求的话。
捕捉演员的互动最好是在实时互动中进行,而不是作为个人表演的整合,这样互动会更加真实,因为这允许演员以脚本无法规划的方式进行创新。通常只有潜意识感知到的自然互动将有助于使场景对玩家更真实。
动作捕捉舞台
[edit | edit source]声音能力
[edit | edit source]能够实时捕捉对话对于赋予场景真实感非常重要,因为语音会根据身体位置以及演员在表演过程中的位置和移动而改变。它还有助于演员充分地进行必要的表演。
多次拍摄
[edit | edit source]对于动作捕捉表演的导演来说,重要的是让演员能够发挥自己的主动性,允许多次拍摄,并且可以自由地超出剧本范围。这通常会带来更好、更丰富的解决方案。这可能取决于可用时间和处理材料所需的资源,但在当今的数字世界中,这通常可以在不产生过高成本增加的情况下实现。
3D 图形
[edit | edit source]有几种方法可以生成 3D 计算机图形来表示 3D 环境中的形状。了解物体将如何被利用以及技术特性和所需的细节水平非常重要。艺术家必须意识到可能存在的任何限制,例如,可能需要降低细节级别以保留资源或仅仅因为它们不需要,每个需求都需要一种独特的艺术方法。
观察
在开始对物体进行建模之前,首先需要观察要创建的对象。必须仔细记录细节以及如何在软件中重现这些细节。必须记录在艺术作品中计划创建的所有内容。每个部分的重建将是任何软件中的主要任务。现在记下(在纸上)所需的所有细节将加快在开始使用软件时的工作速度。
具有 90 度角的事物的表面和角很容易记住,但是近距离观察可能会有更多细节。对于更复杂的事物,请书写或绘制有关主题的具体内容。如果你不知道辐条与轴连接相切并在另一侧朝相反方向延伸,那么试图在不查看的情况下对自行车轮进行建模几乎是不可能的。
有机对象的曲线通常具有不同程度的锐度。在曲线更锐利的地方,可能需要在建模阶段在该区域添加更多细节。曲线的 位置和方向在建模阶段也至关重要。
主题的比例对于确认模型看起来准确和真实很重要。它们可以在建模过程中使用,也可以在最终校正后使用。
每个表面/材料都有几个不同的内在特征(不依赖于环境),例如
- 颜色
- 纹理
- 反射率
- 透明度
如果在 3D 中复制或创建复杂的场景,正确且一致地使用灯光很重要,请注意
- 光源
- 位置
- 方向
- 扩散
建模
在很好地了解如何以及从对象中表示什么之后,下一步是生成要显示的对象模型。创建模型有很多不同的方法,每种方法都有其优缺点。为了让艺术家在这一步骤中更加高效,他们需要了解不同方法及其优缺点。
考虑你的主题,哪种方法最适合这种情况。
多边形和网格建模理论
[edit | edit source]在现实生活中,物体是由难以想象数量的原子组成的。计算机难以处理现实生活的复杂性,因此我们需要使用更简单的东西来对其进行建模。
我们在计算机上可以定义的最简单的东西是空间中的一个点。(类似地,如果我面前有一张纸,我在上面最容易画的就是一个点,我只需用铅笔轻触纸张即可。)空间中的一个点称为顶点。
现在考虑这一点。纸上的每个点(或顶点)都有一个编号。我们将我绘制的第一个点称为顶点 1。如果我继续绘制更多顶点,我绘制的第二个顶点将被称为顶点 2,第三个将被称为顶点 3,依此类推。
一堆点本身对我们来说并没有什么用。所以我们将它们连接起来,就像一个连点游戏。如果我们将其中三个连接起来,并填充中心,我们将得到一个三角形,这是我们可以用顶点创建的最简单的表面。
如果我们创建额外的三角形(从第一个三角形扩展),我们可以创建更复杂的表面。如果我们使用足够的三角形,可以创建任何表面!
如果两个三角形彼此相邻,并且似乎构成物体的侧面,我们通常称它们为多边形,并将它们视为多边形,而不是称它们为两个三角形。它仍然由两个三角形组成,但我们只称它们为多边形,以使其更容易。
三角形有一些特性,使其易于计算机处理
- 它们由直角构成。三角形由直边构成,没有曲线。计算机处理直线很好。它们不轻易处理曲线。这样想,如果我给你一张纸,上面有两个点,并说,“在这两个点之间画一条直线”,你会确切地知道我的意思。我给的每个人如果按照指示都会画出相同的线。现在假设我给你同样的纸,并说,在这两点之间画一条弯曲的圆形线。这些都是含糊不清的指示。你不知道我到底想让你画什么。我给每个人的作业都会画出稍微不同的曲线。为了确保每个人在两点之间画出相同的曲线,我需要给出更复杂的指示。
- 它们是平坦的。
- 它们不能自相交。如果你有两个多边形,它们可以彼此相交(穿过)。计算机难以处理交点。因此,三角形更容易处理,因为它们不能穿过自身。
多边形是下一个最简单的表面。
多边形就像三角形,但边数比三条边多。正方形是一个多边形。任何多边形都可以很容易地分解成三角形,所以它仍然相当简单。多边形通常是平坦的,或接近平坦。如果两个三角形形成一个极端的角度(不平坦),那么我们通常不会称它们为多边形。法线的概念
动画软件中的每个三角形或多边形都有一个“法线”。如果一个三角形是一个桌面,它的法线将直接向上指向,远离表面。法线始终垂直于表面。为了简化计算机需要完成的工作量,3D 软件可以执行一种称为“背面剔除”的操作。剔除表示“不显示”、“修剪掉”、“忽略”,背面表示面的背面,或多边形的背面。背面剔除表示不显示多边形的背面,只显示正面,或者更准确地说,法线指向的一侧。
示例:普通球体上的法线指向远离球体中心的点。如果你站在一个巨大的球体外面,看着它,你会看到它。但是,如果你站在球体里面,你就看不到它。背面剔除将消除球体的内部,因为它的法线不朝向你。
法线由在定义多边形时对顶点进行计数的顺序来定义。无论你在绘制原始三角形或多边形时是按一个方向绕行还是另一个方向绕行。你不应该担心这个问题。只需要知道你经常需要“翻转法线”,这是一个在每个值得信赖的建模软件包中都可以找到的命令。元素(连续网格)
元素是一个独特的表面。如果两个多边形并排创建,每个多边形都是用与最后一个不同的顶点创建的,那么它们被认为是独立的元素(或不是连续网格)。假设我们有两个三角形。(图 1)它们是两个元素。现在假设我们将它们移到一起,使它们接触。即使它们看起来像一个,它们仍然被认为是两个元素。区别在于它们是由不同的顶点定义的。它们不共享任何顶点。为了使它们成为一个元素,我们需要“合并”(或焊接,或折叠,有时也称为)这两个顶点。在三角形看起来相互接触的每个地方,我们都要确保只有一个顶点。然后这两个三角形将共享顶点,它们将成为一个元素。通常,建模软件会在大多数情况下将你的对象保留为一个元素,并在你扩展模型表面时自动共享顶点。
与元素没有连接的多边形不与其“连续”。这在纸上很难理解。在软件中工作。
元素在对象中一次选择多个多边形组很有用,这些对象中存在多个不同的表面。在 3DSMAX 中,你可以在可编辑网格中选择元素模式,并选择元素。在 Maya 中,你可以通过将选择扩展到最远的地方来选择元素。
- 顶点 - 一个点,在一个地方。一个顶点非常小。它没有宽度、长度或高度。它只有一个位置。顶点本身没有用。与其他东西结合起来才有用。如果我们创建多个顶点,我们可以开始将它们连接起来以创建可见的表面。
- 边 - 多边形或三角形的一侧。如果你移动一条边,定义该多边形或三角形该边的两个顶点实际上将被移动。
- 三角形 - 它由 3 个顶点定义。我可以说顶点 1、顶点 2 和顶点 3 构成一个三角形。这将给我一个表面。三角形边框内的区域也是三角形的一部分。三角形是一个表面。三角形可以渲染,并且会显示为实体。
- 多边形 - 多边形就像三角形,但边数比三条边多。多边形实际上是由多个三角形组成的。通常软件允许你处理多边形,而不必担心三角形。它会自己担心三角形。你不必单独定义每个三角形。你只需处理多边形,通常软件会自己弄清楚如何处理三角形。对于一些高级建模目的,你可能有一天需要担心单个三角形,但这并不常见。
一个三边多边形是一个“三角形”,一个四边多边形是一个四边形。结构良好的模型通常应该主要由四边形组成,并包含几个三角形。如果该模型旨在用于细分曲面(一种对模型进行圆角的方法),则它不应包含超过 4 条边的多边形。
- 元素(或“连续网格”)- 元素是焊接在一起的多边形集合。它们彼此共享顶点。
- 法线 - 用于指示多边形的哪一面是可见的。当背面剔除打开时,你只能看到法线朝向你的三角形。本质上,三角形的只有一侧是可见的。
这些多边形(或“网格”)模型的组件也定义为 3DSMAX 中的“子对象”和 Maya 中的“组件”。
次表面建模
[edit | edit source]对于具有对称细节级别的主题,使用次表面建模是理想的选择。相反,人脸需要在脸部和耳朵上拥有更多的细节,而在其他地方则需要很少的细节。这种不均匀的细节会使模型的线框看起来杂乱,并使用三角形来弥补面积差异处的接缝。虽然可用,但继续深入的次表面建模会使模型过于复杂。因此,对脸部的动画可能会因为所有不可预测的三角形而变得很痛苦。
这种建模过程被认为是最常见的建模新对象的方法之一。在这里,我们将盒子作为基础对象,并使用建模工具和技术对形状进行更改,以完成模型。
考虑到对细节的额外关注所蕴藏的力量,它可能让玩家感到惊叹,这将提高满意度,并等同于对制作投入的努力的感知。
人类的心智是一件了不起的事情,如果考虑到捕捉它的想象力,一个良好且详细的环境通常会掩盖实现中的一些小错误。
游戏中的语音对于推进剧情、介绍新元素甚至作为游戏玩法的一部分都很重要。大多数游戏使用数字化语音,如果游戏模拟现实,则声音的质量以及与动作的协调性至关重要。一些游戏未能取悦玩家仅仅是因为配音的质量很差或表现不佳,或者即使同一个配音演员为太多角色配音也是如此。
情绪对人声的影响
快乐 | 悲伤 | 愤怒 | 恐惧 | 厌恶 | 惊讶 | |
---|---|---|---|---|---|---|
音质 | 气声和沙哑 | 浑厚 | 气声,带有胸腔音 | 不规则和沙哑 | 咕哝,带有胸腔音 | 气声和沙哑 |
发音 | 正常 | 含糊不清 | 紧张 | 清晰 | 正常 | 紧张而清晰 |
语速 | 更快或更慢 | 稍微慢一点 | 稍微快一点 | 快得多 | 慢得多 | 快得多 |
强度 | 更高 | 更低 | 更高 | 正常 | 更低 | 更高 |
音域 | 宽得多 | 稍微窄一点 | 宽得多 | 宽得多 | 稍微宽一点 | 宽得多 |
音高平均值 | 高得多 | 稍微低一点 | 高得多 | 高得多 | 低得多 | 高得多 |
音高变化 | 平滑,向上拐弯 | 向下拐弯 | 在重读音节上突然变化 | 正常 | 在结尾拐弯处大幅向下 | 上升的轮廓 |
由于游戏可以面向国际公众,并且作为减少任何缺陷(如糟糕的声音再现)的一种方式,字幕在游戏中也变得很重要。
DECTalk 在 YouTube 上的示例 (计算机演唱“温柔的谎言” 或 语音合成很棒)。DECTalk 最初是合成语音的硬件实现,后来演变成仅软件解决方案,其多功能性仍然无与伦比。
合成语音尚未在游戏中获得发展动力,主要是因为该领域的质量低和技术进步缓慢。随着技术的进步,对话可能会变得更加动态,并且更容易适应国际受众。将这种能力添加到人工智能角色中也很有趣。
大多数合成语音不会直接落到游戏美术部门,而是落到程序员手中,但任何游戏的文本或语音部分的脚本始终需要创意作家。
由于大多数过程生成的内容依赖于算法实现,因此这些例程通常是 游戏框架 的一部分,这使得它易于在多个游戏作品中使用。
编程是将你的概念付诸实践的方式,是构建游戏的过程。有各种各样的 编程语言。这些语言将在后面详细介绍。
游戏程序员或游戏开发者负责实现游戏设计,视频游戏编程的大部分工作都枯燥无味,缺乏创意,除非游戏设计需要一些创新或更新。但需要注意的是,对于任何开发者来说,特别是那些实现视频游戏的开发者来说,最糟糕的情况是,从一开始就拥有糟糕的游戏设计,无法做出决定或对选择犹豫不决会导致开发者不得不实现糟糕的概念,直到游戏设计师接受结果(或由于时间/成本限制被迫同意),从而导致产品质量低下。
并非所有开发工作都具有吸引力,在游戏中,大多数工作都不是,例如,游戏的正面在大多数游戏设计中都是很常见的,做一个更多只是在跳跃。现在,我们以支持显卡硬件更改的任务或甚至低级优化任务为例,这将是创造性程序员的最佳选择。
因为这可以说是游戏设计中最困难的部分,所以我们将花相当多的时间来学习它。如果你对想学习哪种语言有一些想法,并且已经阅读过各种语言,你应该开始学习。如果你能上一些课程,那就太好了,如果没有,还有很多其他选择。购买一些编程书籍,在互联网或维基教科书上查找一些教程,并查看开源程序的源代码。不要以为这会很容易,它并不容易;但要尝试享受其中。如果你不享受其中,那岂不是失去了整个目的吗?
一些资源:Google 代码,Sourceforge
在开始编程之前,选择一种适合您需求的编程语言非常重要。请记住,没有一种语言适合所有人或所有情况。有如此多的语言可供选择,以至于选择一种几乎是不可能的。在决定学习 Java 或汇编语言之前,请确保您知道您要做什么。游戏的复杂程度如何?花大量时间和精力学习一种没有能力制作您计划的语言将是得不偿失的,就像学习一种对您的需求过于复杂的语言一样。当您开始阅读有关各种语言的信息时,您将不可避免地读到“低级”和“高级”语言。在这个阶段,这并不那么重要,但在以后会非常重要。本质上,低级语言(例如:C++、C、Asm)功能更强大、速度更快,让您可以控制计算机的内部工作机制。但是,它们通常更难学习。高级语言(例如:BASIC)更容易学习和使用,但缺乏低级语言的功能和灵活性。
声音在任何游戏中都起着不可或缺的作用,因为它在意识和潜意识层面上影响着玩家的情绪!你能想象在没有声音的情况下玩 UT 或 Quake 吗?那将是无法忍受的!游戏中的声音(当然取决于游戏本身)通常包括背景音乐、事件音效(汽车喇叭、枪声等)和环境音效(脚步声、风声、鸟鸣、海浪、虫鸣、回声等)。
背景音乐,根据游戏的不同,可以一直播放,也可以像电影一样完全停止并改变以适应某些情绪,例如,如果你进入战斗,音乐可能会变成节奏更快或更不稳定的曲目。
另一方面,音效会在某些事件触发时播放。如果玩家要打开一扇门,可能会发出门吱呀作响的声音。音效可以为游戏增添不少真实感,选择合适的音效可以真正让游戏活起来。但是请注意,音效过多,或者音效具有不真实的属性,会损害游戏体验,或者让玩家感到厌烦。例如,有一个游戏包含一个喷气背包。这个喷气背包有无限燃料,所以玩家可以无限期地在空中漂浮。喷气背包运行时,会发出像呼啸的空气的声音。随着时间的推移,这种声音会变得非常烦人,因为它在游戏过程中经常被听到。此外,如果一种声音具有奇怪的属性,它可能会减损真实感。例如,发出嘎嘎声的机枪,或者射击速度快于实际射击速度的机枪。
环境音效在玩家进入环境时触发,并循环播放,直到玩家离开。请注意,这些声音文件数量最多,有时多个声音以随机顺序循环播放,以营造出环境的多样感(例如,两只唱着完全不同的歌的鸟,或者两个角色走路时,每个角色的鞋子发出不同的“咔嗒”声)。
游戏通常为玩家提供许多关于输入的选项。常见的输入方式包括鼠标、键盘、操纵杆和游戏手柄。理想情况下,游戏引擎应该抽象化输入,以便用户可以选择上述任何一种。此外,要记住的一件重要的事情是,所有玩家在按键或按钮放置方面都有不同的偏好,并且通常希望获得特定的配置。这意味着输入也应该被抽象化,以允许按钮或按键在游戏中执行不同的操作。
首先要了解程序解释键盘事件的不同方式。接收键盘事件的最常见方式是通过回调和轮询。
- 回调 - 通常由使用 GLUT 库的游戏使用,函数指针传递给 GLUT,它将该函数“注册”为键盘事件回调。这意味着,每当按下或释放一个键时,GLUT 都会调用相应的函数,传递键数据,并允许程序做出相应的响应。
- 轮询 - 更常被使用 SDL 的游戏使用,如果回调函数在引擎中破坏了抽象,则轮询会很有帮助。轮询是一个过程,游戏在空闲时间检查一组键盘事件。因此,在游戏循环的每次通过中,您的游戏都可以轮询该集合,从而快速响应按键事件,并且不会丢失数据。
每个操作系统都有自己的 TCP/IP API,因此,如果您计划为特定平台开发游戏,那么您必须研究该操作系统的 SDK(例如,Windows API 的 WinSock)。如果您要编写可移植到多个平台的游戏,一个不错的选择是SDL_net.
选择好网络 API 后,应该为游戏引擎构建封装套接字的类。您还必须决定使用哪种网络协议,TCP 和 UDP(尽管通过抽象,可以使用任何一种)。
- TCP - 此协议在两台计算机之间建立连接。如果存在任何错误,在计算机之间发送的数据会被重新发送。此协议的缺点是,它的整体速度不如 UDP 快。
- UDP - 此协议不建立连接。数据包被发送到一个地址,发送方不知道它是否已正确无误地到达。可以使用 UDP 编写一个协议来提供错误检查和重新发送。
最终的决定取决于程序员,以及什么最适合游戏。如果主题是网络象棋游戏,速度不是主要问题,可以使用 TCP 来避免一些麻烦。但是,对于大型团队在 FPS 中玩游戏,UDP 由于速度更快,将是一个更好的选择。
《Free Fire》是一款非常酷的游戏,约有 4100 万人玩这款游戏。Sea Limited 由 Forrest Li 于 2009 年在新加坡成立,他毕业于上海交通大学和斯坦福商学院。Garena 最初的目标是一家游戏开发和发行公司,但后来扩展成为一家科技巨头,还提供金融服务和电子商务。2017 年更名为 Sea 后,数字娱乐部门保留了 Garena 的名称。
同年,《Free Fire》作为一款大逃杀多人游戏发布,并迅速获得了国际上的成功。它是 2019 年全球下载量最高的移动游戏,并已成为 Garena 的重要收入来源。
2021 年,Garena 发布了一个图形增强版《Free Fire Max》,但其收入尚未超过原始版本。根据 AppMagic 的数据,这两款应用程序是 2022 年下载量最高的射击游戏,每款下载量超过 1 亿次。
《Free Fire》已成为三大射击手机游戏之一,另外两款是《PUBG Mobile》和《使命召唤:手游》,此前《堡垒之夜》已于 2020 年 8 月从 App Store 和 Google Play 下架。这三款游戏在该类型游戏中获得了大部分收入,而该类型游戏的受欢迎程度比其他游戏子类别下降得更快。
2022 年初,印度禁止了《Free Fire》和其他 53 款被认为对国家安全构成威胁的应用程序;《Free Fire Max》仍然可以在 Google Play 商店中使用。根据 data.ai 的数据,《Free Fire》曾是印度下载量第二高的应用程序,并且拥有最高的消费者支出。虽然 Sea 总部位于新加坡,但其最大股东是中国社交媒体公司腾讯控股。2022 年,《Free Fire》和 Sea 的年收入大幅下降,这在一定程度上归因于印度的禁令。
自 2019 年以来,《Free Fire》还举办了电子竞技比赛,其世界系列赛已成为历史上观看人数最多的电子竞技赛事,2021 年的直播观看人数达到 540 万。这些区域赛事在全球范围内举行,并提供数百万美元的奖金。
《Free Fire》被《PUBG Mobile》的开发商 Krafton 指控侵犯版权,该公司于 2022 年 1 月对 Garena 提起诉讼,指控其游戏道具、机制和外观存在相似之处。苹果和谷歌也被列入诉讼中,原因是它们分发了这款游戏,该诉讼尚未得到解决。
以下是游戏开发中使用的一些免费脚本引擎
- KonsolScript - 一种免费软件游戏脚本语言
- Lua - Lua 脚本语言
这里列出了一些可用于游戏开发的免费软件工具。
- Blender3D - 一个免费且非常先进的建模程序,虽然有点难上手,但功能与任何其他商业建模程序一样强大。
- OGRE - 一个免费的软件图形引擎。顶尖水平。
- Terragen - 一个免费用于非商业用途的地形生成器
- TrueSpace - 专业级 3D 建模、动画和渲染软件包,之前售价高达 700 美元,现在微软收购 Caligari 后可免费下载。
其他
要开发游戏,您可能不仅需要为特殊任务(如图形设计师)配备合格的专业人员,还需要考虑编辑软件(用于创建角色、物品、场景等),以及支持这些任务的物理硬件。例如,图形设计师可能需要图形板,您可能还需要扫描仪来输入艺术家手绘的图片,以及相机。相机可用于拍摄绘制的艺术作品的照片。所有这些额外成本都需要仔细考虑,并且仅取决于项目的级别。
但是,硬件考虑因素不仅限于您将使用的工具,最重要的是运行已完成产品的需求,这不仅会影响目标受众,还会影响项目的开发。实现游戏设计的软件需求可能需要访问大量内存,但每次只能使用有限的内存。也可能存在其他限制,例如较弱的 CPU、较弱的处理器缓存或非默认内存对齐要求。
没有花哨的功能,没有额外成本。如果您选择一个虚拟框架,例如使用 Flash 作为开发框架,您将无需考虑和支持特殊的硬件或设置,您还将获得一个 RAD 工具来将您的概念付诸行动。
发行媒介对于确定可以打包多少资源以及如何打包至关重要。
原型旨在进行探索,探索想法一旦融入完整的程序会如何发挥作用。它是对之前从未见过的全新概念进行测试,因此必须在其实现中具有最大的灵活性,以便于改进,因为原型的创建会激发全新的想法。如果在原型设计阶段没有探索新概念,那么原型本身还有什么意义呢?
原型设计应该快速完成,然后需要更快地进行更改。要做到这一点,原型设计必须可维护,并且使用灵活且编写良好的代码库。但请记住,原型只有在足够好以证明您的愿景正确并被真正的实现所取代时才有用;如果您在原型上花费了太多时间,以至于您开始质疑它的替代,那么您走错了路或在应该保持为总体规划的第一次尝试上花费了太多精力。
游戏的框架基本上是所有用于创建游戏但并未直接实现任何游戏玩法的编程。这可以是管理显示、文件访问、声音和其他外围设备的代码。
没有适用于所有视频游戏的框架。每个游戏都需要选择组件以及将它们链接在一起的策略。使用免费提供的框架甚至授权流行的框架的好处是,您无需“重新发明轮子”,并获得支持和协作来解决问题并扩展功能。事实上,创建自己的框架的唯一优势是能够对其进行控制,这可能是由于需要实现其他人反对的东西,或者只是为了从这项特定工作中获得经济补偿并将其授权给其他人。
有许多适用于游戏编程的 API。API 的范围从专门(仅限图形,如 OpenGL)到非常非常广泛(窗口、图形、网络等在 ClanLib 中可用)
- OpenGL -- 具体来说,这是一个图形库。一些其他 API 可以很好地与 OpenGL 集成(例如 SDL)。它也是跨平台的。
- DirectX -- 一组由 Microsoft 提供的 API,专门用于运行 Windows 的机器,尽管它也存在于其他 Microsoft 平台上(xbox 1 使用了修改后的 DirectX API 版本)。它们包括声音、音乐、图形、输入和网络。
- SDL(简单直接媒体层) -- 一个基于 C 的良好库,可移植性非常高,虽然非常底层,但它已经足够完整,可以控制声音、图形和输入(来自操纵杆、键盘、鼠标和 CD-ROM)。zlib/png 许可证。
- SFML -- 支持音频、图形、窗口处理、多线程、网络和输入(来自鼠标、键盘和操纵杆)的面向对象的 C/C++/.Net API。
- Allegro -- 一个易于使用的 C/C++ 程序库。跨平台(支持 Windows、DOS、Mac OS X、UNIX 和 BeOS)。提供用于图形、声音、输入和计时器的函数。
- ClanLib -- 一个 C++ 工具包和 OpenGL 2.0 包装器。
图形是游戏环境及其组件的视觉呈现的常用名称。 创建视觉环境通常从概念艺术家开始,根据游戏概念创建视觉表示,不仅包括游戏角色和物体,还包括环境的外观,甚至扩展游戏创造者想象的视觉效果。 这部分工作主要在游戏之外完成,使用专门用于这些不同任务和数据的第三方软件。
游戏的图形不仅限于游戏内艺术,还包括字体设计、标志和营销目的的广告。 它们也会对其他类型的商品产生重大影响,例如 T 恤、玩具或其他衍生产品,例如基于游戏概念的动画系列甚至真人电影。
视觉是人类最重要的感官。 展示一款视觉上令人惊叹的产品将胜过吸引玩家和保证初始销售的大多数其他方面。 我们已经讨论过 为什么有吸引力的展示很重要。
多视图显示
由于如今拥有多显示器设置并不罕见,随着价格持续下降和图像技术提升,游戏中的多显示器支持也将变得普遍。 多显示器设置也可以轻松地将普通视图扩展成马赛克,而无需游戏创建者特别考虑,但拥有不同的屏幕对于策略游戏和模拟游戏来说非常有趣,因为游戏玩法通常允许玩家可视化大量不同的数据。
直到最近,大多数现代游戏似乎都沉浸在 3D 狂潮中,直到手机重新带来了对更简单的视觉效果和传统的 2D 创意和创新的市场。 2D 主要被降级为模拟器和旧游戏模型的重新实现。
在 3D 的初始进步和良好 3D 硬件的开发之后,3D 很快开始成为一种主要用于营销噱头、卖点以及用良好的视觉效果隐藏游戏概念的脆弱性的一种方式,其中性能或视觉真实感取得的每一寸进步都被吹捧为一项革命性的必须看到的发现。 请记住我们之前关于展示的内容,这主要是它的使用方法。 大多数游戏不知道如何以补充游戏玩法和游戏设计的方式使用它。
一款优秀的 3D 游戏使用动态的场景和环境组合,就像电影一样,其目的是展示游戏设计并激发玩家的想象力,但对游戏玩法始终保持敬畏。
游戏引擎应该使用更原始的环境和模型进行调试和测试,特别是对于游戏机。 游戏称为图形引擎的东西用于操纵游戏动画脚本、角色在环境中的位置以及图形渲染的内存分配。 其他数据,例如物理、AI 和游戏脚本,由其他引擎处理。 公众普遍存在一个误解,即游戏仅使用一个“引擎”制作而成。
立体视图
虽然大多数游戏引擎仅打算模拟深度和与其他图形伪影不同的深度环境,但真正的 3D 直到最近才在游戏中流行起来。 有一些技术可以生成和显示 3D 动态图像。 核心要求是显示分别过滤到左眼和右眼的偏移图像,从而为观察到的场景提供独立的焦点,从而提供深度。 已经使用了两种策略来实现这一点:让观看者戴上眼镜来分别过滤偏移图像到每只眼睛,或者让光源将图像方向性地分成观看者的眼睛(不需要眼镜)。 到目前为止,问题在于 CPU 或显卡生成所需的类似但不同的图像,以及生成这些视图的软件,GPU 的兴起以及 3D 电视的采用最终允许普遍使用这种 3D 视图,即使没有大量的游戏实现。
超越多边形
在科学和医学领域,由于其允许使用成像设备(磁性、激光)获得高细节,点云数据的概念开始变得重要。 一家澳大利亚公司 Euclideon 声称使用点而不是多边形来渲染 3D 场景,从而在基于稀疏体素八叉树图形的基础上提高了可能的细节水平。 其他一些公司也在研究这种技术,例如 Atomontage Engine(混合方法)或 Ken Silverman(他还编写了 Build 引擎,用于 Duke Nukem 3D)的 Voxlap 引擎。
用户界面 (UI) 是任何游戏的非常重要的组成部分,因为这通常是新玩家在启动你的游戏时看到的第一件事。 它也(在大多数游戏中)始终对玩家可见,因此明智的做法是花一些时间创建一个直观、易于使用且外观良好的界面! 没有什么比设计糟糕的界面更能让人对一款潜在的优秀游戏感到厌烦了。
用户界面包含
- 图形 - 按钮、信息面板、地图等)
- 布局 - 这些内容在屏幕上的位置
- 交互 - 这些内容如何响应用户输入;它们会调出地图吗?你的库存?访问设置?
UI 可以以 2D 或 3D 方式渲染,界面本身在大多数情况下独立于游戏引擎,充其量它充当玩家与游戏世界的 I/O 界面。 UI 上渲染的许多基元不会出现在游戏引擎中,特别是如果你依赖打包的引擎。
2D 游戏可以有 3D UI,3D 游戏也可以有 2D UI。选择取决于设计和呈现方式。需要注意的是,从计算角度来看,3D UI 会占用更多游戏资源,而且花哨的 UI 往往只对初次接触游戏的人有影响,如果 UI 与游戏玩法没有更深入的整合,这种影响很快就会消失。UI 不应该喧宾夺主,最好是实用且信息丰富。
HUD
[edit | edit source]
打包解决方案
[edit | edit source]商业
- Autodesk Scaleform (http://www.scaleform.com/) - 一个矢量图形渲染引擎,用于在视频游戏行业中作为中间件显示基于 Adobe Flash 的用户界面。HUD 和动画纹理,适用于 Microsoft Windows、Mac OS X、Linux 以及 Xbox 360、PlayStation 2、PlayStation Portable、PlayStation 3、PSVITA、3DS、Wii、iOS 和 Android 平台。
人工智能 (AI)
[edit | edit source]人工智能让你的游戏世界变得生动起来,让游戏中的生物拥有自己的思维。AI 还允许游戏难度发生变化,可以由用户选择自己的难度级别,也可以由游戏根据玩家的技能水平自动调整。在游戏中实现 AI 的方法有很多。
有限状态机
[edit | edit source]《毁灭战士》中使用了一种非常简单的 AI 类型。有限状态机包含一个可能状态(或“情绪”)列表。假设有一个游戏中有警卫在房间里巡逻,寻找入侵者。
假设这些警卫有五个状态
- 巡逻 - 警卫沿着分配给他的路线行走
- 等待或闲置 - 警卫站在某个地方,可能在和附近另一个警卫聊天,抽烟等。
- 可疑 - 警卫听到了一些声音,认为附近有什么东西(例如:警卫听到玩家从悬崖上踢下了一块石头)。
- 警觉 - 警卫明显地看到了你,正在攻击你,或者可能正在呼喊求救。
- 受伤/遇险 - 你伤到了警卫,但警卫还活着,正在逃跑求救。
这些状态将有与警卫的“情绪”相一致的特定动作。巡逻将激活航点系统,警觉将意味着你激活了 AI 的目标系统。
神经网络
[edit | edit source]基于脚本的规则系统
[edit | edit source]程序内容生成
[edit | edit source]这个概念被定义为以程序方式生成任何类型的 2D/3D 几何图形、纹理、脚本或声音的过程,甚至可以使用随机种子。迄今为止,这种技术主要用于创建环境、简单的世界或结构。这种方法也可以应用于许多其他内容,使用严格的定义,它可以与 AI 协同工作(动态环境、物体和生物),但它仍然难以像传统动画一样可靠且逼真,即使它可以提供更大的可变性和复制人声,它仍然处于起步阶段。
除非为了交互性或随机化而存在好处,否则应该避免程序内容生成,因为它在 CPU 周期方面很昂贵,并且通常实施起来很复杂。例外情况是重复但简单的模式,即使没有交互性也可以,例如在模拟水、雨的效应,甚至显示云、烟雾、火焰或爆炸时。程序内容生成的另一个不太重要的因素是最终产品中的空间(大小)限制,由于要使用的媒体或下载的大小。
物理
[edit | edit source]在创建游戏时,有一些功能可以帮助玩家轻松地与创建的虚拟环境进行交互。如果模拟真实的环境,这一点非常重要,因为人们期望游戏是真实的,从物体的轨迹到它们的碰撞方式、质量的感觉以及流体的行为方式以及其他类似的行为,所有这些都可以根据现实世界中也有效的公认公式进行建模。
固体
[edit | edit source]液体
[edit | edit source]- 表面张力
- 粘度
重力
[edit | edit source]光
[edit | edit source]现实主义(现实模拟)
[edit | edit source]物理
[edit | edit source]光影
[edit | edit source]光照和纹理
[edit | edit source]光照贴图
[edit | edit source]纹理
[edit | edit source]凹凸贴图
[edit | edit source]法线贴图
[edit | edit source]视差贴图
[edit | edit source]动画
[edit | edit source]- 添加细节
让游戏包含小的,即使是重复的细节,也会提供更丰富的体验,无论是阵阵风声,一粒尘埃,垃圾桶上的苍蝇,一片随风飘落的树叶,都能像动态光照那样强大,甚至更强大。
水
[edit | edit source]水可能是游戏中最难再现的效果,它包含反射、透明和扭曲,像波浪、泡沫一样的高细节,而且是一种流体,表现得像固体和液体一样,所以根据想要达到的细节程度,这将不仅仅是一项艰巨的任务,如果实时完成,还会消耗大量的计算能力。
沙
[edit | edit source]火
[edit | edit source]风
[edit | edit source]声音
[edit | edit source]对于我们引擎的这部分,我们将使用 OpenAL API。为什么?因为在选择 API 时,我们已经概述了以下简单的原因:它是开源的、跨平台的、功能强大的,同时仍然相对易于使用。所以让我们开始吧……
在我们的游戏世界中,所有可以发出声音的对象都有一个位置(背景音乐除外)。声音还与某种触发事件相关联,因此当玩家执行某些操作来激活触发器时,声音就会开始播放。很简单吧!那么我们现在究竟如何实现这一点呢?
OpenAL 基于拥有一个源(播放的声音)和一个监听器(聆听的人)的概念,这两个对象可以放置在我们 3D 环境中的任何地方,并赋予某些属性,例如使用哪种衰减模型、源的移动速度等,但我们稍后会讲到这些。你还可以拥有许多源(这是有道理的),但只有一个监听器(这也是有道理的)。当你添加一个声音供 OpenAL 播放时,你首先需要做三件事:创建一个缓冲区,用来加载音频数据到其中,然后创建一个源,然后将源与缓冲区关联起来,这样 OpenAL 就能知道从哪个源播放哪个音频。因此,考虑到所有这些因素,我们将把每个源封装到一个 C++ 结构体中。这个结构体,我们将其命名为 newSource,将保存源的位置信息作为 sourcePos[3],一个 sourceID 和一个 bufferID,以便我们可以唯一地寻址每个源。
我们还需要考虑的是,由于 OpenAL 很乐意根据距离为我们衰减声音,我们需要在玩家到达源的“外边界”(你不再能听到声音播放的点)时开始播放声音。因此,我们还会在结构体中添加一个 activateDistance 值。
此外,我们需要考虑到,由于声音数据无法从硬盘中立即加载,因为与内存相比,硬盘的速度非常慢。因此,我们还会在结构体中添加一个 preloadDistance 值,这样当我们移动到该值的范围内时,声音就会加载到缓冲区中,当我们移动到 activateDistance 值的范围内时,声音就会开始播放。真棒吧!
最后,由于我们很有可能会有不止一个源(如果没有的话游戏会很无聊),我们将把我们的结构体塞进一个 C++ 向量中(如果你不知道什么是向量,它只是一个数组,但功能更多),我们将将其命名为 pipeline。我们还需要添加一些功能来从管道中删除“死”源并释放内存,但我们稍后会讲到这一点。
为了说明所有这些是如何组合在一起的。
这个示例说明了 preloadDistance、activateDistance 和 sourcePos 在“游戏内”视图中的位置。
因此,概述一下这个过程:
- 当玩家移动到红色外球的范围内时,就会创建一个新的 newSource 结构体,声音加载到缓冲区中并被推送到 pipeline 中。
- 当玩家移动到黄色球的范围内时,声音就会开始播放,当玩家向白色内球靠近时,声音会越来越大,直到在白色球处达到最大音量。
- 反之,当玩家离开白色球时,声音的音量会降低,直到你移动到黄色球的外面,此时声音会关闭,但仍然保留在 pipeline 中。
- 当玩家离开红色球时,源就会从 pipeline 中删除并销毁(剔除),这样我们就可以避免占用不必要的内存。
虽然存在多种类型的电子游戏,但有一些属性是恒定不变的:每个游戏都需要至少一名玩家,每个游戏都会给玩家至少一项挑战,每个游戏都使用显示器,每个游戏都至少有一种输入/控制方法。
用户界面
[edit | edit source]正如本章开头所述,用户界面由精灵、菜单等组成。它是提供给用户用来控制游戏内操作的东西。这些图形被定义为按钮,可以被按下,或者是一个角色,可以用箭头键移动。所有这些元素都是用户界面的一部分。
主菜单
[edit | edit source]首先,几乎所有电子游戏都会启动到主菜单。这通常是一个带有某种背景的屏幕,上面排列着一些按钮,用于执行诸如新游戏或开始游戏、选项、加载游戏和退出游戏之类的操作。
此屏幕充当游戏的控制面板,允许玩家更改设置、选择模式或访问实际游戏。
有时,游戏会使用主菜单作为游戏内菜单。游戏内菜单通常在游戏过程中通过Esc 键或开始按钮访问。游戏内菜单允许玩家访问大多数主菜单操作,并提供其他操作,例如显示角色属性、点数、库存等。不过,并非所有菜单都必须是带有文字的正方形。游戏 圣剑传说 使用了一个创造性的菜单,在该菜单中,关卡保持在焦点位置,而选择项围绕着玩家形成一个圆圈。
这些菜单不是必需的,但传统上会包含它们。
开始游戏
[edit | edit source]当你第一次启动游戏时,会显示一系列启动画面。启动画面包含诸如徽标、电影等元素。这通常用于告诉玩家哪些公司直接参与了游戏,有时还会部分或全部介绍游戏剧情。
当实际游戏开始时,通常会播放一个介绍性的电影,介绍剧情的序幕。这不是你在电影院看到的电影,而是通常是使用游戏自身图形和声音制作的更精美渲染。
在大多数游戏中,你接下来会被要求输入你的名字,在某些游戏中,你可以自定义角色、设置等。
游戏的这个阶段被称为教程。它并不总是被认为是游戏剧情的一部分,但在某些游戏中,它被整合到游戏中,即使是教程阶段,它也是游戏剧情的一部分。我们将称之为教程整合。它广泛用于诸如 塞尔达传说 和 超级马里奥 64 等游戏中。
玩游戏
[edit | edit source]在游戏过程中,几乎所有游戏都会使用一些基本概念。它们列在下面。
玩家与角色的关系
[edit | edit source]玩家在角色中的作用。玩家如何控制角色?通常有 3 种 PCR,第 3 人称、第 1 人称和影响。
第 3 人称:玩家不是角色,而是以非人物化的方式控制角色/角色。
第 1 人称:玩家就是角色/角色,并从角色的角度以个人和视觉方式看待事物。
影响:玩家不受限于任何角色/角色,而只是在游戏中发挥影响力。这在像俄罗斯方块这样的益智游戏中很常见,在 RTS 游戏中也很常见。
游戏世界
[edit | edit source]游戏描绘的“世界”是什么?这里有两个需要考虑的问题。
角色作用:角色在游戏本身中扮演什么角色也是一个问题,从这个意义上讲,有三种类型。
主角:一切都围绕着角色/角色,拯救世界的类型。在《塞尔达传说》、《马里奥》、《最终幻想》等游戏中可见。
街机传统:一个非人物化的街机角色。
影响力:角色是游戏中一个无名的影响力。
法则 定义领域的法律、概念、规则等是什么?
图形 什么是可见的以及风格法则
声音 什么是可听见的以及风格法则
游戏性 如何玩游戏
保存/加载
[edit | edit source]考虑到游戏的保存和加载,通常这可以是一个基本的菜单操作,玩家在其中输入保存名称,然后游戏就会保存。但在某些游戏中,采用了更具创意的方法,这样玩家就不会被从游戏体验中拉出来。《银河战士》就是用它的存档点来实现这一点。
然而,加载通常是一个菜单操作。
主循环
[edit | edit source]我们游戏的核心是主循环(或游戏循环)。与大多数交互式程序一样,我们的游戏会一直运行,直到我们告诉它停止。每次循环就像游戏的心跳。实时游戏的循环通常与视频更新(垂直同步)绑定。如果我们的主循环与固定时间硬件事件(如垂直同步)同步,那么我们必须将每次更新调用的总处理时间控制在该时间间隔内,否则游戏将“卡顿”。
// a simple game loop in C++ int main( int argc, char* argv[] ) { game our_game; while ( our_game.is_running()) { our_game.update(); } return our_game.exit_code(); }
每个主机制造商都有自己的视频游戏发布标准,但大多数要求游戏在启动后的几秒钟内提供视觉反馈。作为一般设计准则,最好尽快为玩家提供反馈。
因此,大多数启动和关闭代码通常从主循环中处理。冗长的启动和关闭代码可以在从主 update() 函数监控的子线程中运行,或者切分成小块,并按照顺序从 update() 函数本身执行。
状态机
[edit | edit source]即使不考虑游戏本身的各种游戏模式,大多数游戏代码也属于几种状态之一。游戏可能包含以下状态和子状态
- 启动
- 许可证
- 开场动画
- 前端
- 游戏选项
- 声音选项
- 视频选项
- 加载屏幕
- 主游戏
- 简介
- 游戏
- 游戏模式
- 暂停选项
- 结束游戏动画
- 片尾
- 关闭
在代码中对这种模型的一种方法是使用状态机
class state { public: virtual void enter( void )= 0; virtual void update( void )= 0; virtual void leave( void )= 0; };
派生类可以覆盖这些虚拟函数,以提供特定于状态的代码。然后,主游戏对象可以保存一个指向当前状态的指针,并允许游戏从一个状态流向另一个状态。
extern state* shut_down; class game { state* current_state; public: game( state* initial_state ): current_state( initial_state ) { current_state->enter(); } ~game() { current_state->leave(); } void change_state( state* new_state ) { current_state->leave(); current_state= new_state; current_state->enter(); } void update( void ) { current_state->update(); } bool is_running( void ) const { return current_state != shut_down; } };
时间
[edit | edit source]游戏循环必须同时考虑实际时间和游戏时间的流逝。将两者分开可以使慢动作(即子弹时间)效果、暂停状态和调试变得更加容易。如果你打算制作一款可以倒流时间的游戏,比如《布林克斯》或《时间沙漏》,你需要能够在游戏时间倒流的同时,让游戏循环向前运行。
围绕时间的另一个考虑因素取决于你是否要采用固定帧率或可变帧率。固定帧率可以简化游戏中的许多数学运算和时间计算,但它们会使游戏更难移植到其他地区(例如,从美国 60 Hz 电视机移植到欧洲 50 Hz 电视机)。因此,建议将帧时间作为变量传递,即使该值从未改变。当每帧的工作负载达到极限时,固定帧率会受到卡顿的影响,这比较低的帧率感觉更差。
另一方面,可变帧率会自动补偿不同的电视刷新率。但与固定帧率游戏相比,可变帧率往往感觉很卡。调试,特别是调试时间和物理问题,在可变时间下通常更困难。在代码中实现时间计时时,给定平台上通常有几种可用的硬件计时器,它们通常具有不同的分辨率、访问它们的开销和延迟。请特别注意可用的实时时钟。你必须使用分辨率足够高的时钟,同时不要使用过高的精度。你可能需要处理时钟回绕的情况(例如,一个 32 位纳秒计时器将在 2^32 纳秒后溢出回零,这只有 4.2949673 秒)。
const float game::NTSC_interval= 1.f / 59.94f; const float game::PAL_interval= 1.f / 50.f; float game::frame_interval( void ) { if ( time_system() == FIXED_RATE ) { if ( region() == NTSC ) { return NTSC_interval; } else { return PAL_interval; } } else { float current_time= get_system_time(); float interval= current_time - last_time; last_time= current_time; if ( interval < 0.f || interval > MAX_interval ) { return MAX_interval; } else { return interval; } } } void game::update( void ) { current_state->update( frame_interval()); }
加载
[edit | edit source]现代游戏通常直接从 CD 加载,或者间接从硬盘加载。无论哪种方式,你的游戏都可能花费大量时间进行 I/O 访问。磁盘访问,尤其是 CD 和 DVD 访问,比游戏的其他部分慢得多。许多主机制造商将其作为一项标准,即所有磁盘访问必须以视觉方式指示;而无论如何,这也不失为一个好的设计选择。
但是,大多数磁盘访问 API 函数(特别是那些通过 C 运行时库的标准 I/O 映射的函数)会使处理器停滞,直到传输完成。这被称为同步访问。
多线程磁盘访问
[edit | edit source]在访问磁盘时获得反馈的一种方法是在单独的线程中运行磁盘操作。这具有允许其他处理继续进行的优点,包括绘制磁盘操作的一些视觉反馈。但代价是需要编写更多代码,并且需要同步对资源的访问。
异步磁盘访问
[edit | edit source]一些主机操作系统 API 通过允许使用异步读取操作来调度磁盘访问,从而为你处理了一些多线程代码。异步读取可以通过轮询文件句柄或使用回调来确定它们是否已完成。
可渲染对象
[edit | edit source]无论游戏使用 2D 图形、3D 图形还是两者的组合,引擎都应该以类似的方式处理它们。需要考虑三个主要方面。
- 某些对象可能需要一段时间才能加载,并且可能会暂时冻结游戏。
- 有些机器比其他机器运行速度更慢,游戏必须以低帧率继续进行。
- 有些机器运行速度更快,动画可能会比具有较高帧率的时间间隔更流畅。
因此,创建一个作为接口的基类是一个好主意,它将这些函数分开。这样,每个可绘制对象都可以以相同的方式处理,所有加载都可以同时进行(用于加载屏幕),所有绘制都可以独立于时间间隔进行。OpenGL 还要求对象显示列表具有唯一的整数标识符,因此我们还需要支持分配该值。
class IDrawable { public: virtual void load( void ) {}; virtual void draw( void ) {}; virtual void step( void ) {}; int listID() {return m_list_id;} void setListID(int id) {m_list_id = id;} protected: int m_list_id; };
一种常见的碰撞检测方法是使用轴对齐边界框。为了实现这一点,我们将基于我们之前的接口 IDrawable。它应该与 IDrawable 保持分离,因为毕竟,并非屏幕上绘制的每个对象都需要碰撞检测。一个 3D 框应该由六个值定义:x、y、z、宽度、高度和深度。该框还应该返回对象在空间中的当前最小值和最大值。这是一个示例 3D 边界框类
class IBox : public IDrawable { public: IBox(); IBox(CVector loc, CVector size); ~IBox(); float X() {return m_loc.X();} float XMin() {return m_loc.X() - m_width / 2.;} float XMax() {return m_loc.X() + m_width / 2.;} float Y() {return m_loc.Y();} float YMin() {return m_loc.Y() - m_height / 2.;} float YMax() {return m_loc.Y() + m_height / 2.;} float Z() {return m_loc.Z();} float ZMin() {return m_loc.Z() - m_depth / 2.;} float ZMax() {return m_loc.Z() + m_depth / 2.;} protected: float m_x, m_y, m_z; float m_width, m_height, m_depth; }; IBox::IBox() { m_x = m_y = m_z = 0; m_width = m_height = m_depth = 0; } IBox::IBox(CVector loc, CVector size) { m_x = loc.X(); m_y = loc.Y(); m_z = loc.Z(); m_width = size.X(); m_height = size.Y(); m_depth = size.Z(); }
虽然在大多数 API 中显示图像或纹理立方体很简单,但随着你开始为你的游戏添加更多复杂性,任务自然会变得稍微困难一些。对于结构不良的引擎,这种复杂性会随着你的引擎变大而变得越来越明显。它可能变得不清楚需要哪些更改,你可能会最终得到巨大的特殊情况 switch 块,而一些简单的抽象可能会简化问题。
这与上面的观点相关联 - 随着你的游戏引擎发展,你将希望添加新功能。对于无结构的引擎,这些新功能很难添加,并且可能花费大量时间来找出为什么该功能无法按预期工作。也许是某些奇怪的函数正在中断它。精心设计的引擎将任务分开,以便扩展特定区域就是那样 - 而不是必须修改之前的代码。
通过精心设计的游戏引擎设计,你将开始了解你的代码。你会发现自己花更少的时间盯着(或者可能诅咒)空白屏幕,想知道为什么你的代码没有做你认为你告诉它的。
DRY 是一个经常使用(尤其是在极限编程环境中)的缩写词,它代表*不要重复自己*。听起来很简单,但可以为你节省更多时间去做其他事情。此外,执行特定任务的代码位于一个中心位置,这样你就可以修改该小部分并看到你的更改在所有地方生效。
上面的观点可能对你来说并不那么令人难以置信 - 它们确实是常识。但如果没有设计游戏引擎时的思考和规划,你会发现实现这些目标会困难得多。