当前位置:网站首页>Cos start source code and creator

Cos start source code and creator

2020-11-06 01:15:00 Weak scholar Chen Pi Pi

Preface

get set

I don't know if you ever thought about , If you compare the game world to a car , So this one “ automobile ” How to start , How does it work continuously ?

As the title , The main contents of this paper are as follows Cocos Creator Engine Start process and Main circulation .

And in the content of the main loop, there will be : The life cycle of components and timers 、 Retarder system 、 Animation system and physical system, etc ...

This paper will interpret the relationship between the main loop and each module from a macro perspective , For each module will also briefly introduce , But it will not go deep into the specific implementation of the module .

Because if you put every module “ feel ” Again , I'm afraid this article can't be finished .

Go!

I hope you can understand more after reading this article Cocos Creator engine .

At the same time, I hope this article can play a role in “ Master leads in ” The role of , Let's cheer up and practice duck together ~

in addition 《 Source code interpretation 》 series ( should ) It will be updated continuously , If you want a skin to read a module of the interpretation engine , Also welcome to leave a message to tell me , I ... I'll think about it. Ha ha ha ~

This article takes Cocos Creator 2.4.3 Version for reference .


Text

Start process

index.html

about Web platform index.html Documents are the absolute starting point .

In the default index.html In file , Defines the layout of the game launch page , And there's an immediate code to execute .

Here we intercept some of the more critical code in the file :

//  Load engine script 
loadScript(debug ? 'cocos2d-js.js' : 'cocos2d-js-min.ec334.js', function () {
    //  Is the physical system turned on ?
    if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
        //  Load the physical system script and start the engine 
        loadScript(debug ? 'physics.js' : 'physics-min.js', window.boot);
    } else {
        //  Start the engine 
        window.boot();
    }
});

The above code is mainly used to load engine scripts and physical system scripts , After the script is loaded, it will call main.js As defined in window.boot() function .

🧵 Code compression

Script file name with -min The typeface generally means that the code in the file is compressed .

Compressing code can save the space occupied by code files , Speed up file loading , Reduce traffic consumption , But it also makes the code unreadable , Not conducive to debugging .

Therefore, after the debugging mode is turned on, the uncompressed code file will be used directly , Easy to develop, debug and locate errors .

main.js

window.boot()

For different platforms main.js There are also some differences , Here we ignore the difference part , Focus only on the key common behaviors .

About main.js The content of the document basically defines window.boot() function .

For non Web platform , It will be called directly after the definition window.boot() function , therefore main.js That's where they start .

and window.boot() There are the following key behaviors inside the function :

  1. Definition onStart Callback function : It is mainly used to load startup scenarios
  2. cc.assetManager.init(...): initialization AssetManager
  3. cc.assetManager.loadScript(...): load src Plug in script directory
  4. cc.assetManager.loadBundle(...): Load the bundle
  5. cc.game.run(...): Start the engine

This part of the code will not be posted , Partners can look at their own projects after the construction of main.js file .

cc.game

cc.game The object is cc.Game An instance of a class ,cc.game Contains the main body information of the game and is responsible for driving the game .

Say something reasonable. ,cc.game Objects are the modules that manage the life cycle of an engine , start-up 、 It's needed for pauses and restarts .

CCGame.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/CCGame.js

run()

cc.game.run() The engine configuration and onStart Call back and trigger cc.game.prepare() function .

run: function (config, onStart) {
    //  Specify engine configuration 
    this._initConfig(config);
    this.onStart = onStart;
    this.prepare(game.onStart && game.onStart.bind(game));
}

Portal :https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/CCGame.js#L491

prepare()

cc.game.prepare() Function is used to quickly compile project code and call _prepareFinished() function .

prepare(cb) {
    //  Skip if ready 
    if (this._prepared) {
        if (cb) cb();
        return;
    }
    //  Load preview project code 
    this._loadPreviewScript(() => {
        this._prepareFinished(cb);
    });
}

