简单的说,游戏中的实体对象指的是地图、精灵等。在设计实体类的时候,最直接的做法就是把所有与该实体相关的数据,方法,事件等封装到一个类中。当需要一个新的实体时,用该实体类创建一个新的实体的对象,然后初始化数据。该设计的主要问题是,实体数据与对象耦合太紧密,在以数据为中心的环境中,不利于实体对象的重用。举例来说,假设下面精灵类:
class
Sprite:Canvas
{
data1;
data2;
data3;
method1;
method2;
method3;
...
}
{
data1;
data2;
data3;
method1;
method2;
method3;
...
}
当客户端从服务器得到精灵数据,需要创建一个精灵对象,并用该精灵数据初始化精灵对象。由于精灵类继承自Canvas类,同时自己又包含很多逻辑和状态,频繁新建和销毁精灵类可能会影响性能,所以我们希望能够尽量重用精灵类。即某精灵被杀死或者离开可视范围后,不是销毁该精灵对象,而是把该精灵置为不可见。
如果精灵数据和对象耦合过于紧密,重用精灵对象很不方便。因为在游戏构架上,数据传输应该与游戏表现分离。也就是说,在数据传输模块不应该直接操作已经存在的精灵对象,已经存在的精灵对象应该只对游戏表现模块可见。我们知道,清晰的模块设计会大大降低总体的复杂度,尤其是项目越来越大的时候。
解决上面问题的一个办法就是把实体的对象与数据分离。具体来说,就是为该实体定一个数据类,把所有与传输相关的数据封装到这个数据类中。
class
Sprite:Canvas
{
SpriteData spriteData;
method1;
method2;
method3;
...
}
class SpriteData
{
data1;
data2;
data3;
}
{
SpriteData spriteData;
method1;
method2;
method3;
...
}
class SpriteData
{
data1;
data2;
data3;
}
这样做的好处是:当客户端从服务器得到精灵信息的时候,不必创建复杂的精灵对象,也不需要考虑重用精灵对象,只需要创建一个简单的精灵数据类对象,然后把该精灵数据类对象传递给游戏表现模块处理。
在游戏表现模块,首先搜索置为不可见的精灵对象,如果发现,则重用该精灵对象,用精灵数据类对象来重新初始化该精灵对象。如果没有可以重用的精灵对象,则创建一个新的精灵对象,并用精灵数据类对象来初始化该精灵对象。
结论:
在面向服务、以数据为中心的游戏设计中,把实体类的对象和数据相分离便于重用实体对象,便于游戏模块分离。
在面向服务、以数据为中心的游戏设计中,把实体类的对象和数据相分离便于重用实体对象,便于游戏模块分离。