Managing lots of scenes

Hello there!

I have a question. I have a flow of lets say 6-10 different scenes

And I want to automatise the flow, so I need something like a vector<IScene*> scenes;

And inside the vector I need to store the scenes that inherit from IScene and later when the replaceScene method is called I just pop() the scene from the vector.

First question:
Is this a good idea to solve this problem?

Second question:
Is it ok to create the scenes via createScene(); ? Wont it kill the performance?

for example at the beginning (probably in the appdelegate) I will have something like this:

auto scene1 = Scene1::createScene();
scenes.push_back(scene1);
auto scene2 = Scene2::createScene();
scenes.push_back(scene2);

etc.

What do You guys think about it?

10 scenes animated one after the other? I do not know what your goal is, but to me it seems a little weird. Anyway, the Director automatically stores all scenes inside a vector (Vector<Scene*> _scenesStack), so you do not need to store them in another vector. You could simply call runWithScene(Scene *scene) to add the first scene, and then add all the others via pushScene(Scene *scene), then call popScene(); until you are back to the first. Be careful because scenes as for now (cocos2d-x v3.9) can only be animated when pushed or replaced, but not when removed… I really think the best thing could do is trying to find a better solution.
Edit
I remembered there was a topic on the forum about animating popScene();. I do not know whether it works with v3.9, but here it is: Tip) implement popScene with Transition
End edit

Yes.

Worry about optimization only if you see that the game runs with an excessively low fps rate, or if it could help you make more money, otherwise it’s just a waste of time. For more, check out http://c2.com/cgi/wiki?PrematureOptimization

@cei

Yes, each of them with a different duration. For example: Scene1 (2min) -> Scene2 (5min) -> Scene3 -> (1min) -> Scene4 (7min)

I dont get this. Can You show me an example?
For Example with 3 scenes. Lets say I have those classes:

MyScene1 : public Layer
MyScene2 : public Layer
MyScene3 : public Layer

What do I need to do so that the Director knows that after scene1 comes scene2? In AppDelegate I have something like this:

auto scene1 = MyScene1::createScene();
director->runWithScene(scene1);

What about MyScene2, MyScene3, etc. ? I Create them also in appDelegate and pushBack somehow?

Another thing that I would like to know is why this:

Scene* scene = Scene::create();
auto layer = MyScene1::create();
scene->addChild(layer);
director->runWithScene(scene);

works, but this:

Scene* scene = Scene::create();
MyScene1* layer;
layer->create();
scene->addChild(layer);  <- HERE it breaks; 
director->runWithScene(scene);

does not work :frowning:

EDIT:
Ok, I got it with the popScene(); :stuck_out_tongue:
This might work for me if I get the transition to work :smiley:

However I’m still interested in the last part of my question about the > create() method :wink:

The Director stores all scenes in the same order as you push them by calling _scenesStack.pushBack(scene); (It’s pushBack and not push_back because Director uses cocos2d’s Vector, and not std’s). You can see precisely what happens if you check out the implementation of runWithScene(Scene *scene) and pushScene(Scene *scene).

Simply do

auto scene1 = MyScene1::create();
director->runWithScene(scene1);
scene1->release(); //The scene is retained a first time when calling create(); and a second time when Director adds it to _scenesStack. When calling popScene(); the scene is released once, and to ensure it is removed from the memory we need to release it a second time. It's done here just for simplicity. Be careful not to release the scene before pushing it, otherwise it will be deleted.
auto scene2 = MyScene2::create();
director->pushScene(scene2);
scene2->release; //Same as before
...
auto sceneN = MySceneN::create();
director->pushScene(sceneN);
sceneN->release;

This won’t work because create() returns a pointer to a Scene object, but you are not assigning it to your object layer. It breaks because when calling addChild(Node *child) you pass a pointer to an object which does not exist.

@cei
Thank You very much! :smiley: I will probably use the pushScene() solution :smile:

One more question… I’m using CocoStudio and to implement the Transition in popScene(); I need to change the Director.cpp file, Do you know where I can find it? Because somehow I don’t have the cocos classes in my project

You are welcome.

I do not use CocosStudio so I cannot help you. In theory a copy of the cocos2d framework should be inside your project’s folder, but I do not know how CocosStudio organizes the projects’ data… If you find it, the Director’s implementation is at cocos2d/cocos/base/CCDirector.cpp

create is a static function, which creates the Layer on the heap and returns it’s pointer, so the object exists whenn adding it to the scene.

The implementation of Layer::create() is the following:

Layer *Layer::create()
{
    Layer *ret = new (std::nothrow) Layer();
    if (ret && ret->init())
    {
        ret->autorelease();
        return ret;
    }
    else
    {
        CC_SAFE_DELETE(ret);
        return nullptr;
    }

In your code, layer is just a null pointer on which the static function create is called on, but the object does not exist. It’s types are still evaluated and the call is still valid.
It fails, because the pointer is still a null pointer, despite the static function was executed correctly.

scene->addChild(layer); fails, as the layer is not initialized properly.

You can read about this topic here: