/****************************************************************************
/* 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;