制作完主菜单场景,紧接着就是要制作游戏场景GameView。游戏场景的创建和主菜单是一样的,其中的布景、UI都可以参照主菜单场景做出来,难度较低。
游戏中的主要元素,我们要操作的方块也可以看成一个Sprite。同时,明显的,方块我们可以把它抽象成一个类,他们的基本操作和性质都是一样的,只是在表现上有些不同(直线、田字块什么的)。
因此,这一次主要就是分享一下继承Sprite制作自定义Sprite类的方法。
其实像继承Layer或者Scene,这都很简单,但是如果不注意可能会在调试的时候断言错误,主要就是一个空指针异常。因此,这里,我主要分享一下如何避免继承时的简单错误以及发生该错误的原因。
废话不多说,继承Sprite主要关注create。先上一段代码:
BaseBlock * BaseBlock::create(const std::string & filename) { BaseBlock * sprite = new BaseBlock(); if (sprite && sprite->initWithFile(filename)) { sprite->autorelease(); return sprite; } CC_SAFE_DELETE(sprite); return nullptr; }
BaseBlock是我自定义的方块类,他继承自Sprite,create是Sprite类中的一个静态方法,用来创建Sprite。该函数返回Sprite*,但是我们需要的是创建BaseBlock,因此需要重写此方法。
当然,Sprite的create方法大概有5种。但不一定都用,因此可以用到哪个create方法就重写对应的方法。例如:
BaseBlock * BaseBlock::createWithTexture(cocos2d::Texture2D * texture) { BaseBlock * sprite = new BaseBlock(); if (sprite && sprite->initWithTexture(texture)) { sprite->autorelease(); return sprite; } CC_SAFE_DELETE(sprite); return nullptr; }
只要比照着写即可。
这里容易忽略的就是sprite->autorelease()。如果缺少他,便会在结束时报空指针异常。
原因其实也很容易想明白。
首先,我们重载这个create方法,返回的是一个以Sprite为基类的自定义类BaseBlock的指针。在C++中,指针操作需要非常注意。原则上,当有new操作申请指针时,一定要有delete操作与之对应,释放该指针。如果缺少delete就会形成野指针,关闭程序后导致内存泄露。
但是,delete在什么地方与new形成对应有时很难控制。程序短当然没什么,但如果程序够长,并且参与编程的人多,就很有可能在new和delete中间做了些什么操作,直接跳过了delete。因此,最好的解决方案就是智能指针,他可以自动释放自己。
而在cocos2dx中,应该也采用了类似的思想。他里面有一个全局的自析池(自己析构自己的池)。在创建Sprite的指针时,需要令其自动释放(autorelease),其实就是将其添加至自析池中。
同时,为了避免使用cocos2dx开发的开发人员不仔细,产生了像Sprite这个类的野指针,里面应该添加了断言。因此,如果Sprite缺少自析操作,断言会中断程序,报出类似空指针的异常。
附加一些cocos2dx中的这一部分的源码:
<pre name="code" class="cpp">Ref* Ref::autorelease() { PoolManager::getInstance()->getCurrentPool()->addObject(this); return this; }
PoolManager应该就是自析池管理器,是个单例模式。
PoolManager* PoolManager::getInstance() { if (s_singleInstance == nullptr) { s_singleInstance = new PoolManager(); // Add the first auto release pool new AutoreleasePool("cocos2d autorelease pool"); } return s_singleInstance; }
获取自析池单例。
PoolManager::PoolManager() { _releasePoolStack.reserve(10); } PoolManager::~PoolManager() { CCLOGINFO("deallocing PoolManager: %p",this); while (!_releasePoolStack.empty()) { AutoreleasePool* pool = _releasePoolStack.back(); delete pool; } }
创建自析池以及最终释放自析池中所有资源。
原文链接:https://www.f2er.com/cocos2dx/345865.html