4.4 优化渲染
目前我们所讨论的代码在每次更新时是这样渲染图形的:
● 清空后台缓冲区。
● 将所有游戏对象绘制到后台缓冲区中。
● 将后台缓冲区呈现在屏幕上。
这种方式很简单,但效率不高。设想一个俄罗斯方块游戏:我们将玩家的方块向屏幕底部降落,游戏区域已经有了很多其他的方块,这些方块已经是完全静止的了。以我们现在所用的渲染步骤,需要在每次更新画面时也对那些静态的方块进行重绘,即使它们与上一次画面更新时相比没有发生任何变化。如果能够只对后台缓冲区中那些实际发生了变化的一部分进行重绘,那么效率将会明显地提高。
该如何做呢?需要下列步骤:
● 判断前一帧绘制完成后,发生了移动的游戏对象所占的区域。
● 清空后台缓冲区,但只清空发生了移动的区域。
● 对与移动区域发生重叠的所有对象进行绘制。
● 将移动区域绘制到屏幕上,保留该区域以外的所有图形不变。
实现这个改进后能使引擎的表现有实质性的改善。尤其是在那种包含了很多静态元素的游戏中,通常可以避免很多不必要的重绘。
实现此优化所需要进行的改动都发生在CGameEngineGDIBase类中,主要是其Render函数。首先要做的是判断上次绘图完成后发生了移动的区域。
这个区域实际上包含了进入了对象的区域(需要渲染移入对象的区域)以及移出对象的区域(也需要被重绘,这样背景或者在该位置的其他任何对象才能重新显示)。对象移出区域的渲染是很重要的,否则旧的对象会在后面形成拖尾。
注意:
在我们的实现中,将只计算游戏的单个移动区域。还有一种方法是计算许多类似的小移动区域,甚至是对每个对象的移动区域都进行计算。在大多数情况下,优化渲染时使用单个区域实际上是一个效率比较高的方法,因为GDI不必对多个单独的小区域进行记录。该技术所用的代码会简单很多,它将Render函数的复杂度降到了最低。
示意图4-4的对小球的移动区域进行了标注,上一次调用Render函数时该区域的位置为灰色,本次调用时该区域为黑色。于是我们需要对方框中原来被小球遮挡了的方框以及该区域的背景进行重绘。被虚线矩形标注出来的区域为移动区域。