《Windows游戏编程大师技巧》学习笔记(一)
一般的游戏循环结构
一个视频游戏基本上是一个连续的循环,它完成逻辑动作并以每秒30帧或更高的刷新率在屏幕上绘制图像,与动画和电影的放映原理相似,简化的游戏循环结构如下图所示:
对上图每一部分流程进行说明:
- 初始化:游戏程序执行初始化操作,如内存分配、资源检查与加载等;
- 进入游戏循环:代码进入到游戏主循环体内部,各种操作开始运行,直到用户退出主循环;
- 获取玩家输入:缓存/处理玩家通过鼠标、键盘或手柄等设备的输入信息,以备后续游戏逻辑使用;
- 执行游戏逻辑部分:执行诸如人工智能、物理系统等游戏逻辑的更新,更新后的数据用于渲染下一帧图像;
- 渲染下一帧图像:根据前述的输入和逻辑处理,游戏的下一帧动画已经具备渲染条件;渲染中的图像常被放置于不可见的缓冲区,因此玩家不会看到这一帧画面被逐步渲染的过程;渲染完成后的图像会从缓冲区中迅速拷贝至显示设备中(双缓冲原理);
- 同步显示:随着时间推移,渲染每一帧游戏所需要的数据量和运算量可能会有较大变化,对计算机设备的负荷也有所不同,在不加限制的情况下就会导致游戏画面刷新率(帧率)时高时低;所以必须通过定时功能来维持帧率稳定;
- 循环:重复执行从“进入游戏循环”开始到现在的步骤;
- 退出:到达这一步表示游戏将关闭并返回操作系统,执行的操作与“初始化”阶段相反:对必要的数据进行持久化,释放内存等相关资源。
游戏循环与FSM
在大多数情况下,游戏循环是一个含有大量状态的FSM(Finite State Machine,有限状态自动机),如下图所示:
简化的代码如下:
1 |
|
除去上述内容,我们还可以声明变量存储游戏中的异常信息,并在main
函数结束时将错误码返回给操作系统。
常规游戏编程技巧
视频游戏是超高性能的计算机程序,所以必须对其运行时间和内存要求严格把控,避免在游戏主循环内部调用太多高层API,否则可能出现性能问题;下面是作者特别指出的几个编程技巧:
- 不要怕使用全局变量:虽然这可能会扰乱全局命名空间,但是由于参数需要压栈和出栈,对于某些内部逻辑简单的函数,调用它所需要的时间可能会远大于执行它所需要的时间,而全局变量可以避免这个问题,如下例:
1 | // 使用参数对所需数据进行传递 |
- 使用内联函数:与上一条相似,同样也是为避免参数传递带来的性能损耗,inline可以完全摆脱函数调用,但是带来的弊端是可能使编译后的程序体积变大;注意,在使用inline时遵循上一条规则同样合适,尤其是在函数调用时只有一两个参数改变了值的情况——其余旧值可以无须重新加载便可使用;
- 尽量使用32位变量而不是8位变量或16位变量:重点在于字节对齐,提高内存寻址效率,如下例:
1 | // 坏的示例:2 * sizeof(short) + sizeof(char) = 5 bytes |
除去上述方法,还可使用编译器指示符,如 #pragma pack(n)
来设定结构体、联合以及类成员变量以n字节方式对齐;当然,这样带来的弊端就是会因为填充而浪费过多内存,但是在大多数情况下,较之速度的提高,这点代价是值得的;
4. 注释代码:为了确保隔夜的代码依然能够被自己读懂;
5. 简化指令:当用类似RISC(精简指令集计算机)来编程时,尽可能简化代码,这些计算机的处理器特别喜欢简单的指令,而不是复杂的指令,这样对编译器同样友好,如下例:
1 | // 坏的示例 |
按照此方式编写代码原因有二:首先,它可以运行调试程序在代码各部分之间放置断点;其次,在处理器支持的情况下运行更多的执行单元并行处理更多代码;
6. 使用二进制移位运算:对于乘数或除数是2的幂的运算,使用左移或右移有利于提高计算效率;
7. 设计高效的算法:使用清楚、高效的算法,而不是暴力穷举;
8. 不要在编程过程中优化代码:在绝大多数情况下这只是浪费时间,建议将代码优化的工作放到模块完成或者整个程序完成后再进行;除此之外,性能优化不能只凭借经验和感觉,必须要以性能测试(Profiling)结果为依据;
9. 注意代码格式:各层次代码要错落有致,对阅读和理清逻辑关系大有用处,不要写的杂乱无章缩进混乱;
10. 不要为简单对象定义太复杂的数据结构:确保你的数据结构正好适合你真正要解决的问题,链表很好用,但是无需在设计固定大小的元素容器时抛弃数组,静态分配内存会更有好处;
11. 对C++谨慎:标准日新月异,高级特性越来越多,但是与上一条相同,我们只需要用合适的设计恰到好处地解决问题,无需设计过多class,并把任何东西都重载,简单直观的代码是最好的,也最容易调试;
12. 勇敢地断舍离:如果已经意识到了自己的编程思路是错误的,那就及时调转车头绕路而行,在工作中发现问题,重新评估总是比硬着头皮走下去更节约时间和精力;
13. 及时备份你的工作:Git是个好东西,尤其是项目逐渐复杂起来的时候,快速定位在稳定版本之后的修改对错误排查也大有用处;
14. 在开发前先规划好项目:文件名、目录名,以及变量的命名规范等,对图形和声音资源分开存放,策划的工作要先于程序进行;
15. 使用合适且专业的软件:虽然用Windows画板完成所有的游戏素材让人敬佩,但是使用PS或许会节省大量时间精力,以及,获得更好的画面效果。
《Windows游戏编程大师技巧》学习笔记(一)