cocos2d-x 3.0 beta was recently released. one of the big new additions is the introduction of new container classes.
up until now, the cocos2d-x’s container classes were modelled after objective-c’s container classes (NSArray
, NSDictionary
, etc). now they are modelled after the standard c++ library’s containers (std::vector<T>
, std::map<T>
).
this post will show you a simple example of converting code from using the old CCArray
class to the new Vector
class.
consider this cocos2d-x v2.x code:
// HelloWorld.h
class HelloWorld : public cocos2d::CCLayer
{
// ...
cocos2d::CCArray *_bullets;
};
// HelloWorld.cpp
using namespace cocos2d;
bool HelloWorld::init()
{
if (!this->CCLayer::init())
return false;
// ...
// bullets
this->_bullets = CCArray::createWithCapacity(100);
this->_bullets->retain();
}
let’s review some things about the old CCArray
class:
- they can only contain
CCObject*
(i.e. pointers to CCObject). you have to cast its elements to a subclass if you’re storing a bunch ofCCSprite*
s, for example. - they are allocated on the heap using
CCArray::create()
, and follow cocos2d-x memory management rules (must beretain()
ed andrelease()
ed).
the new, 3.0 way might look like this:
// HelloWorld.h
class HelloWorld : public cocos2d::CCLayer
{
// other stuff...
cocos2d::Vector<cocos2d::Sprite *> _bullets;
};
// HelloWorld.cpp
using namespace cocos2d;
HelloWorld::HelloWorld() : _bullets(100)
{
}
things to note here:
cocos2d::Vector<T>
is a template class. the type it contains must be a pointer to a subclass ofcocos2d::Object
(in this example, we are usingcocos2d::Sprite *
— pointers toSprite
s)._bullets
, itself, is no longer a pointer. it’s a statically allocated object: nonew
orcreate
here. in general, the new container classes shouldn’t be allocated on the heap.- we’re initializing
_bullets
inHelloWorld
‘s constructor. if you wanted to initialize it in theinit()
method instead, you could use something like:this->_bullets = cocos2d::Vector<cocos2d::Sprite *>{100};
. again, note that there is nonew
orcreate
involved.
somewhere in some shooting code you might have something like this:
cocos2d-x v2.x:
// add a bullet
CCSprite *bullet = CCSprite::create("circle.png");
this->_bullets->addObject(bullet); // retains bullet
cocos2d-x v3.0 beta:
// add a bullet
Sprite *bullet = Sprite::create("circle.png")
this->_bullets.pushBack(bullet); // retains bullet
not much different here except for the name change (pushBack
is named similarly to the STL’s push_back
method), and the fact that you use “.
” instead of “->
” (because _bullets
is no longer a pointer).
removing an item:
v2.x:
this->_bullets->removeObject(bullet);
v3.0beta:
this->_bullets.eraseObject(bullet);
looping through the array:
v2.x:
// loop through bullets
CCObject *obj;
CCARRAY_FOREACH(this->_bullets, obj)
{
CCSprite *bullet = (CCSprite *)obj;
// do something with bullet.
if (bullet->getPositionX() > 160)
{
// ...
}
}
v3.0beta:
// loop through bullets
for (auto bullet: this->_bullets)
{
// do something with bullet.
// no need to cast in this case
if (bullet->getPositionX() > 160)
{
// ...
}
}
and finally, in your destructor, you’d want to clean up the array so as not to leak memory:
v2.x:
HelloWorld::~HelloWorld()
{
// release stuff
this->_bullets->release();
}
v3.0beta:
HelloWorld::~HelloWorld()
{
// nothing to do! _bullets manages its storage automatically when it falls out of scope
}
comments
comments powered by Disqus