I have a memory problem that I have tracked down to be the main scene layer being chucked out of memory. If I comment out the “layer->retain()” below I get issues when I navigate away from this scene with “replace” and then want come back with from another scene with “replace” later on.
So should I retain here ? and if so how do I release it? If I drill into the code I can see that addChild adds layer to a standard STL vector which should retain it anyway unless something somewhere is clearing that vector.
Thanks.
Scene* GameScene::createScene() {
Scene* GameScene::createScene() {
// 'scene' is an autorelease object
auto scene = Scene::createWithPhysics();
// 'layer' is an autorelease object
auto layer = GameScene::create();
// Note: this needs a retain for some reason
layer->retain();
layer->setPhysicsWorld(scene->getPhysicsWorld());
scene->addChild(layer);
return scene;
}
Scene* GameScene::createScene() {
auto scene = Scene::createWithPhysics();
auto layer = GameScene::create();
layer->setPhysicsWorld(scene->getPhysicsWorld());
scene->addChild(layer);
return scene;
}
You don’t need to retain, layer in an autorelease object.
Except it’s not retaining the layer on re-entry layer, hence my question?
Does your scene extend cocos2d::Layer like this?:
class GameScene : public cocos2d::Layer {
public:
static cocos2d::Scene* createScene();
CREATE_FUNC(GameScene);
}
Yes, though I inherit from BaseScene so it looks like this:
class GameScene : public BaseScene
{
private:
typedef BaseScene inherited;
public:
static Scene* createScene();
...
CREATE_FUNC(GameScene)
};
class BaseScene : public Layer
{
private:
typedef Layer inherited;
public:
static Scene* createScene();
...
CREATE_FUNC(BaseScene)
};
All my scenes follow the same pattern, though I only see memory problems with the GameScene.
Must be something I don’t understand?
Ok so you want to make a base scene and then extend it? Let me show you how I did it.
In my case GameScene is a BaseScene, so don’t get confused
GameScene.h
class GameScene : public cocos2d::Layer
{
public:
~GameScene();
};
nothing explicitly needed in GameScene.cpp.
SafariScene.h:
class SafariScene : public GameScene
{
public:
static cocos2d::Scene* createScene();
CREATE_FUNC(SafariScene);
void initScene();
~SafariScene();
};
SafariScene.cpp:
Scene* SafariScene::createScene() {
auto scene = Scene::create();
auto layer = SafariScene::create();
layer->initScene();
scene->addChild(layer);
return scene;
}
void SafariScene::initScene(){
//this is a custom init called after main init so I can already can have some basic stuff created by GameScene
}
Then I simply create this scene like this:
scene = SafariScene::createScene();
Hope this helps.
Why you guys creating scene from layer, I think, more right way is to just inherit from cocos2d::Scene, and override create macros.
class SafariScene : public cocos2d::Scene
{
public:
CREATE_FUNC(SafariScene);
};
But in my project i have use another tip. Check out: I make function, which creating cocos objects with variadic arguments, which passes to constructor
/*
Create autorelease cocos object
@note T must be derived from cocos2d::Ref
@param args [optional] arguments that forwards to T constructor
@return autorelease object
*/
template<typename T, typename... Args>
inline T* make_autorelease( Args&&... args )noexcept {
static_assert( std::is_base_of<cocos2d::Ref, T>::value,
"T must be derived from cocos2d::Ref" );
auto pRet = new( std::nothrow ) T{ std::forward<Args>( args )... };
if ( pRet && pRet->init( ) ) {
pRet->autorelease( );
return pRet;
} else {
delete pRet;
pRet = nullptr;
return nullptr;
}
}
And create by this:
make_autorelease<LevelScene>( )
or
field_.addNode( *make_autorelease<Bomb>( *&field_,
2u,
currSquare )
i think, it’s more clear C++ way. Because, we don’t use macros at all!!!
Oh yes! I should inherit from Scene not layer! How did I miss that that’s probably the issue. Also not sure I understand variadic code being the new girl but I will give it a try! Thanks.
You don’t even need Layer now-a-days. It really doesn’t serve a lot of purpose.
Why ? I thought layer was light weight and a scene holds usually layers with other elements as children. I use them quite a bit to avoid having one big scene class.
Replace Layer with Node when you extend