本帖最后由 scarlet 于 2016-1-21 23:15 编辑

从一开始接触egret到使用大概有一年多了,记得14年6月份的时候,神经猫火的那段时间就玩过了,只是当时各方面支持不完善,就不了了之,去年2.0出来,就正式开搞了,算一算也快一年了,不过一直都是埋头用引擎,发现连引擎的原理好像都似懂非懂,所以现在从源码看起,让自己更了解引擎的原理。

正所谓好记性不如烂笔头,我觉得自己看完还是要做做笔记的,顺便发到论坛上来分享一下,如果有什么说的不对的,欢迎大家指正。

记得刚开始用的时候,就有疑问,这个东西到底是怎么跑起来的,我当然ts是编译成js在浏览器中运行,但是具体的流程是怎么跑的,一直在我让我很疑惑,那先就从这个跑的流程看起吧。

首先肯定是在浏览器打开index.html的,然后在index.html中调用脚本方法egret.runEgret();

runEgret在EgretEntry中声明了,但是实现却是根据不同平台实现的,分为EgretWeb和EgretNative两种,EgretWeb是跑在原生浏览器上,EgretNative是跑在原生APP和Runtime上的。

那就有人要疑问了,这是怎样判断使用EgretWeb还是EgretNative呢?

本着一探到底的精神,我新建一个空项目,然后分别用web方式和native方式打包

首先观察web打包后的目录

2d45b0089c2a7e653ef1fbdd713219e7.gif

ecaa331e-1f40-4f78-9109-7bc28c02da55.png (2.38 KB, 下载次数: 9)

2016-1-21 23:01 上传

发现和我们调试的目录是差不多的,打开index.html文件

2d45b0089c2a7e653ef1fbdd713219e7.gif

2f154b75-486b-4034-8ed0-c48b2c0b83bd.png (17.42 KB, 下载次数: 9)

2016-1-21 23:01 上传

发现里面引用的是egret.web.min.js,那么看名字应该就能猜到肯定用的是EgretWeb这个类来实现的runEgret方法了,至于怎么实现的,就不在这篇文章的讨论范围内

看完了web打包方式,再来窥探一下native方式的实现,理论上应该是一样的,都是引用一个打包后的js来实现runEgret方法的,下面是native打包后的目录

2d45b0089c2a7e653ef1fbdd713219e7.gif

8f8a755e-02fe-46ec-965d-6008f78a2051.png (1.93 KB, 下载次数: 10)

2016-1-21 23:01 上传

咦,和web方式的目录结构不一样耶

不急不急,看到.zip压缩包没,解压之

2d45b0089c2a7e653ef1fbdd713219e7.gif

365111e7-aa17-43e1-abb9-7cee350756cc.png (2.08 KB, 下载次数: 10)

2016-1-21 23:01 上传

发现还是没有index.html,但是有launcher文件夹,在调试版本下,index.html是放在launcher文件夹下的,那我们打开launcher看看

2d45b0089c2a7e653ef1fbdd713219e7.gif

26ea5a8c-2718-4777-b4d1-302e8e24f008.png (2.02 KB, 下载次数: 10)

2016-1-21 23:01 上传

还是没有,怎么破,不急不急,打开native_require.js会发现

2d45b0089c2a7e653ef1fbdd713219e7.gif

514374a0-d946-4596-8b1f-42bf8c5a4ca2.png (10.37 KB, 下载次数: 10)

2016-1-21 23:01 上传

果然还是引用的js文件,红红火火恍恍惚惚哈哈哈哈

相信大部分人都是搞web版的,所以我们就以EgretWeb来讲解

下面是EgretWeb中runEgret方法是实现代码[mw_shl_code=javascript,true] /**

* @private

* 网页加载完成,实例化页面中定义的Egretsys标签

*/

function runEgret():void {

if (isRunning) {

return;

}

isRunning = true;

var ticker = egret.sys.$ticker;

startTicker(ticker);

var surfaceFactory = new CanvasFactory();

sys.surfaceFactory = surfaceFactory;

if (!egret.sys.screenAdapter) {

egret.sys.screenAdapter = new egret.sys.ScreenAdapter();

}

var list = document.querySelectorAll(".egret-player");

var length = list.length;

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

var container = list;

var player = new WebPlayer(container);

container["egret-player"] = player;

}

}[/mw_shl_code]简单来讲就是,初始化ticker,初始化canvas工厂,初始化屏幕适配器,从index.html中的css获取到egret-player实例

