摘要:是一個靜態(tài)類,調用方法來初始化各項支持信息。小結通過和這兩個靜態(tài)類初始化了項目運行的環(huán)境參數,然后創(chuàng)建了屏幕適配器根據不同的適配策略調整。下一篇源碼分析全局哈?;惡腿之惒胶瘮祵ο蠼涌?/p>
egret的github地址是https://github.com/egret-labs...,大家自己git clone到本地。
一.路口html文件用ergetWing新建一個工程,打開根目錄下的index.html,這個就是項目的入口文件,我們看下其中裝載游戲內容的DIV容器
這里是官方的配置說明,因為我們后面分析源碼會用到,大家可以先粗略看一下
data-entry-class=”Main” 設置項目的入口文件,表示項目的入口類,默認為Main,如果需要自定義的話需要在項目中先創(chuàng)建類,然后在這里配置類的名字。
data-orientation=”auto” 設置旋轉模式。
data-scale-mode=”showAll” 設置縮放模式。
data-frame-rate=”30” 這里是運行的幀率。
data-content-width=”480” 和 data-content-height=”800” 用來設置舞臺的設計寬和高
data-show-paint-rect=”false” 設置顯示臟矩形的重繪區(qū)域。
data-multi-fingered=”2” 設置多指觸摸
data-show-fps=”false” data-show-log=”false” 這里設置顯示幀率和log,只有在調試時會顯示,發(fā)布的版本會去掉。
data-log-filter=”” 設置一個正則表達式過濾條件,日志文本匹配這個正則表達式的時候才顯示這條日志。如 data-log-filter="^egret" 表示僅顯示以 egret 開頭的日志。
data-show-fps-style=”x:0,y:0,size:30,textColor:0x00c200,bgAlpha:0.9” 這里設置fps面板的樣式。目前支持默認的這幾種設置,修改其值即可,比如修改面板位置可以設置x和y,改變大小可以設置size,改變文字顏色textColor,改變背景面板的透明度bgAlpha。
頁面打開后會立即執(zhí)行egret.runEgret(),這幾個參數后面會詳細講,我們先理解erget的運行流程。
EgretWeb.ts入口腳本我們在源碼項目中搜索runEgret可以看到分別在
src/egret/native/EgretNative.ts
src/egret/player/EgretEntry.ts
src/egret/web/EgretWeb.ts中被定義。
這是egret的一個基本的結構,EgretEntry.ts定義了接口,而EgretNative.ts和EgretWeb.ts分別定義在原生平臺和web平臺上的實現(xiàn)。我們先按照web部分的思路進行分析。
let isRunning: boolean = false; /** * @private * 網頁加載完成,實例化頁面中定義的Egret標簽 */ function runEgret(options?: runEgretOptions): void { if (isRunning) { return; } isRunning = true; if (!options) { options = {}; } Html5Capatibility._audioType = options.audioType; Html5Capatibility.$init(); //...... }
首先看runEntry函數的前面幾行,這里利用一個閉包和isRunning,還有if語句來防止重復運行游戲。這里的isRunning這個變量明顯只被runEntry函數使用,所以不把它定義為成員私有屬性而是定義成一個變量。Html5Capatibility是一個靜態(tài)類,調用$init()方法來初始化html5各項支持信息。
public static $init(): void { let ua: string = navigator.userAgent.toLowerCase(); Html5Capatibility.ua = ua; egret.Capabilities.$isMobile = (ua.indexOf("mobile") != -1 || ua.indexOf("android") != -1); //...... }
我們稍微來看一下$init()方法,這里還調用了一個全局靜態(tài)類Capabilities,這個類在src/egret/system/Capabilities.ts下,主要是存儲當前運行的設備(PC/IOS/Android)信息、平臺信息(web/native)、渲染模式、引擎版本和客戶端尺寸。
我們可以看出,在web平臺關于運行環(huán)境的各項信息從Capabilities獲得,HTML5的接口支持從Html5Capatibility獲得。
// WebGL上下文參數自定義 function runEgret(options?: runEgretOptions): void { if (options.renderMode == "webgl") { // WebGL抗鋸齒默認關閉,提升PC及某些平臺性能 let antialias = options.antialias; WebGLRenderContext.antialias = !!antialias; // WebGLRenderContext.antialias = (typeof antialias == undefined) ? true : antialias; } sys.CanvasRenderBuffer = web.CanvasRenderBuffer; setRenderMode(options.renderMode); ...... }
這里有個小技巧就是利用兩個!來轉型,因為options.antialias可能是false、true、undefined中的一個,如果是false或者true,兩個!!相當于沒有作用,如果是undefined就被轉換成false。
/** * 設置渲染模式。"auto","webgl","canvas" * @param renderMode */ function setRenderMode(renderMode: string): void { //...... if (renderMode == "webgl" && WebGLUtils.checkCanUseWebGL()) { sys.RenderBuffer = web.WebGLRenderBuffer; sys.systemRenderer = new WebGLRenderer(); sys.canvasRenderer = new CanvasRenderer(); sys.customHitTestBuffer = new WebGLRenderBuffer(3, 3); sys.canvasHitTestBuffer = new CanvasRenderBuffer(3, 3); Capabilities.$renderMode = "webgl"; } else { sys.RenderBuffer = web.CanvasRenderBuffer; sys.systemRenderer = new CanvasRenderer(); sys.canvasRenderer = sys.systemRenderer; sys.customHitTestBuffer = new CanvasRenderBuffer(3, 3); sys.canvasHitTestBuffer = sys.customHitTestBuffer; Capabilities.$renderMode = "canvas"; } //...... }
我們簡單來看一下setRenderMode方法,如果用戶把renderMode設置為webGL并且瀏覽器支持webGL就使用webGL否則使用canvas,WebGLUtils.checkCanUseWebGL()這個方法大家可以自己去看一下,同樣使用了兩個!!的技巧,關于webGL的使用大家可以看這里初識 WebGL
3.分辨率配置function runEgret(options?: runEgretOptions): void { //...... let canvasScaleFactor; if (options.canvasScaleFactor) { canvasScaleFactor = options.canvasScaleFactor; } else if(options.calculateCanvasScaleFactor) { canvasScaleFactor = options.calculateCanvasScaleFactor(sys.canvasHitTestBuffer.context); } else { //based on : https://github.com/jondavidjohn/hidpi-canvas-polyfill let context = sys.canvasHitTestBuffer.context; let backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; canvasScaleFactor = (window.devicePixelRatio || 1) / backingStore; } sys.DisplayList.$canvasScaleFactor = canvasScaleFactor; //...... }
如果用戶配置了縮放比例就使用它,配置了計算縮放比例的方法就調用它,否則計算當前瀏覽器支持的最大精度的縮放比例。
4.執(zhí)行系統(tǒng)定時器function runEgret(options?: runEgretOptions): void { //...... let ticker = egret.ticker; startTicker(ticker); //...... }
egret.sys.$ticker是egret.SystemTicker類的單例對象,首先對它調用了startTicker方法:
function startTicker(ticker:egret.sys.SystemTicker):void { var requestAnimationFrame = window["requestAnimationFrame"] || window["webkitRequestAnimationFrame"] || window["mozRequestAnimationFrame"] || window["oRequestAnimationFrame"] || window["msRequestAnimationFrame"]; if (!requestAnimationFrame) { requestAnimationFrame = function (callback) { return window.setTimeout(callback, 1000 / 60); }; } requestAnimationFrame.call(window, onTick); function onTick():void { ticker.update(); requestAnimationFrame.call(window, onTick) } }
這里同樣是判讀瀏覽器是否存在requestAnimationFrame的API,存在則使用之,否則使用setTimeout方法,這里onTicker使用了延遲遞歸調用,實現(xiàn)每隔一段時間就調用一次ticker.update()方法,這里使用call方法確保調用該方法對象是全局window對象,避開js中this的坑。
5.屏幕適配和播放器的創(chuàng)建function runEgret(options?: runEgretOptions): void { //...... if (options.screenAdapter) { egret.sys.screenAdapter = options.screenAdapter; } else if (!egret.sys.screenAdapter) { egret.sys.screenAdapter = new egret.sys.DefaultScreenAdapter(); } let list = document.querySelectorAll(".egret-player"); let length = list.length; for (let i = 0; i < length; i++) { let container =list[i]; let player = new WebPlayer(container, options); container["egret-player"] = player; //webgl模式關閉臟矩形 if (Capabilities.$renderMode == "webgl") { player.stage.dirtyRegionPolicy = DirtyRegionPolicy.OFF; } } if (Capabilities.$renderMode == "webgl") { egret.sys.DisplayList.prototype.setDirtyRegionPolicy = function () { }; } window.addEventListener("resize", function () { if (isNaN(resizeTimer)) { resizeTimer = window.setTimeout(doResize, 300); } }); //...... } //...... let resizeTimer: number = NaN; function doResize() { resizeTimer = NaN; egret.updateAllScreens(); if (customContext) { customContext.onResize(context); } }
接下來使用document.querySelectorAll()方法取得所有擁有"egret-player"的CSS class的DOM對象。就是我們一開始在index.html的body里看到的那個div標簽。
遍歷這些DOM對象,為每一個創(chuàng)建一個egret.WebPlayer對象,并賦值給DOM的"egret-player"屬性(這是個自定義屬性)。
這里還有一個值得注意的對方是resizeTimer,每當瀏覽器尺寸變化先進行一個判斷,如果不存在重繪定時器(也就是resizeTimer為NaN),就啟動一個定時器,在300毫秒后重新獲取瀏覽器尺寸重新繪制,并把resizeTimer賦值為NaN表示這個定時器關閉了。這么做,是因為在PC端,我們修改瀏覽器尺寸是一個延續(xù)動作,也就是鼠標持續(xù)移動改變窗口尺寸,定義一個300毫秒的定時器延時重繪是防止過多的重繪請求占用資源。
小結runEgret通過Html5Capatibility和Capatibilities這兩個靜態(tài)類初始化了項目運行的環(huán)境參數,然后創(chuàng)建了屏幕適配器egret.sys.screenAdapter根據不同的適配策略調整。然后通過監(jiān)聽winodw對象的resize事件監(jiān)聽客戶端尺寸變化(包括旋轉設備,改變?yōu)g覽器窗口尺寸等)。最主要的事情是調用創(chuàng)建一個定時器無限地調用egret.sys.$ticker的update()方法進行全局的數據更新和視圖渲染。那么整個游戲引擎大概的啟用流程到這里就結束了。
下一篇:erget源碼分析(2):全局哈希基類和全局異步函數對象接口
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/89710.html
摘要:異步函數對象接口,包含和兩個成員方法。哈希計數在整個的源碼中都沒有找到和方法的調用,這兩個方法的具體作用是在原生中實現(xiàn)類式繼承和私有屬性一類的功能。 文件結構 utils/HashObject.ts文件:showImg(https://segmentfault.com/img/bVZpuq?w=642&h=472); 首先解釋一下文件結構圖 __extends方法 通過原型對象模擬類...
摘要:概述下面我們來分析一下中的生命周期。定義了監(jiān)聽生命周期的類,這個三個成員方法分別執(zhí)行暫停繼續(xù)和刷新。方法作為橋梁,接收到具體的類型的函數,創(chuàng)建的一個實例作為參數調用它。函數做了兩件事情暫停應用程序,暫停背景音樂和音效的播放。 概述 下面我們來分析一下erget中的生命周期。 src/egret/player/SystemTicker.ts: export namespace li...
閱讀 3581·2021-11-18 10:02
閱讀 3143·2019-08-29 18:34
閱讀 3426·2019-08-29 17:00
閱讀 464·2019-08-29 12:35
閱讀 787·2019-08-28 18:22
閱讀 1982·2019-08-26 13:58
閱讀 1709·2019-08-26 10:39
閱讀 2706·2019-08-26 10:11