【讨论】关于游戏实体类继承还是组成自Sprite同时用SpriteBatchNode渲染优化的问题

【讨论】关于游戏实体类继承还是组成自Sprite同时用SpriteBatchNode渲染优化的问题

很多书,比如《Cocos2D-X游戏开发之旅》P38,
都会说到游戏实体类与Sprite(精灵类)应该尽量用组成的设计,而不是继承。
比如:一个敌人飞机类不是继承自Sprite,而是组成Sprite(包含一个Sprite对象作为自己飞机类的成员变量)
因为,从逻辑上来说,飞机不是精灵,它只是需要精灵来显示自身。
那么,组成是比较合理的设计。

但是,另一个方面,Cocos2D-X中的SpriteBatchNode只能添加Sprite及其自身的派生类对象。
这个限制,却让之前的组成设计变得麻烦。

举例一种情况:在一个有非常多敌人的游戏中,希望用到SpriteBatchNode进行批渲染优化,
由于SpriteBatchNode的限制,敌人最方便的设计就是继承自Sprite。
但这样做了,就会破坏良好的设计,之前也说了,敌人较好的设计是组成自Sprite
若决定牺牲良好的设计,选择继承Sprite,但有一种情况,却有点头疼了:
一个敌人不是由一个Sprite组成的,也许是多个Sprite 。这种情况,就只能用组成设计了,
用组成设计的话,又绕了回来:如果需要用SpriteBatchNode优化,怎么办?

现在,问题就变成了,对于拥有大量的敌人对象的类,需要用SpriteBatchNode优化,
同时,敌人类组成自Sprite。这个敌人类,怎么设计?

分享一下,我的做法:

class Enemy : public CCNode
{
public :
// 在初始化函数中,对 Sprite精灵进行初始化
bool init() ;

private :
// 表示敌人显示的精灵对象
CCSprite * m_pSpr1 ;
CCSprite * m_pSpr2 ;

public :
void SetPosition( const CCPoint& pt )
{
this->setPosition( pt ) ;

// 以下是设置精灵 m_pSpr1,m_pSpr2 的位置的代码
m_pSpr1->setPosition( pt ) ;
。。。 。。。

}

} ;

虽然,以上的Enemy敌人类,继承自Node。但它包含的Sprite对象却不能加入到自身的子节点中,
因为,它自身的Sprite 是用来加入到SpriteBatchNode中做优化的
自己写了一个SetPosition 设置敌人对象位置函数,为什么要写这个函数呢,
因为,组成自Sprite ,但Sprite又不是自身的子节点的话,
用CCNode::setPosition也只是移动Enemy敌人节点的位置而已,而表示它显示的Sprite却没有移动。
所以,自己写一个SetPosition 在内部“同步”更新Sprite的位置。

这个类,在敌人准备“上场”出现在舞台的时候,把它包含的所有Sprite都加入到SpriteBatchNode子节点中,
在敌人死亡,要“退场”时,把它包含的所有Sprite都从对应的SpriteBatchNode嬀/size]子节点中移除掉。

我这样做,是现实了实体与Sprite的组成设计,并且同时还用了SpriteBatchNode 做优化
但,感觉很麻烦,使用也不怎么方便,同时增加了代码的复杂性。

如果,SpriteBatchNode没有“只能添加Sprite及其自身的派生类对象”的限制,可以加入CCNode及其派生类的话,
就没那么麻烦了。

这个是我的做法,请问下,你们有什么好的设计方法么?
交流,讨论一下。:)

既然使用组合,封装SpriteBatchNode,就可以了

我就是写守护裙子的时候用的怪物比较多,就用了批处理,当时是直接在构造器里传入SpriteBatchNode对象的,不过有些地方处理起来还是有点小麻烦~
后来的游戏就放弃用批处理了,因为后来的游戏同时出现的怪物不多了,就没继续想更好的点子,嘿嘿