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


    (转载请注明原文:http://blog.csdn.net/while0/article/details/25615685)


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


    在cocos2dx中,sprite作为精灵类是使用最为频繁的类,与其他类相比。如:Node, Layer或Scene。Sprite最大的不同是它包括一个纹理。通过OpenGL的渲染。在游戏中呈现出来。

    游戏中的主角。怪物,背景,或是精灵的血条等都是通过Sprite来实现的。


    在cocos2dx中,关于创建Sprite的类,依据输入參数的不同有下面几个工厂函数。

        static Sprite* create()
        static Sprite* create(const std::string& filename)
        static Sprite* create(const std::string& filename, const Rect& rect)
        static Sprite* createWithTexture(Texture2D *texture)
        static Sprite* createWithTexture(Texture2D *texture, const Rect& rect, bool rotated=false)
        static Sprite* createWithSpriteFrame(SpriteFrame *spriteFrame)
        static Sprite* createWithSpriteFrameName(const std::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 = new Sprite();
        if (sprite && sprite->initWithFile(filename))
        {
            sprite->autorelease();
            return sprite;
        }
        CC_SAFE_DELETE(sprite);
        return nullptr;

    我们重点关注第一句:

    Sprite *sprite = new Sprite();

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

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

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

    class MySprite : public Sprite
    {
        static MySprite * create(const char *pszFileName);
    }
    
    MySprite * MySprite ::create(const char *filename)
    {
        MySprite *sprite = new MySprite();
        if (sprite && sprite->initWithFile(filename)) 
        {
            sprite->autorelease(); return sprite; 
        }
        CC_SAFE_DELETE(sprite); 
        return nullptr;
    }
    


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

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


    假设输入參数不同。能够參考Sprite类的实现。创建不同输入參数的工厂函数。
    所以,依照眼下cocos2dx的设计,在Sprite的继承类中,必须又一次实现新类的工厂函数,在工厂函数中创建新类的实例。这样新类中重载的虚函数就会被调用到。


    使用C++编程,常常须要继承Sprite来定制和封装游戏特定的精灵。

    有时候可能须要在Sprite的基础上进行多次继承,来达到类重用的目的。
    本文以下提供两种方法,提供给读者參考。

    在这两种方法中,不须要在继承类中又一次实现工厂函数。




    1. 在工厂函数中,实例作为输入參数传入
    MySprite * MySprite ::create(Sprite* sprite, const char *filename)
    {
        if (sprite && sprite->initWithFile(filename))
        {
            sprite->autorelease();
            return sprite;
        }
        CC_SAFE_DELETE(sprite);
        return nullptr;
    }


    调用MySprite的代码:
    MySprite *sprite = new MySprite();
    MySprite::create(sprite, "hero.png");
    this->addChild(sprite);
    sprite->setPosition(Point(100, 200));


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

    比如:从MySprite继承新类MySprite2:
    class MySprite2 : public MySprite
    {
        ...
    }


    调用MySprite2的代码:
    MySprite2 *sprite = new MySprite2();
    MySprite::create(sprite, "hero.png");
    this->addChild(sprite);
    sprite->setPosition(Point(100, 200));


        2. 创建newInstance的虚函数

    另外一种方法,我们能够通过虚函数newInstance()来避免反复创建工厂函数。

    在newInstance中创建新类的对象。

    class MySprite : public Sprite
    {
        static MySprite * create(const char *filename);
        virtual Sprite* newInstance();
    }
    Sprite* MySprite::newInstance()
    {
        return new MySprite();
    }
    
    MySprite * MySprite ::create(const char *filename)
    {
        MySprite *sprite = newInstance();
        if (sprite && sprite->initWithFile(filename)) 
        {
            sprite->autorelease(); return sprite; 
        }
        CC_SAFE_DELETE(sprite); 
        return nullptr;
    }
    


    调用MySprite的代码:

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

    另外一种方法的优点是在使用MySprite时与Sprite的全然同样,但须要在继承类中实现虚函数newInstance()。

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

  • 相关阅读:
    二维码生成:使用 JavaScript 库QRCode.js生成二维码
    VC++6.0远程调试(亲试成功)
    Linux同时安装python2和Python3
    Python打包-py2exe
    camera按键采集图像及waitKey的用法(转)
    ucos实时操作系统学习笔记——任务间通信(信号量)(转)
    STM32硬件IIC驱动设计(转)
    基于STM32F4移植W5500官方驱动库ioLibrary_Driver(转)
    USB基础知识概论(版本:v0.9.2)
    usb帧格式
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5127157.html
Copyright © 2020-2023  润新知