在获取到player示例后,新建WebPlayer并赋值给该实例

从index.html中可以看出来这个egret-player是个div元素

我们再调到WebPlayer类中来看

[mw_shl_code=javascript,true]private init(container:HTMLDivElement):void {

var option = this.readOption(container);

var stage = new egret.Stage();

stage.$screen = this;

stage.$scaleMode = option.scaleMode;

stage.$orientation = option.orientation;

stage.$maxTouches = option.maxTouches;

stage.frameRate = option.frameRate;

stage.textureScaleFactor = option.textureScaleFactor;

var surface = egret.sys.surfaceFactory.create();

var canvas = surface;

this.attachCanvas(container, canvas);

var webTouch = new WebTouchHandler(stage, canvas);

var player = new egret.sys.Player(surface.renderContext, stage, option.entryClassName);

var webHide = new egret.web.WebHideHandler(stage);

var webInput = new HTMLInput();

player.showPaintRect(option.showPaintRect);

if (option.showFPS || option.showLog) {

player.displayFPS(option.showFPS, option.showLog, option.logFilter, option.fpsStyles);

}

this.playerOption = option;

this.container = container;

this.canvas = canvas;

this.stage = stage;

this.player = player;

this.webTouchHandler = webTouch;

this.webInput = webInput;

this.webHide = webHide;

egret.web.$cacheTextAdapter(webInput, stage, container, canvas);

this.updateScreenSize();

this.updateMaxTouches();

player.start();

}[/mw_shl_code]

在初始化方法中依次解读,首先将传进来的container(div)所带的参数用readOption方法解析出来,然后新建egret.Stage,新建一个canvas,将新建的canvas放到container(div)里面,然后将egret.Stage和canvas放到WebTouchHandler一起管理,众所周知,egret是在canvas上面不断的绘制内容实现渲染的,不过具体怎么实现的,我们暂且不讨论,不过在这个类里面就可以发现canvas已经和我们的stage整合在一起了

在这段代码的最后,会发现player运行了一个start方法,那么我们进入这个方法看看

[mw_shl_code=javascript,true]/**

* @private

* 启动播放器

*/

public start():void {

if (this.isPlaying || !this.stage) {

return;

}

$TempStage = $TempStage || this.stage;

this.isPlaying = true;

if (!this.root) {

this.initialize();

}

$ticker.$addPlayer(this);

}

/**

* @private

*

*/

private initialize():void {

var rootClass;

if (this.entryClassName) {

rootClass = egret.getDefinitionByName(this.entryClassName);

}

if (rootClass) {

var rootContainer:any = new rootClass();

this.root = rootContainer;

if (rootContainer instanceof egret.DisplayObject) {

this.stage.addChild(rootContainer);

}

else {

DEBUG && $error(1002, this.entryClassName);

}

}

else {

DEBUG && $error(1001, this.entryClassName);

}

}[/mw_shl_code]

注释也说明了,这是启动播放器,看代码很明显,初始化后,我们通过反射entryClassName实例化,然后将rootContainer加到stage上面

而这个entryClassName是怎么来的呢,倒回去看代码

var player = new egret.sys.Player(surface.renderContext, stage, option.entryClassName);

option.entryClassName = container.getAttribute("data-entry-class");

在初始化player的时候通过WebPlayer中的option配置穿过来的,而这个option配置又是在初始化WebPlayer的时候赋值的,并且这个赋值是通过传进浏览器的参数来赋值的,在来看看index.html

[mw_shl_code=html,true]

data-entry-class="Main"

data-orientation="auto"

data-scale-mode="showAll"

data-frame-rate="30"

data-content-width="480"

data-content-height="800"

data-show-paint-rect="false"

data-multi-fingered="2"

data-show-fps="false" data-show-log="false"

data-log-filter="" data-show-fps-style="x:0,y:0,size:30,textColor:0x00c200,bgAlpha:0.9">

[/mw_shl_code]嘟嘟噜,发现里面写的参数是Main,这样就理顺了,成功实例化Main并加到舞台上了,接下来就进入游戏了~

index.html[egret.runEgret]->EgretEntry[runEgret]->EgretWeb[runEgret]->WebPlayer[init]->WebPlayer[start]->Player[start]->Player[initialize]->Main

顺便说一下,由于本人比较懒,这系列文章会心血来潮的更新,可能明天更一篇,也可能十天半个月都没反应,啦啦啦

ps:闹了个qq群,有兴趣的加进来一起讨论游戏制作啊,群号:534186107

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