CocosCreator 源碼./core/CCGame詳解

/****************************************************************************


/* event-target 是一個事件類悼凑,事件對象 怎炊,基于觀察者模式的時間notify 分發(fā)*/

var EventTarget = require('./event/event-target');

/*CCAudioEngine 音效播放類茴丰,音效的播放 暫停 loop等 */

require('../audio/CCAudioEngine');

/* CCDebug 主要包括的 log warn error的封裝 */

const debug = require('./CCDebug');

/* render/index 主要

提供基礎(chǔ)渲染接口的渲染器對象哄尔,渲染層的基礎(chǔ)接口將逐步開放給用戶

包括drawcall 屬性等

?*/

const renderer = require('./renderer/index.js');

/* 圖集管理永高,最大圖集,碎圖管理朋截,最大尺寸等信息維護在這個類 */

const dynamicAtlasManager = require('../core/renderer/utils/dynamic-atlas/manager');

/**

?* @module cc

?*/

/**

?* !#en An object to boot the game.

?* !#zh 包含游戲主體信息并負責(zé)驅(qū)動游戲的游戲?qū)ο蟆?/p>

?* @class Game

?* @extends EventTarget

?*/

var game = {

? ? /**

? ? ?* !#en Event triggered when game hide to background.

? ? ?* Please note that this event is not 100% guaranteed to be fired on Web platform,

? ? ?* on native platforms, it corresponds to enter background event, os status bar or notification center may not trigger this event.

? ? ?* !#zh 游戲進入后臺時觸發(fā)的事件逾苫。

? ? ?* 請注意,在 WEB 平臺柬帕,這個事件不一定會 100% 觸發(fā)哟忍,這完全取決于瀏覽器的回調(diào)行為。

? ? ?* 在原生平臺陷寝,它對應(yīng)的是應(yīng)用被切換到后臺事件魁索,下拉菜單和上拉狀態(tài)欄等不一定會觸發(fā)這個事件,這取決于系統(tǒng)行為盼铁。

? ? ?* @property EVENT_HIDE

? ? ?* @type {String}

? ? ?* @example

? ? ?* cc.game.on(cc.game.EVENT_HIDE, function () {

? ? ?*? ? ?cc.audioEngine.pauseMusic();

? ? ?*? ? ?cc.audioEngine.pauseAllEffects();

? ? ?* });

? ? ?*/

? ? EVENT_HIDE: "game_on_hide",

? ? /**

? ? ?* !#en Event triggered when game back to foreground

? ? ?* Please note that this event is not 100% guaranteed to be fired on Web platform,

? ? ?* on native platforms, it corresponds to enter foreground event.

? ? ?* !#zh 游戲進入前臺運行時觸發(fā)的事件。

? ? ?* 請注意尝偎,在 WEB 平臺饶火,這個事件不一定會 100% 觸發(fā),這完全取決于瀏覽器的回調(diào)行為致扯。

? ? ?* 在原生平臺肤寝,它對應(yīng)的是應(yīng)用被切換到前臺事件。

? ? ?* @property EVENT_SHOW

? ? ?* @constant

? ? ?* @type {String}

? ? ?*/

? ? EVENT_SHOW: "game_on_show",

? ? /**

? ? ?* !#en Event triggered when game restart

? ? ?* !#zh 調(diào)用restart后抖僵,觸發(fā)事件鲤看。

? ? ?* @property EVENT_RESTART

? ? ?* @constant

? ? ?* @type {String}

? ? ?*/

? ? EVENT_RESTART: "game_on_restart",

? ? /**

? ? ?* Event triggered after game inited, at this point all engine objects and game scripts are loaded

? ? ?* @property EVENT_GAME_INITED

? ? ?* @constant

? ? ?* @type {String}

? ? ?*/

? ? EVENT_GAME_INITED: "game_inited",

? ? /**

? ? ?* Event triggered after engine inited, at this point you will be able to use all engine classes.?

? ? ?* It was defined as EVENT_RENDERER_INITED in cocos creator v1.x and renamed in v2.0

? ? ?* @property EVENT_ENGINE_INITED

? ? ?* @constant

? ? ?* @type {String}

? ? ?*/

? ? EVENT_ENGINE_INITED: "engine_inited",

? ? // deprecated

? ? EVENT_RENDERER_INITED: "engine_inited",

? ? /**

? ? ?* Web Canvas 2d API as renderer backend

? ? ?* @property RENDER_TYPE_CANVAS

? ? ?* @constant?

? ? ?* @type {Number}

? ? ?*/

? ? RENDER_TYPE_CANVAS: 0,/* 渲染類型為canvas */

? ? /**

? ? ?* WebGL API as renderer backend

? ? ?* @property RENDER_TYPE_WEBGL

? ? ?* @constant

? ? ?* @type {Number}

? ? ?*/

? ? RENDER_TYPE_WEBGL: 1,/* 渲染類型為webgl */

? ? /**

? ? ?* OpenGL API as renderer backend

? ? ?* @property RENDER_TYPE_OPENGL

? ? ?* @constant

? ? ?* @type {Number}

? ? ?*/

? ? RENDER_TYPE_OPENGL: 2,/* 渲染類型opengl */

? ? _persistRootNodes: {},/* 根節(jié)點容器,存儲預(yù)加載的node節(jié)點 */

? ? // states

? ? _paused: true,//whether the game is paused 游戲是否暫停了

? ? /* 【配置是否已經(jīng)加載完畢了耍群,這個配置在build后的main.js里面义桂,

? ? 包括渲染模式找筝、debug模式,showFPS,幀率frameRate

? ? groupList: settings.groupList, 分組

? ? collisionMatrix: settings.collisionMatrix,?

? ? 分組可進行碰撞的分組配對慷吊,在項目-項目設(shè)置里面的面板配置

? ? ? ? 】 */

? ? _configLoaded: false,//whether config loaded?

? ? /* 反序列化或?qū)嵗?*/

? ? _isCloning: false,? ? // deserializing or instantiating

? ? /* 引擎已經(jīng)初始化完畢袖裕,此時內(nèi)置的class都能調(diào)用,引擎配置[]都已經(jīng)載入 */

? ? _prepared: false, //whether the engine has prepared

? ? /* 渲染器已經(jīng)初始化 */

? ? _rendererInitialized: false,

? ? /* 渲染器溉瓶?急鳄?? */

? ? _renderContext: null,

? ? /* 主循環(huán)的interval時間間隔 */

? ? _intervalId: null,//interval target of main

? ? _lastTime: null,

? ? _frameTime: null,

? ? /**

? ? ?* !#en The outer frame of the game canvas, parent of game container.

? ? ?* !#zh 游戲畫布的外框堰酿,container 的父容器疾宏。

? ? ?* @property frame

? ? ?* @type {Object}

? ? ?*/

? ? frame: null,

? ? /**

? ? ?* !#en The container of game canvas.

? ? ?* !#zh 游戲畫布的容器。

? ? ?* @property container

? ? ?* @type {HTMLDivElement}

? ? ?*/

? ? container: null,

? ? /**

? ? ?* !#en The canvas of the game.

? ? ?* !#zh 游戲的畫布触创。

? ? ?* @property canvas

? ? ?* @type {HTMLCanvasElement}

? ? ?*/

? ? canvas: null,

? ? /**

? ? ?* !#en The renderer backend of the game.

? ? ?* !#zh 游戲的渲染器類型坎藐。

? ? ?* @property renderType

? ? ?* @type {Number}

? ? ?*/

? ? renderType: -1,

? ? /**

? ? ?* !#en

? ? ?* The current game configuration, including:<br/>

? ? ?* 1. debugMode<br/>

? ? ?*? ? ? "debugMode" possible values :<br/>

? ? ?*? ? ? 0 - No message will be printed.? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? 1 - cc.error, cc.assert, cc.warn, cc.log will print in console.? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? 2 - cc.error, cc.assert, cc.warn will print in console.? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? 3 - cc.error, cc.assert will print in console.? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<br/>

? ? ?*? ? ? 4 - cc.error, cc.assert, cc.warn, cc.log will print on canvas, available only on web.<br/>

? ? ?*? ? ? 5 - cc.error, cc.assert, cc.warn will print on canvas, available only on web.? ? ? ? <br/>

? ? ?*? ? ? 6 - cc.error, cc.assert will print on canvas, available only on web.? ? ? ? ? ? ? ? ?<br/>

? ? ?* 2. showFPS<br/>

? ? ?*? ? ? Left bottom corner fps information will show when "showFPS" equals true, otherwise it will be hide.<br/>

? ? ?* 3. exposeClassName<br/>

? ? ?*? ? ? Expose class name to chrome debug tools, the class intantiate performance is a little bit slower when exposed.<br/>

? ? ?* 4. frameRate<br/>

? ? ?*? ? ? "frameRate" set the wanted frame rate for your game, but the real fps depends on your game implementation and the running environment.<br/>

? ? ?* 5. id<br/>

? ? ?*? ? ? "gameCanvas" sets the id of your canvas element on the web page, it's useful only on web.<br/>

? ? ?* 6. renderMode<br/>

? ? ?*? ? ? "renderMode" sets the renderer type, only useful on web :<br/>

? ? ?*? ? ? 0 - Automatically chosen by engine<br/>

? ? ?*? ? ? 1 - Forced to use canvas renderer<br/>

? ? ?*? ? ? 2 - Forced to use WebGL renderer, but this will be ignored on mobile browsers<br/>

? ? ?*<br/>

? ? ?* Please DO NOT modify this object directly, it won't have any effect.<br/>

? ? ?* !#zh

? ? ?* 當(dāng)前的游戲配置,包括:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?* 1. debugMode(debug 模式嗅榕,但是在瀏覽器中這個選項會被忽略)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? "debugMode" 各種設(shè)置選項的意義顺饮。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<br/>

? ? ?*? ? ? ? ? 0 - 沒有消息被打印出來。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<br/>

? ? ?*? ? ? ? ? 1 - cc.error凌那,cc.assert兼雄,cc.warn,cc.log 將打印在 console 中帽蝶。? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? ? ? 2 - cc.error赦肋,cc.assert,cc.warn 將打印在 console 中励稳。? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? ? ? 3 - cc.error佃乘,cc.assert 將打印在 console 中。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<br/>

? ? ?*? ? ? ? ? 4 - cc.error驹尼,cc.assert趣避,cc.warn,cc.log 將打印在 canvas 中(僅適用于 web 端)新翎。 <br/>

? ? ?*? ? ? ? ? 5 - cc.error程帕,cc.assert,cc.warn 將打印在 canvas 中(僅適用于 web 端)地啰。? ? ? ? ?<br/>

? ? ?*? ? ? ? ? 6 - cc.error愁拭,cc.assert 將打印在 canvas 中(僅適用于 web 端)。? ? ? ? ? ? ? ? ? <br/>

? ? ?* 2. showFPS(顯示 FPS)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? 當(dāng) showFPS 為 true 的時候界面的左下角將顯示 fps 的信息亏吝,否則被隱藏岭埠。? ? ? ? ? ? ? <br/>

? ? ?* 3. exposeClassName? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<br/>

? ? ?*? ? ? 暴露類名讓 Chrome DevTools 可以識別,如果開啟會稍稍降低類的創(chuàng)建過程的性能,但對對象構(gòu)造沒有影響惜论。 <br/>

? ? ?* 4. frameRate (幀率)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? “frameRate” 設(shè)置想要的幀率你的游戲许赃,但真正的FPS取決于你的游戲?qū)崿F(xiàn)和運行環(huán)境。? ? ? <br/>

? ? ?* 5. id? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? "gameCanvas" Web 頁面上的 Canvas Element ID来涨,僅適用于 web 端图焰。? ? ? ? ? ? ? ? ? ? ? ? ?<br/>

? ? ?* 6. renderMode(渲染模式)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<br/>

? ? ?*? ? ? “renderMode” 設(shè)置渲染器類型,僅適用于 web 端:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <br/>

? ? ?*? ? ? ? ? 0 - 通過引擎自動選擇蹦掐。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<br/>

? ? ?*? ? ? ? ? 1 - 強制使用 canvas 渲染技羔。

? ? ?*? ? ? ? ? 2 - 強制使用 WebGL 渲染,但是在部分 Android 瀏覽器中這個選項會被忽略卧抗。? ? ?<br/>

? ? ?* <br/>

? ? ?* 注意:請不要直接修改這個對象藤滥,它不會有任何效果。

? ? ?* @property config

? ? ?* @type {Object}

? ? ?*/

? ? config: null,

? ? /**

? ? ?* !#en Callback when the scripts of engine have been load.

? ? ?* !#zh 當(dāng)引擎完成啟動后的回調(diào)函數(shù)社裆。

? ? ?* @method onStart

? ? ?* @type {Function}

? ? ?*/

? ? onStart: null,

? ? //@Public Methods

? ? //? @Game play control

? ? /**

? ? ?* !#en Set frame rate of game.

? ? ?* !#zh 設(shè)置游戲幀率拙绊。

? ? ?* @method setFrameRate

? ? ?* @param {Number} frameRate

? ? ?*/

? ? setFrameRate: function (frameRate) {

? ? ? ? var config = this.config;

? ? ? ? config.frameRate = frameRate;

? ? ? ? /*?

? ? ? ? window.cancelAnimFrame(this._intervalId);

? ? ? ? 取消一個先前通過調(diào)用window.requestAnimationFrame()方法添加到計劃中的動畫幀請求。

? ? ? ? ?*/

? ? ? ? if (this._intervalId)

? ? ? ? ? ? window.cancelAnimFrame(this._intervalId);

? ? ? ? this._intervalId = 0;

? ? ? ? /* 設(shè)置幀率泳秀,設(shè)置flag标沪,pause暫停為true */

? ? ? ? this._paused = true;

? ? ? ? this._setAnimFrame();

? ? ? ? this._runMainLoop();

? ? },

? ? /**

? ? ?* !#en Get frame rate set for the game, it doesn't represent the real frame rate.

? ? ?* !#zh 獲取設(shè)置的游戲幀率(不等同于實際幀率)。

? ? ?* @method getFrameRate

? ? ?* @return {Number} frame rate

? ? ?*/

? ? getFrameRate: function () {

? ? ? ? return this.config.frameRate;

? ? },

? ? /**

? ? ?* !#en Run the game frame by frame.

? ? ?* !#zh 執(zhí)行一幀游戲循環(huán)嗜傅。

? ? ?* @method step

? ? ?*/

? ? step: function () {

? ? ? ? cc.director.mainLoop();

? ? },

? ? /**

? ? ?* !#en Pause the game main loop. This will pause:

? ? ?* game logic execution, rendering process, event manager, background music and all audio effects.

? ? ?* This is different with cc.director.pause which only pause the game logic execution.

? ? ?* !#zh 暫停游戲主循環(huán)金句。包含:游戲邏輯,渲染吕嘀,事件處理违寞,背景音樂和所有音效。這點和只暫停游戲邏輯的 cc.director.pause 不同偶房。

? ? ?* @method pause

? ? ?*/

? ? pause: function () {

? ? ? ? /* 如果已經(jīng)pause趁曼,返回 */

? ? ? ? if (this._paused) return;

? ? ? ? /* 執(zhí)行pause,暫停 */

? ? ? ? this._paused = true;

? ? ? ? // Pause audio engine

? ? ? ? /* 暫停音頻 */

? ? ? ? if (cc.audioEngine) {

? ? ? ? ? ? cc.audioEngine._break();

? ? ? ? }

? ? ? ? // Pause main loop

? ? ? ? /* 暫停主循環(huán) */

? ? ? ? if (this._intervalId)

? ? ? ? ? ? window.cancelAnimFrame(this._intervalId);

? ? ? ? /* 重置indtervalId =0 */

? ? ? ? this._intervalId = 0;

? ? },

? ? /**

? ? ?* !#en Resume the game from pause. This will resume:

? ? ?* game logic execution, rendering process, event manager, background music and all audio effects.

? ? ?* !#zh 恢復(fù)游戲主循環(huán)棕洋。包含:游戲邏輯挡闰,渲染,事件處理掰盘,背景音樂和所有音效摄悯。

? ? ?* @method resume

? ? ?*/

? ? resume: function () {

? ? ? ? /* 已經(jīng)暫停,則return */

? ? ? ? if (!this._paused) return;

? ? ? ? /* 執(zhí)行resume庆杜,恢復(fù) */

? ? ? ? this._paused = false;

? ? ? ? // Resume audio engine

? ? ? ? /* 恢復(fù)音頻 */

? ? ? ? if (cc.audioEngine) {

? ? ? ? ? ? cc.audioEngine._restore();

? ? ? ? }


? ? ? ? cc.director._resetDeltaTime();

? ? ? ? // Resume main loop

? ? ? ? /* 恢復(fù)主循環(huán) */

? ? ? ? this._runMainLoop();

? ? },

? ? /**

? ? ?* !#en Check whether the game is paused.

? ? ?* !#zh 判斷游戲是否暫停。

? ? ?* @method isPaused

? ? ?* @return {Boolean}

? ? ?*/

? ? isPaused: function () {

? ? ? ? return this._paused;

? ? },

? ? /**

? ? ?* !#en Restart game.

? ? ?* !#zh 重新開始游戲

? ? ?* @method restart

? ? ?*/

? ? restart: function () {

? ? ? ? /* 渲染過程之后所觸發(fā)的事件碟摆。 */

? ? ? ? cc.director.once(cc.Director.EVENT_AFTER_DRAW, function () {

? ? ? ? ? ? /* 移除常駐節(jié)點 */

? ? ? ? ? ? for (var id in game._persistRootNodes) {

? ? ? ? ? ? ? ? game.removePersistRootNode(game._persistRootNodes[id]);

? ? ? ? ? ? }

? ? ? ? ? ? // Clear scene

? ? ? ? ? ? /* 清除場景 */

? ? ? ? ? ? cc.director.getScene().destroy();

? ? ? ? ? ? cc.Object._deferredDestroy();

? ? ? ? ? ? // Clean up audio

? ? ? ? ? ? /* 銷毀所有audio */

? ? ? ? ? ? if (cc.audioEngine) {

? ? ? ? ? ? ? ? cc.audioEngine.uncacheAll();

? ? ? ? ? ? }

? ? ? ? ? ? /* 導(dǎo)演重置 */

? ? ? ? ? ? cc.director.reset();

? ? ? ? ? ? /* 游戲暫停 */

? ? ? ? ? ? game.pause();

? ? ? ? ? ? /* 內(nèi)置資源init后回調(diào) */

? ? ? ? ? ? cc.assetManager.builtins.init(() => {

? ? ? ? ? ? ? ? /* 游戲開始 */

? ? ? ? ? ? ? ? game.onStart();

? ? ? ? ? ? ? ? /* notify通知 game重啟 */

? ? ? ? ? ? ? ? game.emit(game.EVENT_RESTART);

? ? ? ? ? ? });

? ? ? ? });

? ? },

? ? /**

? ? ?* !#en End game, it will close the game window

? ? ?* !#zh 退出游戲

? ? ?* @method end

? ? ?*/

? ? end: function () {

? ? ? ? /* 退出游戲 */

? ? ? ? close();

? ? },

? ? //? @Game loading

/* 初始化引擎 */

? ? _initEngine() {

? ? ? ? /* render加入已經(jīng)初始化 則不再重復(fù)初始化 */

? ? ? ? if (this._rendererInitialized) {

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? /* 初始化 容器 畫布等 */

? ? ? ? this._initRenderer();

? ? ? ? if (!CC_EDITOR) {

? ? ? ? ? ? this._initEvents();

? ? ? ? }

? ? ? ? this.emit(this.EVENT_ENGINE_INITED);

? ? },

? ? _loadPreviewScript(cb) {

? ? ? ? if (CC_PREVIEW && window.__quick_compile_project__) {

? ? ? ? ? ? window.__quick_compile_project__.load(cb);

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? cb();

? ? ? ? }

? ? },

? ? _prepareFinished(cb) {

? ? ? ? // Init engine

? ? ? ? this._initEngine();

? ? ? ? this._setAnimFrame();

? ? ? ? /* 引擎內(nèi)置資源初始化完畢后回調(diào) */

? ? ? ? cc.assetManager.builtins.init(() => {

? ? ? ? ? ? // Log engine version

? ? ? ? ? ? console.log('Cocos Creator v' + cc.ENGINE_VERSION);

? ? ? ? ? ? this._prepared = true;

? ? ? ? ? ? this._runMainLoop();

? ? ? ? ? ? /* 播放廣播事件晃财,觸發(fā)游戲初始化 */

? ? ? ? ? ? this.emit(this.EVENT_GAME_INITED);

? ? ? ? ? ? if (cb) cb();

? ? ? ? });

? ? },

? ? eventTargetOn: EventTarget.prototype.on,

? ? eventTargetOnce: EventTarget.prototype.once,

? ? /**

? ? ?* !#en

? ? ?* Register an callback of a specific event type on the game object.

? ? ?* This type of event should be triggered via `emit`.

? ? ?* !#zh

? ? ?* 注冊 game 的特定事件類型回調(diào)。這種類型的事件應(yīng)該被 `emit` 觸發(fā)。

? ? ?*

? ? ?* @method on

? ? ?* @param {String} type - A string representing the event type to listen for.

? ? ?* @param {Function} callback - The callback that will be invoked when the event is dispatched.

? ? ?*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? The callback is ignored if it is a duplicate (the callbacks are unique).

? ? ?* @param {any} [callback.arg1] arg1

? ? ?* @param {any} [callback.arg2] arg2

? ? ?* @param {any} [callback.arg3] arg3

? ? ?* @param {any} [callback.arg4] arg4

? ? ?* @param {any} [callback.arg5] arg5

? ? ?* @param {Object} [target] - The target (this object) to invoke the callback, can be null

? ? ?* @return {Function} - Just returns the incoming callback so you can save the anonymous function easier.

? ? ?* @typescript

? ? ?* on<T extends Function>(type: string, callback: T, target?: any, useCapture?: boolean): T

? ? ?*/

? ? on(type, callback, target, once) {

? ? ? ? // Make sure EVENT_ENGINE_INITED and EVENT_GAME_INITED callbacks to be invoked

? ? ? ? if ((this._prepared && type === this.EVENT_ENGINE_INITED) ||

? ? ? ? ? ? (!this._paused && type === this.EVENT_GAME_INITED)) {

? ? ? ? ? ? callback.call(target);

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? this.eventTargetOn(type, callback, target, once);

? ? ? ? }

? ? },

? ? /**

? ? ?* !#en

? ? ?* Register an callback of a specific event type on the game object,

? ? ?* the callback will remove itself after the first time it is triggered.

? ? ?* !#zh

? ? ?* 注冊 game 的特定事件類型回調(diào)断盛,回調(diào)會在第一時間被觸發(fā)后刪除自身罗洗。

? ? ?*

? ? ?* @method once

? ? ?* @param {String} type - A string representing the event type to listen for.

? ? ?* @param {Function} callback - The callback that will be invoked when the event is dispatched.

? ? ?*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? The callback is ignored if it is a duplicate (the callbacks are unique).

? ? ?* @param {any} [callback.arg1] arg1

? ? ?* @param {any} [callback.arg2] arg2

? ? ?* @param {any} [callback.arg3] arg3

? ? ?* @param {any} [callback.arg4] arg4

? ? ?* @param {any} [callback.arg5] arg5

? ? ?* @param {Object} [target] - The target (this object) to invoke the callback, can be null

? ? ?*/

? ? once(type, callback, target) {

? ? ? ? // Make sure EVENT_ENGINE_INITED and EVENT_GAME_INITED callbacks to be invoked

? ? ? ? if ((this._prepared && type === this.EVENT_ENGINE_INITED) ||

? ? ? ? ? ? (!this._paused && type === this.EVENT_GAME_INITED)) {

? ? ? ? ? ? callback.call(target);

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? this.eventTargetOnce(type, callback, target);

? ? ? ? }

? ? },

? ? /**

? ? ?* !#en Prepare game.

? ? ?* !#zh 準備引擎,請不要直接調(diào)用這個函數(shù)钢猛。

? ? ?* @param {Function} cb

? ? ?* @method prepare

? ? ?*/

? ? prepare(cb) {

? ? ? ? // Already prepared

? ? ? ? if (this._prepared) {

? ? ? ? ? ? if (cb) cb();

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? this._loadPreviewScript(() => {

? ? ? ? ? ? this._prepareFinished(cb);

? ? ? ? });

? ? },

? ? /**

? ? ?* !#en Run game with configuration object and onStart function.

? ? ?* !#zh 運行游戲伙菜,并且指定引擎配置和 onStart 的回調(diào)。

? ? ?* @method run

? ? ?* @param {Object} config - Pass configuration object or onStart function

? ? ?* @param {Function} onStart - function to be executed after game initialized

? ? ?*/

? ? run: function (config, onStart) {

? ? ? ? this._initConfig(config);

? ? ? ? this.onStart = onStart;

? ? ? ? this.prepare(game.onStart && game.onStart.bind(game));

? ? },

? ? //? @ Persist root node section

? ? /**

? ? ?* !#en

? ? ?* Add a persistent root node to the game, the persistent node won't be destroyed during scene transition.<br/>

? ? ?* The target node must be placed in the root level of hierarchy, otherwise this API won't have any effect.

? ? ?* !#zh

? ? ?* 聲明常駐根節(jié)點命迈,該節(jié)點不會被在場景切換中被銷毀贩绕。<br/>

? ? ?* 目標節(jié)點必須位于為層級的根節(jié)點,否則無效壶愤。

? ? ?* @method addPersistRootNode

? ? ?* @param {Node} node - The node to be made persistent

? ? ?*/

? ? addPersistRootNode: function (node) {

? ? ? ? /* 不是Node類型或者uuid位空 提示warn */

? ? ? ? if (!cc.Node.isNode(node) || !node.uuid) {

? ? ? ? ? ? /* The target can not be made persist because it's not a cc.Node or it doesn't have _id property. */

? ? ? ? ? ? cc.warnID(3800);

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? var id = node.uuid;

? ? ? ? /* 不在容器里面 */

? ? ? ? if (!this._persistRootNodes[id]) {

? ? ? ? ? ? /* 主場景 */

? ? ? ? ? ? var scene = cc.director._scene;

? ? ? ? ? ? /* scene 是有效的 */

? ? ? ? ? ? if (cc.isValid(scene)) {

? ? ? ? ? ? ? ? /* node 沒有父節(jié)點 淑倾,設(shè)置node的父節(jié)點為scene,add到scene上 */

? ? ? ? ? ? ? ? if (!node.parent) {

? ? ? ? ? ? ? ? ? ? node.parent = scene;

? ? ? ? ? ? ? ? }/* 假如node的父節(jié)點類型不是scene類型提示 */

? ? ? ? ? ? ? ? else if (!(node.parent instanceof cc.Scene)) {

? ? ? ? ? ? ? ? ? ? /* The node can not be made persist because it's not under root node.

? ? ? ? ? ? ? ? ? ? 常駐節(jié)點的父節(jié)點 一定是scene征椒,假如不是會提示 */

? ? ? ? ? ? ? ? ? ? cc.warnID(3801);

? ? ? ? ? ? ? ? ? ? return;

? ? ? ? ? ? ? ? }/* 假如當(dāng)前node節(jié)點的父節(jié)點娇哆,不是當(dāng)前場景 提示 這個預(yù)加載節(jié)點,沒有在當(dāng)前場景下

? ? ? ? ? ? ? ? The node can not be made persist because it's not in current scene. */

? ? ? ? ? ? ? ? else if (node.parent !== scene) {

? ? ? ? ? ? ? ? ? ? cc.warnID(3802);

? ? ? ? ? ? ? ? ? ? return;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? /* 添加node到容器 */

? ? ? ? ? ? this._persistRootNodes[id] = node;

? ? ? ? ? ? /* 設(shè)置node為常駐節(jié)點 flag為true */

? ? ? ? ? ? node._persistNode = true;

? ? ? ? ? ? /* _releaseManager 是一個對象勃救,管理釋放asset; */

? ? ? ? ? ? cc.assetManager._releaseManager._addPersistNodeRef(node);

? ? ? ? }

? ? },

? ? /**

? ? ?* !#en Remove a persistent root node.

? ? ?* !#zh 取消常駐根節(jié)點碍讨。

? ? ?* @method removePersistRootNode

? ? ?* @param {Node} node - The node to be removed from persistent node list

? ? ?*/

? ? removePersistRootNode: function (node) {

? ? ? ? /* 移除某個具體的常駐節(jié)點 ,node節(jié)點的uuid獲取蒙秒,*/

? ? ? ? var id = node.uuid || '';

? ? ? ? if (node === this._persistRootNodes[id]) {

? ? ? ? ? ? delete this._persistRootNodes[id];

? ? ? ? ? ? node._persistNode = false;

? ? ? ? ? ? cc.assetManager._releaseManager._removePersistNodeRef(node);

? ? ? ? }

? ? },

? ? /**

? ? ?* !#en Check whether the node is a persistent root node.

? ? ?* !#zh 檢查節(jié)點是否是常駐根節(jié)點勃黍。

? ? ?* @method isPersistRootNode

? ? ?* @param {Node} node - The node to be checked

? ? ?* @return {Boolean}

? ? ?*/

? ? isPersistRootNode: function (node) {

? ? ? ? return node._persistNode;

? ? },

? ? //@Private Methods

? ? //? @Time ticker section

? ? _setAnimFrame: function () {

? ? ? ? /* 獲取當(dāng)前時間-ms?


? ? ? ? Performance.now()和Date.now()之間最大的區(qū)別是,

? ? ? ? Date.now()返回一個與Unix時間有關(guān)的時間戳

? ? ? ? (從00:00:00 UTC税肪,1970年1月1日開始的時間)溉躲。

? ? ? ? 這就是我們可能面臨的一個問題。

? ? ? ? JavaScript如何知道從這個日期開始已經(jīng)過了多少時間益兄?它從系統(tǒng)時鐘中獲取锻梳。

? ? ? ? 但是,由于系統(tǒng)時鐘存在于我們的機器中净捅,它可以手動或通過程序進行調(diào)整疑枯,因此,

? ? ? ? 時間精度無法保證蛔六。

? ? */

? ? ? ? this._lastTime = performance.now();

? ? ? ? /* 幀率 */

? ? ? ? var frameRate = game.config.frameRate;

? ? ? ? /* 1000毫秒 除以幀率【每秒多少幀】荆永,就是每一幀需要的時間 */

? ? ? ? this._frameTime = 1000 / frameRate;

? ? ? ? /*_maxParticleDeltaTime 粒子系統(tǒng)最大步長增量時間 */

? ? ? ? cc.director._maxParticleDeltaTime = this._frameTime / 1000 * 2;

? ? ? ? /* 通過 CC_JSB 來判斷是否為 native 環(huán)境(模擬器)。

? ? ? ? 基于jsb的說明

? ? ? ? https://docs.cocos.com/creator/2.4/manual/zh/advanced-topics/JSB2.0-learning.html

? ? ? ? ?*/

? ? ? ? if (CC_JSB || CC_RUNTIME) {

? ? ? ? ? ? jsb.setPreferredFramesPerSecond(frameRate);

? ? ? ? ? ? window.requestAnimFrame = window.requestAnimationFrame;

? ? ? ? ? ? window.cancelAnimFrame = window.cancelAnimationFrame;

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? /* 當(dāng)幀率不等于60 并且不等于30的時候国章,重寫requestAnimFrame

? ? ? ? ? ? 和 cancelAnimFrame 方法 */

? ? ? ? ? ? /*?

? ? ? ? ? ? window.requestAnimationFrame() 告訴瀏覽器——你希望執(zhí)行一個動畫具钥,

? ? ? ? ? ? 并且要求瀏覽器在下次重繪之前調(diào)用指定的回調(diào)函數(shù)更新動畫。

? ? ? ? ? ? 該方法需要傳入一個回調(diào)函數(shù)作為參數(shù)液兽,該回調(diào)函數(shù)會在瀏覽器下一次重繪之前執(zhí)行骂删。

? ? ? ? ? ? ?*/

? ? ? ? ? ? if (frameRate !== 60 && frameRate !== 30) {

? ? ? ? ? ? ? ? window.requestAnimFrame = this._stTime;

? ? ? ? ? ? ? ? window.cancelAnimFrame = this._ctTime;

? ? ? ? ? ? }

? ? ? ? ? ? else {

? ? ? ? ? ? ? ? /* 對requestAnimFrame函數(shù)做了兼容性封裝,用于兼容不同的瀏覽器環(huán)境, */

? ? ? ? ? ? ? ? window.requestAnimFrame = window.requestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.webkitRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.mozRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.oRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.msRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? this._stTime;

? ? ? ? ? ? ? ? window.cancelAnimFrame = window.cancelAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.cancelRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.msCancelRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.mozCancelRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.oCancelRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.webkitCancelRequestAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.msCancelAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.mozCancelAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.webkitCancelAnimationFrame ||

? ? ? ? ? ? ? ? ? ? window.oCancelAnimationFrame ||

? ? ? ? ? ? ? ? ? ? this._ctTime;

? ? ? ? ? ? }

? ? ? ? }

? ? },

? ? _stTime: function (callback) {

? ? ? ? /* 當(dāng)前時間 */

? ? ? ? var currTime = performance.now();

? ? ? ? /* game._frameTime 每一幀的時間 */

? ? ? ? var timeToCall = Math.max(0, game._frameTime - (currTime - game._lastTime));

? ? ? ? var id = window.setTimeout(function () { callback(); },

? ? ? ? ? ? timeToCall);

? ? ? ? game._lastTime = currTime + timeToCall;

? ? ? ? return id;

? ? },

? ? /* 清除定時器 */

? ? _ctTime: function (id) {

? ? ? ? window.clearTimeout(id);

? ? },

? ? //Run game.

? ? /* 游戲主循環(huán) */

? ? _runMainLoop: function () {

? ? ? ? /* 如果是編輯器 則不執(zhí)行 */

? ? ? ? if (CC_EDITOR) {

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? /* 引擎沒有準備好宁玫,則return */

? ? ? ? if (!this._prepared) return;

? ? ? ? /* 聲明多個變量?

? ? ? ? self = this

? ? ? ? callback 為undefined

? ? ? ? config為 配置

? ? ? ? director導(dǎo)演器

? ? ? ? frameRate 幀率 = config.frameRate;

? ? ? ? */

? ? ? ? var self = this, callback, config = self.config,

? ? ? ? ? ? director = cc.director,

? ? ? ? ? ? skip = true, frameRate = config.frameRate;

? ? ? ? /* 設(shè)置顯示fps與否 */

? ? ? ? debug.setDisplayStats(config.showFPS);

? ? ? ? /* 對callback進行賦值,// 設(shè)置幀回調(diào) */

? ? ? ? callback = function (now) {

? ? ? ? ? ? if (!self._paused) {

? ? ? ? ? ? ? ? self._intervalId = window.requestAnimFrame(callback);

? ? ? ? ? ? ? ? if (!CC_JSB && !CC_RUNTIME && frameRate === 30) {

? ? ? ? ? ? ? ? ? ? /* 30幀的時候粗恢,在web瀏覽器 */

? ? ? ? ? ? ? ? ? ? /* 賦值,skip = !skip欧瘪,用于判斷是否繼續(xù)循環(huán) */

? ? ? ? ? ? ? ? ? ? if (skip = !skip) {

? ? ? ? ? ? ? ? ? ? ? ? return;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? director.mainLoop(now);

? ? ? ? ? ? }

? ? ? ? };

? ? ? ? // 將在下一幀開始循環(huán)回調(diào)

? ? ? ? self._intervalId = window.requestAnimFrame(callback);

? ? ? ? /* 暫停設(shè)置為false */

? ? ? ? self._paused = false;

? ? },

? ? //? @Game loading section

? ? _initConfig(config) {

? ? ? ? // Configs adjustment

? ? ? ? if (typeof config.debugMode !== 'number') {

? ? ? ? ? ? config.debugMode = 0;

? ? ? ? }

? ? ? ? config.exposeClassName = !!config.exposeClassName;

? ? ? ? if (typeof config.frameRate !== 'number') {

? ? ? ? ? ? config.frameRate = 60;

? ? ? ? }

? ? ? ? let renderMode = config.renderMode;

? ? ? ? if (typeof renderMode !== 'number' || renderMode > 2 || renderMode < 0) {

? ? ? ? ? ? config.renderMode = 0;

? ? ? ? }

? ? ? ? if (typeof config.registerSystemEvent !== 'boolean') {

? ? ? ? ? ? config.registerSystemEvent = true;

? ? ? ? }

? ? ? ? if (renderMode === 1) {

? ? ? ? ? ? config.showFPS = false;

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? config.showFPS = !!config.showFPS;

? ? ? ? }

? ? ? ? // Collide Map and Group List

? ? ? ? this.collisionMatrix = config.collisionMatrix || [];

? ? ? ? this.groupList = config.groupList || [];

? ? ? ? /* 重置調(diào)試模式 */

? ? ? ? debug._resetDebugSetting(config.debugMode);

? ? ? ? /* 給全局變量config 賦值 */

? ? ? ? this.config = config;

? ? ? ? /* 配置加載完畢眷射,設(shè)置為true */

? ? ? ? this._configLoaded = true;

? ? },

? ? _determineRenderType() {

? ? ? ? /* 聲明變量config,不直接用佛掖,是可以減少作用域鏈查找的消耗 */

? ? ? ? let config = this.config,

? ? ? ? ? ? userRenderMode = parseInt(config.renderMode) || 0;

? ? ? ? // Determine RenderType

? ? ? ? this.renderType = this.RENDER_TYPE_CANVAS;

? ? ? ? let supportRender = false;

? ? ? ? if (userRenderMode === 0) {

? ? ? ? ? ? /* 設(shè)置渲染類型妖碉,默認為webgl */

? ? ? ? ? ? if (cc.sys.capabilities['opengl']) {

? ? ? ? ? ? ? ? this.renderType = this.RENDER_TYPE_WEBGL;

? ? ? ? ? ? ? ? supportRender = true;

? ? ? ? ? ? }

? ? ? ? ? ? else if (cc.sys.capabilities['canvas']) {

? ? ? ? ? ? ? ? this.renderType = this.RENDER_TYPE_CANVAS;

? ? ? ? ? ? ? ? supportRender = true;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? else if (userRenderMode === 1 && cc.sys.capabilities['canvas']) {

? ? ? ? ? ? this.renderType = this.RENDER_TYPE_CANVAS;

? ? ? ? ? ? supportRender = true;

? ? ? ? }

? ? ? ? else if (userRenderMode === 2 && cc.sys.capabilities['opengl']) {

? ? ? ? ? ? this.renderType = this.RENDER_TYPE_WEBGL;

? ? ? ? ? ? supportRender = true;

? ? ? ? }

? ? ? ? /*? 不支持渲染模式 拋出異常 */

? ? ? ? if (!supportRender) {

? ? ? ? ? ? throw new Error(debug.getError(3820, userRenderMode));

? ? ? ? }

? ? },

? ? /* 初始化渲染相關(guān)-畫布,div等元素 */

? ? _initRenderer() {

? ? ? ? // Avoid setup to be called twice.

? ? ? ? /* 假如已經(jīng)初始化苦囱,則返回 */

? ? ? ? if (this._rendererInitialized) return;

? ? ? ? /* 聲明幾個變量 id-畫布對應(yīng)的cavas的id嗅绸; eg:id: 'GameCanvas',

? ? ? ? ?寬高 */

? ? ? ? let el = this.config.id,

? ? ? ? ? ? width, height,

? ? ? ? ? ? localCanvas, localContainer;

? ? ? ? ? ? /* 假如是模擬器native環(huán)境 */

? ? ? ? if (CC_JSB || CC_RUNTIME) {

? ? ? ? ? ? /* 創(chuàng)建html-node節(jié)點 名稱為DIV */

? ? ? ? ? ? this.container = localContainer = document.createElement("DIV");

? ? ? ? ? ? this.frame = localContainer.parentNode === document.body ? document.documentElement : localContainer.parentNode;

? ? ? ? ? ? localCanvas = window.__canvas;

? ? ? ? ? ? this.canvas = localCanvas;

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? /* 查找名稱為GameCanvas 的元素 */

? ? ? ? ? ? var element = (el instanceof HTMLElement) ? el : (document.querySelector(el) || document.querySelector('#' + el));

? ? ? ? ? ? if (element.tagName === "CANVAS") {

? ? ? ? ? ? ? ? width = element.width;

? ? ? ? ? ? ? ? height = element.height;

? ? ? ? ? ? ? ? //it is already a canvas, we wrap it around with a div

? ? ? ? ? ? ? ? /* 它已經(jīng)是一個畫布,我們用一個 div 將它包裹起來 */

? ? ? ? ? ? ? ? this.canvas = localCanvas = element;

? ? ? ? ? ? ? ? this.container = localContainer = document.createElement("DIV");

? ? ? ? ? ? ? ? if (localCanvas.parentNode)

? ? ? ? ? ? ? ? ? ? localCanvas.parentNode.insertBefore(localContainer, localCanvas);

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? //we must make a new canvas and place into this element

? ? ? ? ? ? ? ? /* //我們必須制作一個新畫布并將其放入此元素中 */

? ? ? ? ? ? ? ? if (element.tagName !== "DIV") {

? ? ? ? ? ? ? ? ? ? /* Warning: target element is not a DIV or CANVAS */

? ? ? ? ? ? ? ? ? ? cc.warnID(3819);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? width = element.clientWidth;

? ? ? ? ? ? ? ? height = element.clientHeight;

? ? ? ? ? ? ? ? this.canvas = localCanvas = document.createElement("CANVAS");

? ? ? ? ? ? ? ? this.container = localContainer = document.createElement("DIV");

? ? ? ? ? ? ? ? element.appendChild(localContainer);

? ? ? ? ? ? }

? ? ? ? ? ? /* 設(shè)置html標簽的id名稱為Cocos2dGameContainer */

? ? ? ? ? ? localContainer.setAttribute('id', 'Cocos2dGameContainer');

? ? ? ? ? ? localContainer.appendChild(localCanvas);

? ? ? ? ? ? this.frame = (localContainer.parentNode === document.body) ? document.documentElement : localContainer.parentNode;

? ? ? ? ? ? function addClass(element, name) {

? ? ? ? ? ? ? ? var hasClass = (' ' + element.className + ' ').indexOf(' ' + name + ' ') > -1;

? ? ? ? ? ? ? ? if (!hasClass) {

? ? ? ? ? ? ? ? ? ? if (element.className) {

? ? ? ? ? ? ? ? ? ? ? ? element.className += " ";

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? element.className += name;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? /* Web 頁面上的 Canvas Element ID撕彤,僅適用于 web 端鱼鸠。 */

? ? ? ? ? ? addClass(localCanvas, "gameCanvas");

? ? ? ? ? ? localCanvas.setAttribute("width", width || 480);

? ? ? ? ? ? localCanvas.setAttribute("height", height || 320);

? ? ? ? ? ? localCanvas.setAttribute("tabindex", 99);

? ? ? ? }

// 獲取可用的渲染模式

? ? ? ? this._determineRenderType();

? ? ? ? // WebGL context created successfully

? ? ? ? /* WebGL 上下文創(chuàng)建成功 */

? ? ? ? if (this.renderType === this.RENDER_TYPE_WEBGL) {

? ? ? ? ? ? var opts = {

? ? ? ? ? ? ? ? 'stencil': true,

? ? ? ? ? ? ? ? // MSAA is causing serious performance dropdown on some browsers.

? ? ? ? ? ? ? ? /* MSAA 導(dǎo)致某些瀏覽器的性能嚴重下降。 */

? ? ? ? ? ? ? ? 'antialias': cc.macro.ENABLE_WEBGL_ANTIALIAS,

? ? ? ? ? ? ? ? 'alpha': cc.macro.ENABLE_TRANSPARENT_CANVAS

? ? ? ? ? ? };

? ? ? ? ? ? renderer.initWebGL(localCanvas, opts);

? ? ? ? ? ? this._renderContext = renderer.device._gl;

? ? ? ? ? ? // Enable dynamic atlas manager by default

? ? ? ? ? ? /* 默認啟用動態(tài)圖集管理器 */

? ? ? ? ? ? if (!cc.macro.CLEANUP_IMAGE_CACHE && dynamicAtlasManager) {

? ? ? ? ? ? ? ? dynamicAtlasManager.enabled = true;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? if (!this._renderContext) {

? ? ? ? ? ? this.renderType = this.RENDER_TYPE_CANVAS;

? ? ? ? ? ? // Could be ignored by module settings

? ? ? ? ? ? /* // 可以被模塊設(shè)置忽略 */

? ? ? ? ? ? renderer.initCanvas(localCanvas);

? ? ? ? ? ? this._renderContext = renderer.device._ctx;

? ? ? ? }

? ? ? ? this.canvas.oncontextmenu = function () {

? ? ? ? ? ? if (!cc._isContextMenuEnable) return false;

? ? ? ? };

? ? ? ? this._rendererInitialized = true;

? ? },

? ? _initEvents: function () {

? ? ? ? var win = window, hiddenPropName;

? ? ? ? // register system events

? ? ? ? if (this.config.registerSystemEvent)

? ? ? ? ? ? cc.internal.inputManager.registerSystemEvent(this.canvas);


? ? ? ? ? ? /* Document.hidden (只讀屬性)返回布爾值羹铅,表示頁面是(true)否(false)隱藏蚀狰。?

? ? ? ? ? ? 表示頁面是否處于隱藏狀態(tài)。頁面隱藏包括頁面在后臺標簽頁或者瀏覽器最小化职员。

? ? ? ? ? ? */

? ? ? ? ? ?/* // 兼容不同瀏覽器 */

? ? ? ? if (typeof document.hidden !== 'undefined') {

? ? ? ? ? ? hiddenPropName = "hidden";

? ? ? ? } else if (typeof document.mozHidden !== 'undefined') {

? ? ? ? ? ? hiddenPropName = "mozHidden";

? ? ? ? } else if (typeof document.msHidden !== 'undefined') {

? ? ? ? ? ? hiddenPropName = "msHidden";

? ? ? ? } else if (typeof document.webkitHidden !== 'undefined') {

? ? ? ? ? ? hiddenPropName = "webkitHidden";

? ? ? ? }

? ? ? ? var hidden = false;

? ? ? ? /* 頁面隱藏的監(jiān)聽 */

? ? ? ? function onHidden() {

? ? ? ? ? ? if (!hidden) {

? ? ? ? ? ? ? ? hidden = true;

? ? ? ? ? ? ? ? game.emit(game.EVENT_HIDE);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? // In order to adapt the most of platforms the onshow API.

? ? ? ? /* 頁面顯示的監(jiān)聽 */

? ? ? ? function onShown(arg0, arg1, arg2, arg3, arg4) {

? ? ? ? ? ? if (hidden) {

? ? ? ? ? ? ? ? /* 設(shè)置hidden為false */

? ? ? ? ? ? ? ? hidden = false;

? ? ? ? ? ? ? ? game.emit(game.EVENT_SHOW, arg0, arg1, arg2, arg3, arg4);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? if (hiddenPropName) {

? ? ? ? ? ? /* 監(jiān)控view變化 */

? ? ? ? ? ? var changeList = [

? ? ? ? ? ? ? ? "visibilitychange",

"mozvisibilitychange",

? ? ? ? ? ? ? ? "msvisibilitychange",

? ? ? ? ? ? ? ? "webkitvisibilitychange",

? ? ? ? ? ? ? ? "qbrowserVisibilityChange"

? ? ? ? ? ? ];

? ? ? ? ? ? for (var i = 0; i < changeList.length; i++) {

? ? ? ? ? ? ? ? document.addEventListener(changeList[i], function (event) {

? ? ? ? ? ? ? ? ? ? var visible = document[hiddenPropName];

? ? ? ? ? ? ? ? ? ? // QQ App

? ? ? ? ? ? ? ? ? ? visible = visible || event["hidden"];

? ? ? ? ? ? ? ? ? ? if (visible)

? ? ? ? ? ? ? ? ? ? ? ? onHidden();

? ? ? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? ? ? ? ? onShown();

? ? ? ? ? ? ? ? });

? ? ? ? ? ? }

? ? ? ? } else {

? ? ? ? ? ? /* 添加監(jiān)聽麻蹋,頁面隱藏 和 頁面顯示 */

? ? ? ? ? ? win.addEventListener("blur", onHidden);

? ? ? ? ? ? win.addEventListener("focus", onShown);

? ? ? ? }

? ? ? ? if (navigator.userAgent.indexOf("MicroMessenger") > -1) {

? ? ? ? ? ? win.onfocus = onShown;

? ? ? ? }

? ? ? ? if ("onpageshow" in window && "onpagehide" in window) {

? ? ? ? ? ? win.addEventListener("pagehide", onHidden);

? ? ? ? ? ? win.addEventListener("pageshow", onShown);

? ? ? ? ? ? // Taobao UIWebKit

? ? ? ? ? ? document.addEventListener("pagehide", onHidden);

? ? ? ? ? ? document.addEventListener("pageshow", onShown);

? ? ? ? }

? ? ? ? this.on(game.EVENT_HIDE, function () {

? ? ? ? ? ? /* 頁面隱藏 游戲暫停 */

? ? ? ? ? ? game.pause();

? ? ? ? });

? ? ? ? this.on(game.EVENT_SHOW, function () {

? ? ? ? ? ? /* 頁面顯示 游戲恢復(fù) */

? ? ? ? ? ? game.resume();

? ? ? ? });

? ? }

};

/* EventTarget 是一個function, */

EventTarget.call(game);

/* 把EventTarget的屬性賦值到 game 上焊切; 核心是添加? on off 等事件注冊 */

cc.js.addon(game, EventTarget.prototype);

/**

?* @module cc

?*/

/**

?* !#en This is a Game instance.

?* !#zh 這是一個 Game 類的實例扮授,包含游戲主體信息并負責(zé)驅(qū)動游戲的游戲?qū)ο蟆专肪!?/p>

?* @property game

?* @type Game

?*/

cc.game = module.exports = game;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刹勃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嚎尤,更是在濱河造成了極大的恐慌荔仁,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芽死,死亡現(xiàn)場離奇詭異乏梁,居然都是意外死亡,警方通過查閱死者的電腦和手機关贵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門遇骑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人揖曾,你說我怎么就攤上這事落萎∈拼郏” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵模暗,是天一觀的道長。 經(jīng)常有香客問我念祭,道長兑宇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任粱坤,我火速辦了婚禮隶糕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘站玄。我一直安慰自己枚驻,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布株旷。 她就那樣靜靜地躺著再登,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晾剖。 梳的紋絲不亂的頭發(fā)上锉矢,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機與錄音齿尽,去河邊找鬼沽损。 笑死,一個胖子當(dāng)著我的面吹牛循头,可吹牛的內(nèi)容都是我干的绵估。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼卡骂,長吁一口氣:“原來是場噩夢啊……” “哼国裳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起偿警,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤躏救,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后螟蒸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盒使,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年七嫌,在試婚紗的時候發(fā)現(xiàn)自己被綠了少办。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡诵原,死狀恐怖英妓,靈堂內(nèi)的尸體忽然破棺而出挽放,到底是詐尸還是另有隱情,我是刑警寧澤蔓纠,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布辑畦,位于F島的核電站,受9級特大地震影響腿倚,放射性物質(zhì)發(fā)生泄漏纯出。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一敷燎、第九天 我趴在偏房一處隱蔽的房頂上張望暂筝。 院中可真熱鬧,春花似錦硬贯、人聲如沸焕襟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸵赖。三九已至,卻和暖如春卫漫,著一層夾襖步出監(jiān)牢的瞬間肾砂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工镐确, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人源葫。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像息堂,于是被迫代替她去往敵國和親嚷狞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容