Portal :https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/CCGame.js#L472

For the details of quick compilation , You can open the browser's developer tool during project preview , stay Sources In the search bar (Ctrl + P) __quick_compile_project__ You can find it __quick_compile_project__.js file .

_prepareFinished()

cc.game._prepareFinished() The function is mainly used to initialize the engine 、 Set the frame rate timer and initialize the built-in resources (effect Resources and material resources ).

Called when the built-in resource is loaded cc.game._runMainLoop() Start the engine main cycle .

_prepareFinished(cb) {
    //  Initialize engine 
    this._initEngine();
    //  Set frame rate timer 
    this._setAnimFrame();
    //  Initialize built in resources ( Load built-in  effect  and  material  resources )
    cc.assetManager.builtins.init(() => {
        //  Print engine version to console 
        console.log('Cocos Creator v' + cc.ENGINE_VERSION);
        this._prepared = true;
        //  start-up  mainLoop
        this._runMainLoop();
        //  launch  ‘game_inited’  event ( That is, the engine has been initialized )
        this.emit(this.EVENT_GAME_INITED);
        //  call  main.js  As defined in  onStart  function 
        if (cb) cb();
    });
}

Portal :https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/CCGame.js#L387

about _prepareFinished() Internally called _setAnimFrame() Function here we have to mention .

_setAnimFrame()

cc.game._setAnimFrame() Internal to different game frame rate to do the adaptation .

It's also true window.requestAnimationFrame() The interface is packaged with compatibility , For compatibility with different browser environments , We'll talk about it later .

We don't post them here _setAnimFrame() The code of , If you need it, you can check it by yourself .

Portal :https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/CCGame.js#L564

_runMainLoop()

cc.game._runMainLoop() The name of this function is very simple and direct , It's a showdown. It's used to run mainLoop() Functional .

Let's look at the code :

_runMainLoop: function () {
    if (CC_EDITOR) return;
    if (!this._prepared) return;
    //  Defining local variables 
    var self = this, callback, config = self.config,
        director = cc.director,
        skip = true, frameRate = config.frameRate;
    //  Show or hide performance statistics 
    debug.setDisplayStats(config.showFPS);
    //  Set frame callback 
    callback = function (now) {
        if (!self._paused) {
            //  Loop call callback 
            self._intervalId = window.requestAnimFrame(callback);
            if (!CC_JSB && !CC_RUNTIME && frameRate === 30) {
                if (skip = !skip) return;
            }
            //  call  mainLoop
            director.mainLoop(now);
        }
    };
    //  The loop callback will start at the next frame 
    self._intervalId = window.requestAnimFrame(callback);
    self._paused = false;
}

Portal :https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/CCGame.js#L612

Through the above code, we can know that ,_runMainLoop() Mainly through window.requestAnimFrame() Interface to implement the loop call mainLoop() function .

window.requestAnimFrame()

window.requestAnimFrame() That's what we said _setAnimFrame() Internal to window.requestAnimationFrame() Compatibility encapsulation of .

Small partners who are not familiar with the front end may have questions ,window.requestAnimationFrame() What is it , What is it for , How does it work ?

window.requestAnimationFrame()

Simply speaking ,window.requestAnimationFrame() Used to request a redraw from the browser (repaint), And calls the specified callback function before repainting .

window.requestAnimationFrame() Receives a callback as a parameter and returns an integer as a unique identifier , The browser will execute this callback before the next redraw ; And a parameter will be passed in when the callback is executed , The value of the parameter and performance.now() The values returned are equal .

performance.now() The return value of the browser window can be simply interpreted as the running time of the browser window , That is, the time difference between opening the window and the current time .

MDN file :https://developer.mozilla.org/zh-CN/docs/Web/API/Performance/now

The number of times the callback function is executed usually matches the number of browser screen refreshes , in other words , For refresh rate of 60Hz Display for , The browser will execute in a second 60 Sub callback function .

