Welcome reprinted: http://blog.csdn.net/fylz1125/article/details/8524081
The game logic is actually like shooting a movie. The whole process is driven by the Director.
One level in the game, one scenario is similar to that in movies. Each scene has some specific elements, such as Lin Chong's Temple of wind and snow. The big environment is a snowy night, a silver-clad defeated Mountain, and a defeated Mountain Temple, of course, there may also be some other elements, such as firelight, Wolf, light, crow, and yellow dog. This is a specific scenario. Then the director shouted, "Action !", Then all the plots will be shown here. The leading role and the supporting role are playing...
All the above elements constitute such a scenario, so how can we organize these elements in the game. Let's take a look at the cocos2d-x scene processing process.
The Director Execution Unit in cocos2d-x is scene ccscene. A scene has so many elements, such as a big background, and then some small elements, such as stars, fire heaps, and dogs, how can they be added to the scene.
In this case, a special container (actually a ccnode) can accommodate various nodes (by addchild ). Like a movie, there is a big environment first when the camera comes out. This is the main background layer (cclayer), right, It is the cclayer (how to translate better ). Then add some other elements in the main layer, such as characters, fireworks, wild dogs, and singing birds. These elements are independent objects (inherited from ccsprite). They all have their own attributes and behaviors. For example, a character is a man who walks aimlessly, the fire is burning and giving off a one-hop fire. The dogs are running, and the birds are flying. All these elements are added to the main layer, and then the main layer is added to the scene (ccscene). Finally, the Director executes the scene (pdirector-> runwithscene (pscene )), A picture is coming out.
Let's take a look at the code-level execution process:
Main Loop (read my previous article if you do not know)
Void ccdisplaylinkdirector: mainloop (void) {If (m_bpurgedirecotorinnextloop) {m_bpurgedirecotorinnextloop = false; purgedirector ();} else if (! M_binvalid) {drawscene (); // note that this is the scenario. // release the objects ccpoolmanager: sharedpoolmanager ()-> POP ();}}
Follow up with drawscene () to see how to draw it.
Void ccdirector: drawscene (void) {// calculate "Global" DT calculatedeltatime (); // tick before glclear: Issue #533 if (! M_bpaused) {m_pscheduler-> Update (m_fdeltatime); // schedule the UPDATE function by priority (each node has such a function)} glclear (gl_color_buffer_bit | gl_depth_buffer_bit ); /* 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 (m_pnextscene) // This variable is stored in the next plot scenario, this painting is the last set scenario {setnextscene (); // note this. Do not be misled by the name. It is actually set the scenario to run next time} kmglpushmatrix (); // draw the scene if (m_prunningscene) {m_prunningscene-> visit (); // check it out, this visit function is used to recursively draw subnodes} // draw the configurations node if (m_picationicationnode) {m_pnotificationnode-> visit ();} If (m_bdisplaystats) {showstats ();} kmglpopmatrix (); m_utotalframes ++; // swap buffers if (m_pobopenglview) {m_pobopenglview-> swapbuffers ();} If (m_bdisplaystats) {calculatempf ();}}
Well, look at the comments. There is a visit function, which is used to recursively draw subnodes.
Void ccnode: visit () {// quick return if not visible. children won't be drawn. If (! M_bvisible) {return;} kmglpushmatrix (); If (m_pgrid & m_pgrid-> isactive () {m_pgrid-> beforedraw ();} This-> transform (); ccnode * pnode = NULL; unsigned int I = 0; If (m_pchildren & m_pchildren-> count ()> 0) // start here, if there are subnodes, enter {sortallchildren (); // sort by zcoordinate, that is, sort the subnodes in Z order // draw children zorder <0 ccarray * arraydata = m_pchildren-> data; for (; I <arraydata-> num; I ++) // draw a subnode In the Z sequence <0 {pnode = (ccnode *) arraydata-> arr [I]; if (pnode & pnode-> m_nzorder <0) {pnode-> visit () ;}else {break ;}// self draw this-> draw (); // draw your own for (; I <arraydata-> num; I ++) {pnode = (ccnode *) arraydata-> arr [I]; If (pnode) {pnode-> visit () ;}} else {This-> draw (); // draw yourself without subnodes} // reset for next frame m_uorderofarrival = 0; if (m_pgrid & m_pgrid-> isactive () {m_pgrid-> afterdraw (this) ;} kmglpopmatrix ();}
This is a main loop, but where does it start to run a scenario, such
CCScene *pScene = HelloWorld::scene(); // run pDirector->runWithScene(pScene);
See, the first scenario starts from here and follows up.
Void ccdirector: runwithscene (ccscene * pscene) {ccassert (pscene! = NULL, "This command can only be used to start the ccdirector. there is already a scene present. "); ccassert (m_prunningscene = NULL," m_prunningscene shocould be null "); // The current run is null (first time) pushscene (pscene ); // What is push? startanimation (); // controls the frame rate and enters the main loop}
What is the pushscene function?
Void ccdirector: pushscene (ccscene * pscene) {ccassert (pscene, "the scene shocould not null"); m_bsendcleanuptoscene = false; m_pobscenesstack-> addobject (pscene ); // The current scene stack m_pnextscene = pscene; // next scene, that is, the next scene painting}
Now, pushscene does two things: the scene to be drawn is written into the stack, and the scenario to be drawn next time is set to pscene. After this function is returned
Startanimation (). This function adjusts the frame rate and then enters the main loop again.
Let's look back at the drawscene () function of the Main Loop (above), where there are segments:
If (m_pnextscene) // The pushscene function just set this value {setnextscene (); // send the next scene to m_prunningscene} kmglpushmatrix (); // draw the scene if (m_prunningscene) // start rendering the scene {m_prunningscene-> visit ();}
Looking at the code, it is actually an iteration process. For the first time, m_prunningscene is null, and then runwithscene is generated. m_prunningscene is the scene you passed in, but it will be executed in the next loop. There are two processes: the runwithscene function and the replacescene function. Both of these functions will set the next scene and the scene to be run will be written into the stack. Next, enter the main loop. In the main loop, the scene to be run is detected every time. If yes, the rendering is executed. This is the process.
The director can only execute one scenario at a time. The execution not only involves plotting, but also actions, callbacks, and transitions. Each scenario is essentially a ccnode,
As mentioned above, ccnode has a very important member variable m_pchildren, which is a ccarray used to store the child nodes added to the node. Scene recursively renders its subnodes during rendering, which forms a rendering chain to ensure that all elements in the entire scenario are rendered.