2. 存储对象状态
除了对象的位置,在游戏引擎中还有两个与其状态相关的其他属性。它们是IsNew和Terminate。
IsNew用于指示该对象自上次更新后是否已添加到游戏引擎中。我们可以通过该属性来确认对象在屏幕上的初始显示是否正确。对于新对象,该属性会自动被设置为true,当游戏引擎对它进行了一次更新操作后,该属性就自动被设置为false。
Terminate属性(我们曾经提到过)用于请求将对象从仿真环境中删除。要请求终止操作的话只需要将该属性值设置为true,当游戏发生下一次更新时,对象就会从游戏中删除。
3. 对象中的方法
最后,我们需要在引擎中添加两个虚函数,供对象完成操作任务。
首先是Render,对象通过该函数来将自身绘制到后台缓冲区中。与CgameEngineBase类中的Render方法类似,该方法以一个Graphics对象作为参数,在该阶段实际并不做任何操作,它将在继承类的对象中得以使用。
另一个函数是Update。您很快就能看到我们可以使许多对象自主(或部分自主),它们可以控制自己的移动位置,在一定程度上与引擎控制系统保持独立。因此,引擎将调用该函数使对象可以根据需要执行各种力所能及的操作。再一次,在基类中该函数不包含代码,但是继承类要对它进行重写。
4.2.3 CGameObjectGDIBase类
下面对CGameObjectGDIBase类进行概要的介绍:
● 目的 一个CGameObjectBase类的实现,提供GDI图形所需的功能。
● 类型 抽象基类。
● 父类 CgameObjectBase。
● 子类 各个游戏的游戏对象,创建在独立的程序集中。
● 主要功能
● Width和Height 尺寸属性。
● HasMoved和GetRenderRectangle 判断移动状态以及对象所在的区域。
虽然我们对游戏对象类的讨论还不多,但能看到GDI的脉络。CGameObjectGDIBase类是另一个抽象类,其内容不是很多,只是添加了一些使GDI渲染引擎能够高效工作的属性与方法。
1. 在GDI中设置对象的状态
首先要添加的是用于跟踪对象Width和Height的属性。这是两个很重要的属性,根据它们提供的信息就可以得到每个对象在屏幕上占用的空间。在本章后文介绍渲染引擎优化时将使用到它。
我们还要添加一个名为GetRenderRectangle的函数。对象根据自己的位置及尺寸在屏幕上进行绘制,该函数将得到对象占用的矩形区域,并返回该矩形,在对象本身的Render方法中及游戏引擎优化中都将使用该函数,在本章后文中将会看到。在内部,对象也记录了其先前的位置,每当发生移动时,该位置的值都会进行更新。这也对后面的优化有帮助。
2. 对象移动
然后我们添加一个名为HasMoved的属性。我们用它来标识对象是否往某个方向移动了。移动不仅仅包括其位置的变化,还包括对象是否添加到了游戏引擎中,或者对象是否被终止。这些条件中的任何一个如果发生,都需要在窗体上重绘对象。
该属性通过CheckIfMoved函数进行更新。该函数检查对象中的每一个相关的状态属性,如果任何一个状态属性发生变化,就认为对象发生了移动,而将HasMoved属性设置为true,该函数如程序清单4-6所示。
程序清单4-6 CheckIfMoved 函数
/// <summary>
/// Determine whether any of our object state has changed in a way that would
/// require the object to be redrawn. If so, set the HasMoved flag to true.
/// </summary>
internal virtual void CheckIfMoved()
{
if (XPos != LastXPos) HasMoved = true;
if (YPos != LastYPos) HasMoved = true;
if (ZPos != LastZPos) HasMoved = true;
if (IsNew) HasMoved = true;
if (Terminate) HasMoved = true;
}
另外,对任何一个位置属性(Xpos、Ypos或ZPos)进行修改,都将使HasMoved属性被设置为true。