- Creating Scene Classes
- Running And Repcaling Scenes
- More About Scene Methods
- The CREATE_FUNC() Helper
In this post we will write classes that inherit from cocos2d::Scene class, show some sprite images and switch themselves with each other every two seconds.
Creating Scene Classes
Lets make two similar scene classes and call them SceneA and SceneB. They inherit directly from cocos2d::Scene and will have one sprite object that shows an image (Logo.png and Menu.png for A and B). Every two seconds, they will replace themselves with the other one.
- Create a new project and delete the HelloWorldScene.h and HelloWorldScene.cpp from the project and your folder.
- Now first create SceneA.h and SceneA.cpp files and add them to your project.
#ifndef SceneA_h #define SceneA_h #include "cocos2d.h" #include "SceneB.h" class SceneA : public cocos2d::Scene { public: static cocos2d::Scene* createScene(); // Returns a Scene instance pointer virtual bool init(); // Initializes the class CREATE_FUNC(SceneA); // Makes a create() method // Returns a pointer to an instance of itself void nextScene(float delta); // Our scheduler to call the next scene }; #endif
The cpp file will be:
#include "SceneA.h" USING_NS_CC; Scene* SceneA::createScene() { return SceneA::create(); } bool SceneA::init() { if ( !Scene::init() ) { return false; } auto sprite = Sprite::create("Logo.png"); sprite->setPosition(512, 384); this->addChild(sprite); scheduleOnce(SEL_SCHEDULE(&SceneA::nextScene), 2); return true; } void SceneA::nextScene(float delta) { auto director = Director::getInstance(); auto scene = SceneB::createScene(); director->replaceScene(scene); }
- Inside the init() method, we check to see if the parent class doesn’t return an error. Then we create a sprite and attach it to the scene and activate the scheduler for every two seconds.
- Duplicate these two files that you just created for SceneA and rename them to SceneB.h and SceneB.cpp in your project. Inside the new files replace SceneA with SceneB and SceneB with SceneA.
Running And Repcaling Scenes
Remember I said the first scene always starts running with a call to runWithScene()? Good! Because that is how it starts.
runWithScene(); // Use to run the first scene
That is why you have these lines somewhere in the AppDelegate class:
auto director = Director::getInstance(); // Get the instance of the director auto scene = SceneA::createScene(); // Create your scene director->runWithScene(scene); // Call it to run only your FIRST scene. // Don't call it if there is already a running scene.
But after that, if you want to run a new scene, you should switch the running scene with a new one using replaceScene().
replaceScene(); // Use to replace the running scene with a new scene
That is why we have these lines in our scene classes:
auto director = Director::getInstance(); // Get the instance of the director auto scene = SceneB::createScene(); // Create your new scene director->replaceScene(scene); // Run to replace your scene with the new scene
- Now inside the AppDelegate.cpp replace:
auto scene = HelloWorld::createScene();
with:
auto scene = SceneA::createScene();
- Also, changed the designResolutionSize to 1024 x 768 too.
- Compile and run your project to see the Logo.png is displayed first and then after two seconds it gets replaced by Menu.png and this continues in a loop forever!
More About Scene Methods
replaceScene() is not the only method in the Director class that works on scenes. There are more:
// Director Class Methods runWithScene() // Call it to run only your FIRST scene. // Don't call it if there is already a running scene. replaceScene() // Replace the running scene with a new one pushScene(Scene* scene) // Suspends the execution of the running scene, pushing it on the stack of suspended scenes. popScene() // Pops out a scene from the stack. popToRootScene() // Pops out all scenes from the stack until the root scene in the queue. // This scene will replace the running one. Internally it will call popToSceneStackLevel(1). popToSceneStackLevel(int level) // Pops out all scenes from the stack until it reaches level. // If level is 0, it will end the director. If level is 1, it will pop all scenes until it reaches to root scene. // If level is <= than the current stack level, it won't do anything. getRunningScene() // Gets current running Scene. drawScene() // Draw the scene. This method is called every frame. Don't call it manually. // GLView Class Methods renderScene() // Renders a Scene with a Renderer This method is called directly by the Director. // Node Class Methods getScene() // Returns the Scene that contains the Node. setScene() // Set the scene,this method shall not be invoked manually.
Out of these, the pushScene() and popScene() are the most interesting ones. They work similar to the replaceScene() but instead of destroying and deleting the old scene, they just use a stack to push and pop the older scenes into and out of.
The rest are quite self explanatory I think!
The CREATE_FUNC() Helper
CREATE_FUNC() that you saw in the header file of the scene class is a predefined Cocos2d-x C++ directive that automates making a create() method for the class to reduce the code size and save you some time. You can have a look at its definition here:
#define CREATE_FUNC(__TYPE__) \ static __TYPE__* create() \ { \ __TYPE__ *pRet = new(std::nothrow) __TYPE__(); \ if (pRet && pRet->init()) \ { \ pRet->autorelease(); \ return pRet; \ } \ else \ { \ delete pRet; \ pRet = nullptr; \ return nullptr; \ } \ }
If you replace __Type__ with your class name and remove the #define line, you will see what it really is. A static member method that returns an instance of itself or nullptr if it fails. Nothing fancy!
static SceneA* create() { SceneA *pRet = new(std::nothrow) SceneA(); if (pRet && pRet->init()) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = nullptr; return nullptr; } }
You could just write this yourself and not bother with the CREATE_FUNC() at all.
Leave a Reply