about window.requestAnimationFrame() That's all , If you want to know more, please search by yourself .

MDN file :https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame

Summary

Draw a picture to make a small summary of the engine starting process ~

Main circulation

After some twists and turns , Finally came to the most anticipated part of the main engine cycle , Don't talk much , We continue !

cc.director

cc.director The object is the director class cc.Director Example , Engine pass cc.director Object to manage the logical flow of the game .

CCDirector.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/CCDirector.js

mainLoop()

cc.director.mainLoop() Function is probably one of the most critical logic in the engine , It contains a lot of content and it's critical .

Now let's go in mainLoop() Let's look inside the function !

Here I selectively exclude some of the code in the function , I made some notes :

mainLoop: function(now) {
    //  Calculation “ overall situation ” Incremental time (DeltaTime)
    //  That is, from the last call  mainLoop  Time interval of 
    this.calculateDeltaTime(now);
    //  The game will be updated if it is not suspended 
    if (!this._paused) {
        //  launch  'director_before_update'  event 
        this.emit(cc.Director.EVENT_BEFORE_UPDATE);
        //  Call the new component ( Enabled ) Of  start  function 
        this._compScheduler.startPhase();
        //  Call all components ( Enabled ) Of  update  function 
        this._compScheduler.updatePhase(this._deltaTime);
        //  Update scheduler (cc.Scheduler)
        this._scheduler.update(this._deltaTime);
        //  Call all components ( Enabled ) Of  lateUpdate  function 
        this._compScheduler.lateUpdatePhase(this._deltaTime);
        //  launch  'director_after_update'  event 
        this.emit(cc.Director.EVENT_AFTER_UPDATE);
        //  Destroy recently removed entities ( node )
        Obj._deferredDestroy();
    }
    //  launch  'director_before_draw'  event 
    this.emit(cc.Director.EVENT_BEFORE_DRAW);
    //  Rendering game scene 
    renderer.render(this._scene, this._deltaTime);
    //  launch  'director_after_draw'  event 
    this.emit(cc.Director.EVENT_AFTER_DRAW);
    //  Update event manager event monitoring (cc.eventManager  It has been abandoned )
    eventManager.frameUpdateListeners();
    //  Add up the total number of frames the game runs 
    this._totalFrames++;
}

Portal :https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/CCDirector.js#L843

Next, let's decompose the key points in the main loop one by one .

ComponentScheduler

cc.director Object _compScheduler attribute yes ComponentScheduler Class .

Most of the partners may be interested in ComponentScheduler This class has no impression , Let me explain briefly .

take ComponentScheduler That's the literal translation of the name “ Component scheduler ”, You can see from the name that , This class is used to schedule components .

Say something reasonable. ,ComponentScheduler Class is used for centralized scheduling. ( management ) All components in the game scene (cc.Component) Life cycle of .

The text is not intuitive enough , After reading the following picture, you will understand :

component-scheduler.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/component-scheduler.js

startPhase

//  Call the new component ( Enabled ) Of  start  function 
this._compScheduler.startPhase();

Component's start The callback function will be before the component is activated for the first time , That's the first execution update Trigger before .

In the lifetime of components start The callback will only be triggered once ,onLoad and onEnable It's the same thing .

It's just onLoad and onEnable By NodeActivator Class :

  • onLoad Will trigger when the node is active
  • onEnable Will trigger when the component is enabled

and start It will wait until the next main loop mainLoop() Only when the .

NodeActivator

NodeActivator Class is mainly used to enable and disable nodes and their components .

cc.director There is an instance in the object _nodeActivator, All nodes in the game need to be enabled and disabled through it .

like this :cc.director._nodeActivator.activateNode(this, value);

node-activator.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/node-activator.js

updatePhase

//  Call all components ( Enabled ) Of  update  function 
this._compScheduler.updatePhase(deltaTime);

