Search code examples
c++cocos2d-x

Should I use CCArray to hold custom CCNode in cocos2d-x?


I have met a problem recently. I used vector STL a lot in cocos2d-x. And in one of my class I wrote:

vector<StrokeDrawnode*> strokedrawList;

StrokeDrawnode is inherited from CCNode. However, I read some article said that it is better to use CCArray to hold sub-class of CCObject. Actually, I have problem with the memory management. I guess it is the problem. So my question is what situation should I use CCArray and How can I deal with the memory management.

In what situation should I define the class member like this?

CC_SYNTHESIZE_RETAIN(CCSprite* , m_sprite_draw, Sprite);

Solution

  • The main difference between std::vector and CCArray in this case is that when you add objects to CCArray they get retained. This is really important in cocos, as CCObject-dervied (basically everything) objects get destroyed when their retainCount reaches 0. This is done automatically between every frame.

    Consider this example : Let's say you want to create 5 sprites and cache them for later use (they don't get to be on the screen until some time later in the future). Code (somewhere in the init() method):

    for(int i = 0; i < 5; ++i) {
    
       CCSprite *vectorSprite = (...);
       CCSprite *arraySprite = (...);
    
       _vector.push_back(vectorSprite);
       _array->addObject(arraySprite);
    
    }
    
    _array->retain(); // < ------- IMPORTANT!
    
    // end of init method 
    

    We of course assume that _vector and _array are instance variables and don't get destroyed when init() ends.

    What does happen before the next frame is drawn is that all sprites we put into the _vector will get destroyed - the vector will hold pointers to invalid memory locations.

    Objects we put in _array will not, because addObject retains them for us. Notice that the _array itself has to be retained as well, or it will be destroyed (I'm not sure about its contents).

    Generally, I think it may be better to use cocos-containers when working with cocos objects, as you only have to remember about retaining the container itself, and not all the objects. IF you really want to use std::vector it may be plausible to subclass std::vector so that its push_back and pop_back methods will retain and realese your objects respectively.


    As to the macro - I have never used it, but it expands to this :

    #define CC_SYNTHESIZE_RETAIN(varType, varName, funName)    \
    private: varType varName; \
    public: virtual varType get##funName(void) const { return varName; } \
    public: virtual void set##funName(varType var)   \
    { \
        if (varName != var) \
        { \
            CC_SAFE_RETAIN(var); \
            CC_SAFE_RELEASE(varName); \
            varName = var; \
        } \
    } 
    

    Which creates a setter and a getter for your variable for outside use. In my opinion it seems only viable if you want to expose a variable to outside use and have this methods provided for you automatically. The added value here is of course the retain - release process done in the setter.

    Let me know if anything is not clear! Cheers.