关于在cocos2dx中继承Sprite的分析与技巧

本文章特指使用C++作为编程语言,基于cocos2dx游戏引擎开发游戏。

 

在cocos2dx中,sprite作为精灵类是使用最为频繁的类,与其它类相比,如:Node, Layer或Scene,Sprite最大的不同是它包含一个纹理,通过OpenGL的渲染,在游戏中呈现出来。游戏中的主角,怪物,背景,或是精灵的血条等都是通过Sprite来实现的。

 

在cocos2dx中,关于创建Sprite的类,根据输入参数的不同有以下几个工厂函数,

      
staticSprite* create()
staticSprite* create(conststd::string& filename)
staticSprite* create(conststd::string& filename, constRect& rect)
staticSprite* createWithTexture(Texture2D *texture)
staticSprite* createWithTexture(Texture2D *texture, constRect& rect, bool rotated=false)
staticSprite* createWithSpriteFrame(SpriteFrame *spriteFrame)
staticSprite* createWithSpriteFrameName(conststd::string& spriteFrameName)


顺便提醒,工厂函数中Sprite的实例都调用了autorelease(),所以由工厂函数返回的实例一般立即通过addChild到加入到父节点中,这样它的引用计数加一,表示有人在使用这个实例,这个实例不能被释放。当然,如果你不想立即加入到父节点中,也可以调用retain()函数直接对其引用计数加1,不然在主循环的下一次,就会将其回收,这是cocos2dx内存自动回收的机制决定的。

 

在游戏的开发过程中,使用Sprite最频繁的编码就是三部曲 (1)创建Sprite (2)加入layer中 (3)设置精灵位置:

Sprite *sprite = Sprite::create(hero.png);
this->addChild(sprite);
sprite->setPosition(Point(100,200));


第一行创建Sprite的实例,也就是创建了一个类Sprite的对象,这个是在工厂函数中实现的,
Sprite *sprite = newSprite();
if(sprite && sprite->initWithFile(filename))
{
    sprite->autorelease();
    returnsprite;
}
CC_SAFE_DELETE(sprite);
returnnullptr;

我们重点关注第一句:
Sprite *sprite = newSprite();



它决定了工厂函数创建的实例是Sprite类型,所以当在编码中调用Sprite的虚函数时,调用的就是Sprite类中的相应函数。

可能你会有这样一个问题:如果我想重载一个虚函数,在这个函数中实现自己需要的一些特殊行为,该怎么做?

答案是:必须继承Sprite创建一个你自己精灵类,在类中重载这个虚函数,这样还不够,必须定义这个新的继承类的工厂函数,在这个工厂函数中创建这个类的对象,

classMySprite : publicSprite
{
    staticMySprite * create(constchar *pszFileName);
}
 
MySprite * MySprite ::create(constchar *filename)
{
    MySprite *sprite = newMySprite();
    if(sprite && sprite->initWithFile(filename))
    {
        sprite->autorelease();returnsprite;
    }
    CC_SAFE_DELETE(sprite);
    returnnullptr;
}

在程序中使用MySprite的代码与Sprite类似,

MySprite *sprite = MySprite::create(hero.png);
this->addChild(sprite);
sprite->setPosition(Point(100,200));

如果输入参数不同,可以参考Sprite类的实现,创建不同输入参数的工厂函数。
所以,按照目前cocos2dx的设计,在Sprite的继承类中,必须重新实现新类的工厂函数,在工厂函数中创建新类的实例,这样新类中重载的虚函数就会被调用到。


使用C++编程,经常需要继承Sprite来定制和封装游戏特定的精灵。有时候可能需要在Sprite的基础上进行多次继承,来达到类重用的目的。
本文下面提供两种方法,提供给读者参考。在这两种方法中,不需要在继承类中重新实现工厂函数。


在工厂函数中,实例作为输入参数传入

MySprite * MySprite ::create(Sprite* sprite, constchar *filename)
{
    if(sprite && sprite->initWithFile(filename))
    {
        sprite->autorelease();
        returnsprite;
    }
    CC_SAFE_DELETE(sprite);
    returnnullptr;
}

调用MySprite的代码:

MySprite *sprite = newMySprite();
MySprite::create(sprite, hero.png);
this->addChild(sprite);
sprite->setPosition(Point(100,200));

在MySprite的基础上再做继承时,就不需要实现工厂函数了。


例如:从MySprite继承新类MySprite2:

classMySprite2 : publicMySprite
{
    ...
}

调用MySprite2的代码:

MySprite2 *sprite = newMySprite2();
MySprite::create(sprite, hero.png);
this->addChild(sprite);
sprite->setPosition(Point(100,200));

2. 创建newInstance的虚函数

第二种方法,我们可以通过虚函数newInstance()来避免重复创建工厂函数。在newInstance中创建新类的对象。

classMySprite : publicSprite
{
    staticMySprite * create(constchar *filename);
    virtual Sprite* newInstance();
}
Sprite* MySprite::newInstance()
{
    returnnew MySprite();
}
 
MySprite * MySprite ::create(constchar *filename)
{
    MySprite *sprite = newInstance();
    if(sprite && sprite->initWithFile(filename))
    {
        sprite->autorelease();returnsprite;
    }
    CC_SAFE_DELETE(sprite);
    returnnullptr;
}

调用MySprite的代码:

MySprite::create(hero.png);
this->addChild(sprite);
sprite->setPosition(Point(100,200));

第二种方法的好处是在使用MySprite时与Sprite的完全相同,但需要在继承类中实现虚函数newInstance()。

本文抛砖引玉,在您的实现过程中也许会有更好的方法,欢迎讨论,共同进步。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值