Component's update The function is triggered once per frame .

lateUpdatePhase

//  Call all components ( Enabled ) Of  lateUpdate  function 
this._compScheduler.lateUpdatePhase(deltaTime);

Component's lateUpdate The function will be in the update And scheduler cc.Scheduler Triggered after update . The scheduler updates include jogging 、 Animation and physics, etc , This will unfold below .

ParticleSystem

BTW, Particle system components (cc.ParticleSystem) Is in the lateUpdate Callback function to update .

CCParticleSystem.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/particle/CCParticleSystem.js#L923

Tips

Please use with caution update and lateUpdate Callback , Because they're triggered every frame , If update or lateUpdate Too much logic in , It will make the execution time of each frame ( That is frame time Frame time) All grow longer , Cause the game running frame number to reduce or appear unstable situation .

Notice that it's not that you're not allowed to use it , Should we use it or not , Just don't abuse it , Don't race everything inside ~

Scheduler

cc.director Object's _scheduler The attribute is cc.Scheduler Class .

cc.Scheduler Is the class responsible for triggering callback functions .

Scheduler.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/Scheduler.js

You can't guess what happens when the next line of seemingly flat code is executed .

//  Update scheduler (cc.Scheduler  Class instance )
this._scheduler.update(this._deltaTime);

cc.director.mainLoop() Use in _scheduler.update() Function to distribute update, In scheduler (cc.director._scheduler) The internal system will trigger the timer update of each system module and component according to the priority .

System module

The scheduler update will trigger the following system module updates first :

  • ActionManager
  • AnimationManager
  • CollisionManager
  • PhysicsManager
  • Physics3DManager
  • InputManager

All the above modules are based on cc.director._scheduler.scheduleUpdate() To register to the scheduler , Because these modules need to be updated every frame .

except InputManager The priority of other modules is cc.Scheduler.PRIORITY_SYSTEM, That is, system priority , Will be triggered first .

ActionManager

ActionManager namely Action manager , Used to manage all actions in the game , It's a slow motion system Action and Tween( In fact, they are essentially the same thing ).

CCActionManager.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/actions/CCActionManager.js

AnimationManager

AnimationManager namely Animation Manager , Used to manage all animations in the game , On the drive node Animation Component play animation .

animation-manager.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/animation/animation-manager.js

CollisionManager

CollisionManager namely Collision component manager , It is used to deal with the collision between nodes and whether the components have caused collision , And call the corresponding callback function .

CCCollisionManager.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/collider/CCCollisionManager.js

PhysicsManager

PhysicsManager namely Physical system manager , Inside with Box2D As 2D Physical engine , Encapsulate and open some common interfaces . meanwhile PhysicsManager Also responsible for managing the distribution of collision information .

CCPhysicsManager.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/physics/CCPhysicsManager.js

Physics3DManager

Physics3DManager namely 3D Physical system manager ,Cocos Creator Medium 3D The physics engine has Cannon.js and Builtin Optional ,Physics3DManager Encapsulate them with a unified common interface .

physics-manager.ts:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/3d/physics/framework/physics-manager.ts

InputManager

InputManager namely Input event manager , Used to manage all input events . Developers actively enable accelerometers (Accelerometer) after , The engine will pass at regular intervals InputManager send out cc.SystemEvent.EventType.DEVICEMOTION event ( The default interval is 0.2 second ).

CCInputManager.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d\core\platform\CCInputManager.js

Component timer

I believe that most of the partners have used components of schedule() and scheduleOnce() Interface , It is mainly used to execute functions repeatedly or regularly .

actually ,cc.Component Of schedule() The interface is also dependent cc.Scheduler class , It is also used specifically cc.director Object _scheduler example .

Component's schedule() Interface in cc.director._scheduler.schedule() A layer of encapsulation is added to the interface , Take the component itself as target, In this way, the timed tasks within the component are bound to the life cycle of the component , When a component is destroyed, the scheduled task is also removed .

