考虑到这一点3d游戏开发编程基础,本书将重点关注 3D 数学和图形学,仅简要介绍与游戏编程相关的内容。 我认为您已经了解这些内容 - 如果您不了解,我建议您阅读《Windows 游戏编程大师技巧》或其他优秀的游戏编程书籍,并在计算机上进行练习,以熟悉 Windows、DirectX 和游戏编程。 另一方面,即使你没有读过《Windows 游戏编程大师技巧》,不懂游戏编程,你仍然可以从这本书中学到一些东西,因为它是一本关于图形学的书。 我们将在每一章中逐步构建 3D 引擎,但为了节省时间,我们将基于《Windows 游戏编程大师技巧》中开发的基本 DirectX 引擎。 它将在 2D、声音、音乐、输入等方面有所帮助。 当然材质材料,引擎是DirectX 7/8引擎,而DirectX 8.0+中所做的修改使2D编程变得更加困难,因为DirectDraw已经集成到Direct3D中。 我们将继续使用DirectX 7/8接口,但在DirectX 9.0 SDK下编译。 注意:本书涵盖软件和算法,而不是DirectX,因此引擎将在DOS下编写。 只需要适当的高级图形、I/O 和声音层,因此 DirectX 8.0+ 是一个合理的选择。
如果读者是Linux用户,将引擎移植到SDL是相当容易的! 因此,如果你读过《Windows游戏编程大师技巧》,你就会熟悉这个引擎及其功能; 否则,它可以被视为一个黑盒API(当然包括源代码),因为本书将逐步构建在该引擎上。 添加 3D 功能。 别担心,下一章会介绍整个2D引擎及其结构,你会知道各个函数的作用; 我还将提供一些演示程序,帮助您熟悉使用《Windows 游戏编程大师技巧》中创建的基本 DirectX 引擎。 本书将从总体角度介绍图形系统。 本书中的代码将基于《Windows 游戏编程大师技巧》中创建的引擎,该引擎使用标准线性寻址构建双缓冲图形系统。 只需几个小时或一个周末即可将您的代码移植到 Mac 或 Linux 平台。 本书的目标是从一般角度介绍 3D 图形和数学。 DirectX所基于的Windows平台是目前最流行的计算机操作系统,因此将基于它进行介绍。 本书的重点是高级概念。 我已经编写了大约 20 个 3D 引擎,它们都存储在我的硬盘上。 但在写这本书时,我想随着本书的进展编写一个新的 3D 引擎,因此为这本书编写一个引擎,而不是写一本关于引擎的书。 这本书不是关于3D引擎的,而是关于如何编写3D引擎的。
因此,我不知道我最终会得到什么样的 3D 引擎! 事实上,我对我将要看到的东西感到非常兴奋。 我正在尝试编写一个类似于Quake的6DOF(自由度,自由度)引擎,但谁知道结果会是什么? 您将学习创建 Quake 引擎所需的所有知识游戏评测,但我将重点关注户外引擎或其他内容 - 谁知道呢。 重点是3d游戏开发编程基础,本书将提供一个学习过程,而不是充满作者注释的典型代码。 我想你很清楚我在说什么! 最后,读过《Windows 游戏编程大师技巧》的读者可能还会注意到,本书中有些地方与那本书相同。 事实上,我根本没有办法不重复上一本书的内容就直接介绍3D图形。 我不能假设每个人都购买了《Windows 游戏编程大师技巧》,也不能强迫他们这样做。 总之,本书的前几章包含了一些与DirectX、引擎和Windows相关的内容。 1.2 2D/3D 游戏的要素 我们首先回顾一下视频游戏程序与其他程序的区别。 视频游戏是一些相当复杂的软件。 毫无疑问,它们是最难编写的程序。 确实,编写像 MS Word 这样的东西比编写明星游戏更难,但是编写像 Unreal、Quake Arena 或 Halo 这样的游戏比编写我能想象到的任何其他程序都更难 - 包括军事武器控制软件! 这意味着您必须学习一种有利于实时应用程序和模拟的新编程方式,而不是您习惯的单线、事件驱动或顺序逻辑程序。
视频游戏本质上是一个执行逻辑并在屏幕上绘制图像的连续循环——通常以每秒 30 到 60 帧或更高的速度。 这与电影的播放方式类似,只不过您可以控制电影的情节。 首先,我们来看一个简化的游戏循环,如图 1.1 所示。 接下来的几节描述了游戏循环的各个部分。 1.2.1 初始化 这部分执行类似于任何其他程序的标准操作,例如内存分配、资源获取、从磁盘加载数据等。 1.2.2 进入游戏循环 这部分进入主游戏循环。 用户将继续在此处执行操作,直到退出主循环。 图 1.1 一般游戏循环架构 1.2.3 读取玩家输入 这部分处理玩家输入或将其存储在缓冲区中以供 AI 和游戏逻辑使用。 1.2.4 执行AI和游戏逻辑这部分包含游戏代码的主要部分,它将执行人工智能、物理系统和通用游戏逻辑,并根据结果在屏幕上绘制下一帧。 1.2.5 渲染下一帧 在这一部分中,将根据玩家输入以及游戏AI和逻辑的执行结果生成下一帧游戏动画。 此类图像通常在离屏缓存中绘制,因此用户无法看到渲染过程。 图像的下一帧被快速复制到可见区域以生成动画图像。 在基于 3D 软件的引擎中,非常复杂的 3D 图形管道将渲染构成世界的数千(甚至数百万)个多边形; 在基于OpenGL或Direct3D的3D硬件加速引擎中,大部分工作取决于硬件。
1.2.6 同步显示 许多计算机会根据当前正在执行的游戏的复杂程度来提高或降低速度。 例如,如果屏幕上有 1000 个对象,则 CPU 上的负载将比只有 10 个对象时更重。 结果,游戏的帧率会发生变化,这是不可接受的。 因此,您必须使用计时函数或等待函数将游戏同步到某个最大帧速率并维持该帧速率。 一般来说,30帧/秒是可接受的最低帧率,60帧/秒是理想的帧率。 将帧速率提高到每秒 60 帧以上并没有多大意义,因为人脑很难处理每秒 60 帧以上的信息。 注意:虽然有些游戏理论上可以达到30到60帧/秒,但随着3D渲染复杂度的增加,帧率会下降。 如果在代码的游戏逻辑、物理模型和AI部分使用基于时间的计算,则可以在一定程度上保持显示速率尽可能稳定。 也就是说,如果在运动和动画控制中使用时间(t)进行计算,您将得到显示速度更稳定的动画。 1.2.7 循环 这部分非常简单,只需回到游戏循环的开头并重新执行整个循环即可。 1.2.8 关闭 这是游戏的结束,意味着用户已经退出主游戏或游戏循环并返回到操作系统。 然而,与任何其他软件一样,在返回操作系统之前需要释放所有占用的资源并清理系统。 现在,您可能想了解实际游戏循环的所有细节。 诚然,上面的介绍有点过于简单,但它涵盖了游戏的最佳部分。
事实上,在大多数情况下,游戏循环是一个包含多个状态的 FSM(有限状态机)。 例如,以下程序清单更详细地说明了 C/C++ 游戏循环。 程序清单 1.1 一个简单的游戏事件循环 // 代表游戏循环状态的常量 #define GAME_INIT // 游戏正在初始化 #define GAME_MENU // 游戏处于菜单模式 #define GAME_START // 游戏将开始运行 #define GAME_RUN / / 游戏正在初始化 Run #define GAME_RESTART // 游戏将重新启动 #define GAME_EXIT // 游戏正在退出 // 全局变量 int game_state = GAME_INIT; // 游戏状态 int error = 0; // 用于将错误发送回操作系统 // 主循环 void main(){// 执行主游戏循环 while (game_state!=GAME_EXIT) { // 检查游戏循环状态 switch(game_state) {case GAME_INIT : // 游戏正在初始化 {// 分配所有内存和资源Init( );// 切换到菜单模式 game_state = GAME_MENU;} break;case GAME_MENU: // 游戏处于菜单模式 {// 调用主菜单函数并让它切换状态 game_state = Menu(); // 这里可以直接切换到运行状态 }break;case GAME_START: // 游戏即将运行 {// 这个状态是可选的,但通常用于为游戏运行做准备 // 也可以做一些清理工作工作Setup_For_Run(); // 切换到运行状态 game_state = GAME_RUN;} break;case GAME_RUN: // 游戏正在运行 {// 这部分包含了整个游戏逻辑循环 // 清屏 Clear(); // 读取输入 Get_Input(); // 执行逻辑和 AIDo_Logic(); // 显示下一帧 Render_Frame(); // 将显示速度同步到30帧/秒 + Wait(); // 改变游戏状态的唯一方法是通过用户交互} case GAME_RESTART: // 游戏重新启动 {// 这部分是清理状态 // 用于在重新运行游戏之前解决剩余问题 Fixup(); // 切换到菜单模式 game_state = GAME_MENU;} break; case GAME_EXIT: // 游戏正在退出 {//如果游戏处于该状态 // 释放所有占用的资源 Release_And_Cleanup(); // 设置错误变量 error = 0; // 这里不需要切换状态 // 因为处于退出状态后,代码会在下一个循环中退出循环,返回到操作系统}break;default:break;} // 结束切换 } // end while // 返回错误代码给操作系统 return(error); } // end main 虽然上面的代码并没有真正运行,但是通过研究它们,你可以了解一个真实游戏循环的结构。 所有游戏循环(2D 和 3D 游戏)都以某种方式采用这种结构。 图1.2展示了游戏循环逻辑的状态切换图。 看过图1.2游戏循环逻辑状态切换图的人可以看到,状态切换是一个串行化的过程。 中国3D游戏编程掌握技巧第一章中国3D游戏编程入门 – 4 – – 5 – 第一网络电脑书店 – 2 –