4.2.4 CGameEngineGDIBase类
下面对CGameEngineGDIBase类进行概要的介绍:
● 目的 一个CGameEngineBase类的实现,提供GDI图形所需的功能。
● 类型 抽象基类。
● 父类 CgameEngineBase。
● 子类 各个游戏,创建在独立的程序集中。
● 主要功能
● Prepare 为执行GDI渲染做好准备。
● Render 提供有效的图形渲染技术。
● Present 将生成好的图形显示到屏幕上。
抽象引擎对象与抽象游戏对象都已经就位了,现在要为GDI绘制引擎添加功能。CGameEngineGDIBase类仍然被声明为abstract,但实际的游戏类将从它继承而来。
该类附加函数中最有意义的是Render方法。我们来看看该方法以及这里实现方式上的区别。
1. 渲染
每个对象需要对后台缓冲区进行更新时,都会使用Render函数。我们要进行许多需要的操作:
● 如果后台缓冲区尚未执行初始化,则进行初始化。
● 清空背景。
● 向后台缓冲区中绘制所有对象。
● 使游戏窗体失效,触发一个Paint事件,这样我们就可以将修改了的后台缓冲区复制到窗体中。
我们首先来讨论后台缓冲区,正如上一章中所述,这是一个不显示在屏幕上的Bitmap对象,我们将在其中绘制所有的图形对象。它通常维护的是当前要显示的游戏内容的图形。在Render函数的开始阶段,如果对象尚未可用,就会调用InitBackBuffer来对缓冲区进行准备。在本例中,图形后台缓冲区的大小与游戏窗体的大小一致,如程序清单4-7所示。
程序清单4-7 对后台缓冲区进行初始化
/// <summary>
/// If not already ready, creates and initialises the back buffer that we
/// use for off-screen rendering.
/// </summary>
private void InitBackBuffer()
{
// Make a new back buffer if needed.
if (_backBuffer == null)
{
_backBuffer = new Bitmap(GameForm.ClientSize.Width, GameForm.ClientSize.Height);
// Ensure we repaint the whole form
ForceRepaint();
}
}
下一步,清空背景。这里有两种可能的方法:将背景改为纯色,或者在移动的图形背后显示一个背景图像。
如果没有图像,那么调用CreateBackgroundImage函数,该函数为虚函数,继承游戏类可以对它进行重写。如果需要背景图片,可以返回一个包含了背景图片的Bitmap对象。然后在绘制图形之前调用该函数来清空后台缓冲区。
另一方面,如果调用了该函数之后还是没有背景图像,那么游戏会用一个纯色来清除后台缓冲区。通过对象的BackgroundColor属性来指定该颜色。
第三步是将所有的对象都绘制到后台缓冲区中。这里先跳过这一步骤的细节,因为我们马上要在第4.4节中对它进行深入的介绍。可以这样说:所有需要重绘的对象都会在后台缓冲区中绘制好。
最后,我们调用窗体的Invalidate方法来触发重绘事件。就是靠这种机制,将修改后的后台缓冲区中的内容绘制到屏幕上,这样才能被人们看到。当该事件被触发时,通过传递窗体的Graphics实例,在CGameEngineGDIBase.Present方法中会对窗体进行调用。我们很快就会看到窗体是如何与引擎相联系的。