and scheduleOnce() The interface is in the component schedule() The interface has a layer of encapsulation , Fixed will only be executed once after the specified time .

CCComponent.js:https://github.com/cocos-creator/engine/blob/2.4.3/cocos2d/core/components/CCComponent.js#L555

[ file ] Using timers :http://docs.cocos.com/creator/manual/zh/scripting/scheduler.html

I also noticed that , There are a lot of small partners are not very clear about the component timer and setTimeout()setInterval() The difference and usage of , Let's take this opportunity to talk about it briefly ~

setTimeout & setInterval

setTimeout() and setInterval() Both are created by the browser or Node.js This kind of runtime Interface provided .

  • setTimeout() Interface is used to set a timer , The timer executes a function or a specified piece of code after the timer expires .
  • setInterval() Interface is used to repeatedly call a function or execute a code segment , There is a fixed time delay between calls .

Add a little knowledge :

In the browser setTimeout() and setInterval() Minimum delay of ( interval ) yes 4ms.

If not activated ( backstage ) Tab for (tab), minimum delay ( interval ) It will be extended to 1000ms.

Take a chestnut

If I set a per in the current tab 500ms Output one log Timer for , When I switch to another tab , Then the timer becomes every 1000ms Only one output log.

like this , If you are interested, you can try it yourself :

setInterval(() => {
    console.log(new Date().getTime());
}, 500);
//  Analog output 
//  The tab is at the front desk 
// 1604373521000
// 1604373521500
// 1604373522000
//  After switching to another tab 
// 1604373523000
// 1604373524000
// 1604373525000
difference & usage

Component timers depend on the engine's mainLoop() And the component itself , If the engine is suspended , Then the timer of the component will also be suspended , If a component or its node is destroyed , Then the timer will fail .

setTimeout() and setInterval() Depends on where you are window object , That is to say, as long as the current browser tab is not closed ,setTimeout() and setInterval() Will still be implemented .

When you need to execute a function or operate a node regularly or repeatedly within a component , Then you can use the component timer .

Let's imagine a scene :

Use within a script in the current scenario setInterval() To repeatedly move a node in the scene , What happens when we switch scenes ?

When the timer calls the callback again to try to move the node , An error is reported when the target node cannot be found , Because the node has been destroyed along with the previous scene , And the timer goes on .

In this case, the timer using the component will not have this problem , Because the timer will be cleared with the destruction of the component .

And when we need to do something that has nothing to do with the game scene , You can consider using it setTimeout() or setInterval().

Of course, if you can use the component timer, you'd better use the component timer ~

Summary

Still draw a picture to sum up a little Scheduler.

summary

That's all about the engine's starting process and main loop .

If there are omissions or mistakes , You are also welcome to raise it , After all, it's excusable to stay up late and write articles in a trance, right ~

Last, last , Or draw a picture to make a final conclusion ~( Gradually fell in love with painting ~)


Portal

Wechat tweet version

Personal blog : Rookie Inn

Open source Homepage : Tangerine peel

Eazax-CCC Game development scaffolding

Eazax-CCC Sample online preview


Share more

《 Why choose to use TypeScript ?》

《 Gaussian blur Shader》

《 Read a text YAML》

《Cocos Creator performance optimization :DrawCall》

《 Internet operation terminology literacy 》

《 stay Cocos Creator It's a cool radar map 》

《 use Shader Write a perfect wave 》

《 stay Cocos Creator Manage pop ups gracefully and efficiently 》


official account

Rookie Inn

I'm tangerine peel , A game developer who is still learning , One who loves sharing Cocos Star Writer.

This is my personal official account. , Focus on but not limited to game development and front-end technology sharing .

Every original article is very attentive , Your attention is the driving force of my originality !

Input and output.

版权声明
本文为[Weak scholar Chen Pi Pi]所创,转载请带上原文链接,感谢