Cocos2d-X3.0 (9) ----- scene switching (transitionscene) Source Code Analysis

Source: Internet
Author: User

In the previous chapter, we analyze the source code of scene and layer-related classes, and have a preliminary understanding of the Cocos2d-x scenario. In this chapter, we will analyze the scene transform transitionscene source code.

Let's look at the definition of transitionscene.

class CC_DLL TransitionScene : public Scene{public:    /** Orientation Type used by some transitions     */    enum class Orientation    {        /// An horizontal orientation where the Left is nearer        LEFT_OVER = 0,        /// An horizontal orientation where the Right is nearer        RIGHT_OVER = 1,        /// A vertical orientation where the Up is nearer        UP_OVER = 0,        /// A vertical orientation where the Bottom is nearer        DOWN_OVER = 1,    };        /** creates a base transition with duration and incoming scene */    static TransitionScene * create(float t, Scene *scene);    /** called after the transition finishes */    void finish(void);    /** used by some transitions to hide the outer scene */    void hideOutShowIn(void);    //    // Overrides    //    virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;    virtual void onEnter() override;    virtual void onExit() override;    virtual void cleanup() override;    CC_CONSTRUCTOR_ACCESS:    TransitionScene();    virtual ~TransitionScene();    /** initializes a transition with duration and incoming scene */    bool initWithDuration(float t,Scene* scene);    protected:    virtual void sceneOrder();    void setNewScene(float dt);    Scene *_inScene;    Scene *_outScene;    float _duration;    bool _isInSceneOnTop;    bool _isSendCleanupToScene;private:    CC_DISALLOW_COPY_AND_ASSIGN(TransitionScene);};

This class is not big. We can see from the Class header information inheritance relationship that the scenario switching class is actually also a scenario.

The old rule is to analyze the member variables first.

The transitionscene class has five member variables. These five variables are almost identical in terms of variable naming.

SCENE * _ inscene; // The scenario pointer SCENE * _ outscene for scenario switching; // The scenario pointer float _ duration for scenario switching; // time consumed by scenario switching bool _ isinsceneontop; // scenario switching describes the rendering hierarchy between the cut-in scenario and the cut-out scenario. true: the cut-in scenario specifies the top-layer bool _ issendcleanuptoscene of the cut-out scenario; // indicates whether the clear command has been sent to the switch-out scenario.

Here, we can guess what kind of process the transitionscene class uses to implement scenario switching,

Transitionscene is an intermediary scenario. It holds the scene (_ inscene) on the left and the scene (_ outscene) on the right ), let these two scenes complete the process of switching to the scene in a gorgeous way on your own, and finally exit the intermediary scenario and hand over the stage to the new scene.

We have pushed the principle of implementing scenario switching in transitionscene. We are curious about the detailed process of implementing the scenario and scenario switching in the transitionscene class? Is the Failover principle correct?

Let's continue to look at the source code to find the answer.

We start with the creation method of transitionscene.

The constructor of transitionscene is an empty function ignored. Let's take a look at the static method transitionscene: Create to start analysis.

TransitionScene * TransitionScene::create(float t, Scene *scene){    TransitionScene * pScene = new TransitionScene();    if(pScene && pScene->initWithDuration(t,scene))    {        pScene->autorelease();        return pScene;    }    CC_SAFE_DELETE(pScene);    return nullptr;}

See the structure of the create function familiar can no longer be familiar with, in the basic year of Cocos2d-x node class and subclass creation is this structure.

Next, let's take a look at the initwithduration initialization method.

bool TransitionScene::initWithDuration(float t, Scene *scene){    CCASSERT( scene != nullptr, "Argument scene must be non-nil");    if (Scene::init())     {        _duration = t;        // retain        _inScene = scene;        _inScene->retain();        _outScene = Director::getInstance()->getRunningScene();        if (_outScene == nullptr)        {            _outScene = Scene::create();        }        _outScene->retain();        CCASSERT( _inScene != _outScene, "Incoming scene must be different from the outgoing scene" );                sceneOrder();        return true;    }    else    {        return false;    }}

It can be inferred from the number of arguments of this function that the initialization function is used to initialize a scenario switching mediation scenario (transitionscene) by specifying the scenario switching duration and the scenario pointer to be switched).

Initial process of transitionscene instance

  1. Call the scene Initialization Method of the base class. Scene: init
  2. Assign a value to the number of passed duration values _ duration = T;
  3. Cut-in scenario assignment _ inscene = scene; note that a reference to the cut-in scenario is added here. Because a cut-in scenario is referenced in the mediation scenario, a reference count is added.
  4. The output scenario value indicates that the current director class is being executed by Director: getinstance ()-> getrunningscene (); we can get another inference from the current execution scenario assigned to _ outscene. If no execution scenario is in progress, an empty scenario will be created as the output scenario, in addition, a pair is added to the reference count of the scene.
  5. After the sceneorder () function is called, the name of this function indicates that the scenario is sorted once. What have you done in detail? The following is an analysis of sceneorder.
void TransitionScene::sceneOrder(){    _isInSceneOnTop = true;}

Sceneorder: This is a virtual function. The process is very easy. It only sets the _ isinsceneontop mark to specify the hierarchy between the scene and the scene to be cut, that is, who is who.

We have analyzed the creation of transitionscene instances. The following describes how to implement the scenario switching process.

Take a look at the transitionscene Class header file and find the following functions.

    virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;    virtual void onEnter() override;    virtual void onExit() override;    virtual void cleanup() override;

The functions of these four functions are initially analyzed in terms of naming.

Draw Rendering Method

Called when the onenter mediation scenario enters the stage

Called when the onexit mediation scenario exits the stage

Clearup cleanup scenario method.

Read onenter for one analysis

void TransitionScene::onEnter(){    Scene::onEnter();        // disable events while transitions    _eventDispatcher->setEnabled(false);        // outScene should not receive the onEnter callback    // only the onExitTransitionDidStart    _outScene->onExitTransitionDidStart();        _inScene->onEnter();}

Function Process Analysis:

  1. Call the onenter of the scene base class
  2. The event distributor is set to unavailable. Scene switching is an animation process in which events are not processed to avoid unexpected errors.
  3. Call the onexittransitiondidstart method of the cut-out scenario. Friends who have read the previous chapters should still be impressed. This method is defined in the node base class, and the function meaning is the callback method when the scenario changes. It is reasonable to call this method when the current scenario leaves when the intermediary scenario enters the stage.
  4. Finally, the onenter of the scenario is called. There is no problem at all. When the scenario is switched out, the scenario starts to enter the stage. This is the process in which the intermediary scenario is exchanged between the left and right hands.

 

Let's look at the onexit method again.

void TransitionScene::onExit(){    Scene::onExit();        // enable events while transitions    _eventDispatcher->setEnabled(true);    _outScene->onExit();    // _inScene should not receive the onEnter callback    // only the onEnterTransitionDidFinish    _inScene->onEnterTransitionDidFinish();}

Function Process Analysis:

  1. Call the onexit method of the base class scene.
  2. The availability of the event distributor is restored.
  3. Call the exit callback for the cut-out scenario
  4. Call the callback for the entry completion of the cut-in scenario.

We can compare the onenter and onexit methods.

Through analysis, we can understand the sequence of function calls from the scene to the stage. Here we will summarize it.

Enter the stage ----> exit the stage. (The stage can be understood as the area that can be displayed on the screen)

Onenter ---> onentertransitiondidfinish ---> onexittransitiondidstart (START and exit the stage) ---> onexit (Exit)

After learning about the sequence of function calls in the scenario, we can understand what the onexit and onenter functions in the mediation scenario do.

When an intermediary scenario enters the stage, it is precisely when the scenario begins to exit the stage and the scenario enters the stage.

The mediation scenario starts from the beginning, and enters the stage after the scenario is completed.

At this time, both the mediation scenario and the scene were taken off the stage, and there were cut-in scenarios left on the stage. Now the switching of the scenario has been completed.

Next, let's take a look at the other two virtual functions.

void TransitionScene::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated){    Scene::draw(renderer, transform, transformUpdated);    if( _isInSceneOnTop ) {        _outScene->visit(renderer, transform, transformUpdated);        _inScene->visit(renderer, transform, transformUpdated);    } else {        _inScene->visit(renderer, transform, transformUpdated);        _outScene->visit(renderer, transform, transformUpdated);    }}

The draw method has no difficulty, that is, based on _ isinsceneontop, the entries recorded here cut in two scene hierarchies for separate rendering.

void TransitionScene::cleanup(){    Scene::cleanup();    if( _isSendCleanupToScene )        _outScene->cleanup();}

The clearup method also calls other clearup methods and then clears the scene based on whether the _ issendcleanuptoscene mark has been cleared.

Next, let's take a look at the methods of transitionscene.

void TransitionScene::finish(){    // clean up    _inScene->setVisible(true);    _inScene->setPosition(Point(0,0));    _inScene->setScale(1.0f);    _inScene->setRotation(0.0f);    _inScene->setAdditionalTransform(nullptr);    _outScene->setVisible(false);    _outScene->setPosition(Point(0,0));    _outScene->setScale(1.0f);    _outScene->setRotation(0.0f);    _outScene->setAdditionalTransform(nullptr);    //[self schedule:@selector(setNewScene:) interval:0];    this->schedule(schedule_selector(TransitionScene::setNewScene), 0);}

This finish method is called when the scenario switch is complete.

The function process is also very easy. You can set the switch-in scenario to the display status. The switch-out scenario is not displayed, and the rotation, scaling, and position of the scenario are all restored to the initial state.

It is worth noting that the callback function is added to the timer transitionscene: setnewscene. The callback interval is 0, that is, it will be called at the next frame.

Let's take a look at what the setnewscene function is doing.

void TransitionScene::setNewScene(float dt){        CC_UNUSED_PARAM(dt);    this->unschedule(schedule_selector(TransitionScene::setNewScene));        // Before replacing, save the "send cleanup to scene"    Director *director = Director::getInstance();    _isSendCleanupToScene = director->isSendCleanupToScene();        director->replaceScene(_inScene);        // issue #267    _outScene->setVisible(true);}

This function has a number of shards but is not used. It may be reserved.

In this function, the director class is used to clear the scene tag, and the value is assigned to the _ issendcleanuptoscene variable.

Note this line of code Director-> replacescene (_ inscene );

We know that Director manages scenarios, and there is only one runningscene at the same time. This line of code actually gives the stage to the scenario we want to cut in through Director (_ inscene)

void TransitionScene::hideOutShowIn(){    _inScene->setVisible(true);    _outScene->setVisible(false);}

FunctionHideoutshowinHide and show cut-in scenes. There is nothing to say.

 

After the analysis, we have analyzed all the methods in the transitionscene class and may have some questions.

  1. We only analyzed the callbacks for some scenarios to cut into the stage and leave the stage, but did not see the switching process for those dynamic scenarios.
  2. How do intermediary scenarios enter the stage? How can I use an intermediary scenario for scenario switching?
  3. The finish function is not called, so it seems that the name is actually saved.

With questions, we continue to look for answers in the source code.

 

We can see that in the header file cctransition. H, apart from transitionscene, it also defines a lot of sub-classes of the transitionscene class. Below we will select a class for analysis.

/** @brief TransitionRotoZoom:Rotate and zoom out the outgoing scene, and then rotate and zoom in the incoming */class CC_DLL TransitionRotoZoom : public TransitionScene{public:    static TransitionRotoZoom* create(float t, Scene* scene);    //    // Overrides    //    virtual void onEnter() override;protected:    TransitionRotoZoom();    virtual ~TransitionRotoZoom();private:    CC_DISALLOW_COPY_AND_ASSIGN(TransitionRotoZoom);};

Let's take a look at this kind of gaze. The scene is scaled and rotated, and the scene is rotated and scaled.

The transitionrotozoom class inherits the transitionscene class and does not add any attributes and methods. Instead, the onenter method is overloaded. What changes are there in onenter?

Follow-up code:

void TransitionRotoZoom:: onEnter(){    TransitionScene::onEnter();    _inScene->setScale(0.001f);    _outScene->setScale(1.0f);    _inScene->setAnchorPoint(Point(0.5f, 0.5f));    _outScene->setAnchorPoint(Point(0.5f, 0.5f));    ActionInterval *rotozoom = (ActionInterval*)(Sequence::create    (        Spawn::create        (            ScaleBy::create(_duration/2, 0.001f),            RotateBy::create(_duration/2, 360 * 2),            nullptr        ),        DelayTime::create(_duration/2),        nullptr    ));    _outScene->runAction(rotozoom);    _inScene->runAction    (        Sequence::create        (            rotozoom->reverse(),            CallFunc::create(CC_CALLBACK_0(TransitionScene::finish,this)),            nullptr        )    );}

I saw the onenter implementation, which is so interesting. There are animations, latencies ....... Start analysis.

Onenter function process:

  1. Call the onenter of the base class to connect the onenter and onexit-related scenario process callback.
  2. Set the cut-in scene to 0.001 times the size of the cut-in scene to the original size.
  3. Place the point of the cut-in and cut-out scenario in the center of the scenario.
  4. Here is a new class actioninterval, which is named as an animation class. Here we set two change processes, one being scaling and the other being rotating. This action is performed in the switch-out scenario.
  5. The switch-in scenario reversed the previously defined action process rotozoom-> reverse ()
  6. A callback function callfunc: Create (cc_callback_0 (Transitionscene: Finish, This), haha, here we seeTransitionscene: FinishThis function can be fully understood here, And the completion method of the intermediate scene is called when the scene animation is played. As mentioned above, in the finish method, the replctor's replacescene method is used to add the scenario to the stage.

Note: actioninterval and other animation-related classes are used here. Here we only need to know the approximate functions of these animation classes. We will analyze the subsequent chapters one by one.

Ainemo wrote a demo to show you the procedure of switching the transitionrotozoom scenario.



Through the analysis of transitionrotozoom, a derived class of the transitionscene class, we understand the action process of the transitionscene class. The following is a summary:

  1. The transitionscene class is the base class for scenario switching, and the scenario effects of Cocos2d-x all inherit this class. However, this class has no effect in any switching scenario. It only provides several function interfaces, such as onenter onexit, and reloads these interface functions in the subclass to implement switching in a specific scenario.
  2. The transitionscene series class is the intermediary class of a scenario. In this class, onenter and onexit of the scenario are called one after another.
  3. Assume that you have customized the effect of scenario switching. Do not forget to callTransitionscene: FinishMethod.

Now the three questions above are basically answered.

Some readers may have questions.

Here, I will discuss the association between scenario switching and director class and engine.

First, let's talk about the usage of the transitionscene class.

See the following code.

    auto visibleSize = Director::getInstance()->getVisibleSize();    Scene *myScene = Scene::create();    Sprite * sp = Sprite::create("mv2.jpg");    sp->setPosition( visibleSize.width / 2, visibleSize.height / 2 );    myScene->addChild( sp );    TransitionRotoZoom *tranScene = TransitionRotoZoom::create( 2.0, myScene );    Director::getInstance()->replaceScene( tranScene );

This example shows the code snippet of the GIF image above. It mainly uses a change like transitionrotozoom.

The first five lines of code are very easy, that is, I created a new scenario called scenario 2. I put an image on scenario 2.

In the sixth line of code, I created a transitionrotozoom scenario to switch the object instance, set the switching time to 2 seconds, and pass scenario 2 as the cut-out scenario.

Line 7: Find the Director Instance Object and use scenario 2 to replace the current scenario.

The above results are achieved with these lines of code.

In a word, the intermediate scenario of scenario change is added to the stage during scenario switching. We have analyzed the mediation scenario above. At the end, we will actually replace the scenario into the stage.

 

For better understanding, the above example code is used to analyze the code of some function related to director.

Let's first look at what replacescene has done.

Void Director: replacescene (SCENE * scene) // The input scene is our mediation scenario myscene {ccassert (_ runningscene, "Use runwithscene: instead to start the Director "); ccassert (scene! = Nullptr, "the scene shocould not be null"); If (_ nextscene) // assume that the next scene to be split has been specified. In this case, release the next scene. {If (_ nextscene-> isrunning () {_ nextscene-> onexittransitiondidstart (); _ nextscene-> onexit () ;}_ nextscene-> cleanup (); _ nextscene = nullptr;} // put myscene to the top of the scene stack, and change _ nextscene to myscene ssize_t Index = _ scenesstack. size (); _ sendcleanuptoscene = true; _ scenesstack. replace (index-1, Scene); _ nextscene = scene;} // After the function is completed, _ nextscene in ctor Ctor is our myscene. In the main loop of each director frame, let's look for the processing of _ nextscene.

Let's go back to mainctor's mainloop.

Void displaylinkdirector: mainloop () {If (_ purgedirectorinnextloop) {_ purgedirectorinnextloop = false; purgedirector ();} else if (! _ Invalid) {drawscene (); // you do not need to check the other items. We will follow up with drawscene to find the processing method for _ nextscene. // Release the objects poolmanager: getinstance ()-> getcurrentpool ()-> clear ();}}

The following is the code snippet of drawscene.

Void Director: drawscene (){............ // Omitted above
/* To avoid Flickr, nextscene must be here: After tick and before draw. XXX: Which bug is this one. it seems that it can't be reproduced with v0.9 */If (_ nextscene) // There are _ nextscene processing in drawscene, in this case, _ nextscene is the myscene {setnextscene ();} kmglpushmatrix ();
............ // Omitted below}

Follow up the setnextscene method.

Void Director: setnextscene () {// note the following two conversions, in this case, _ runningscene is a common scene in scenario 1. Therefore, when performing dynamic_cast conversion, It is null bool runningistransition = dynamic_cast <transitionscene *> (_ runningscene )! = Nullptr; // here runningistransition = false bool newistransition = dynamic_cast <transitionscene *> (_ nextscene )! = Nullptr; // here newistransition = true // if it is not a transition, call onexit/cleanup if (! Newistransition) // because _ nextscene is of the transiton type, this if inference will not walk in {If (_ runningscene) {_ runningscene-> onexittransitiondidstart (); _ runningscene-> onexit ();} // issue #709. the root node (scene) shocould receive the cleanup message too // otherwise it might be leaked. if (_ sendcleanuptoscene & _ runningscene) {_ runningscene-> cleanup () ;}} if (_ runningscene) // The reference count of _ runningscene is released here, because _ runningscene needs Replaced by _ nextscene {_ runningscene-> release ();} _ runningscene = _ nextscene; // _ nextscene adds a reference count _ nextscene-> retain (); _ nextscene = nullptr; If ((! Runningistransition) & _ runningscene) // This inference will enter, although the current _ runningscene is of the Transition type, we have not replaced _ nextscene when obtaining the runningistransition value. {_ Runningscene-> onenter (); // finally found. Here, the onenter of myscene in the mediation scenario is called, and then there is a series of rotation and scaling changes. This is the process of analyzing the transitionscene class. Wait until the finish method of myscene switches scenario 2 to the stage. _ Runningscene-> onentertransitiondidfinish ();}}

Well, today's content is basically the same.

Through the above analysis we have Cocos2d-x scene change is how to do. Here I just gave you an example, suppose you want to know more about the Cocos2d-x are prepared for us which changes in the scenario, it is best to make the cctransition. H class inside the demo have a try.

Today, we have encountered an action-related class in our analysis. Now we only know that it has something to do with animation changes. What are the things of the action series?

Well, let's get it done. In the next chapter, we will analyze the source code related to action.















Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.