程序清单4-18 ClipRegion可视化调试代码
// Debug: draw a rectangle around the clip area so we can see what we have
// redrawn
using (Pen p = new Pen(Color.Blue))
{
backGfx.DrawRectangle(p, renderRect.X, renderRect.Y,
renderRect.Width - 1, renderRect.Height - 1);
}
运行Bounce项目时启用该代码,屏幕上的显示效果如图4-6所示。
当前绘制矩形后面的方框痕迹显示了每一帧中的ClipRegion。由于我们只对移动区域进行更新,因此旧的绘制区域在屏幕的后面形成了一条轨迹。这可以让我们很容易地看到在游戏运行时对哪些区域进行了绘制。
4.4.1 添加、更新和删除对象
有三个进一步的操作可以影响到移动区域,但与对象的移动并不直接相关:即添加新对象、删除已有对象、更新静态对象的图。
添加一个新对象时,即使它是完全静止的,还是需要对它进行渲染,否则它会保持不可见直到落入到移动矩形区域中。因此,我们需要在每个对象被创建时在其内部设置一个名为IsNew的标志,任何设置了该标志的对象都将被包含到累加的移动矩形区域中,而不用考虑它们坐标的变化。
对象生命周期的另一个端点是终止。当一个对象不再被需要时,我们需要对屏幕区域进行重绘,使该对象从画面中消失。因此我们需要使用一个Terminate标志,在本章中已经多次提到了它。被标记为终止的对象不会被重绘,但它们仍被认为是属于移动矩形区域的。处理完毕后,使用RemoveTerminatedObjects函数将它们从游戏对象列表中删除。
任何没有使用Terminate标志但被直接从列表中删除了的对象将仍然留在屏幕的后面,直到移动矩形将它们完全擦除掉,所以,在终止对象时要记得使用这种方法。
CGameObjectGDIBase包含了Check If Moved函数,游戏的每一步运行都会由引擎来调用该函数。该函数根据条件来查找需要进行重绘的对象(发生移动的对象、新对象或终止对象)。如果发现匹配的对象,就将其HasMoved属性设置为true。然后在下一次调用Render函数时设置它。
最后,我们会碰到这种情形:对象的图像被修改了,但位置并没有发生改变。在这种情况下,需要对它进行重绘才能使用户看到新图像,但就我们目前所描述的条件来看,这种情况不会发生,因为对象都不是新对象,也没有被终止且没有发生移动。
在这种情形下,我们可以将对象的HasMoved属性设置为true,强制对其进行重绘。当下一次调用Render函数时,该函数会查看该标志是否被设置,如果设置了,那么不论其他的属性值如何发生变化,对象都会被重绘。