白鹭php源码,看源码系列之从运行流程开始-Egret社区-教程文档-白鹭引擎-Egret Engine-免费开源HTML5游戏引擎 - Powered by Discuz!...
本帖最后由 scarlet 于 2016-1-21 23:15 编辑从一开始接触egret到使用大概有一年多了,记得14年6月份的时候,神经猫火的那段时间就玩过了,只是当时各方面支持不完善,就不了了之,去年2.0出来,就正式开搞了,算一算也快一年了,不过一直都是埋头用引擎,发现连引擎的原理好像都似懂非懂,所以现在从源码看起,让自己更了解引擎的原理。正所谓好记性不如烂笔头,我觉得自己看完还是要做做笔
本帖最后由 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打包后的目录
ecaa331e-1f40-4f78-9109-7bc28c02da55.png (2.38 KB, 下载次数: 9)
2016-1-21 23:01 上传
发现和我们调试的目录是差不多的,打开index.html文件
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打包后的目录
8f8a755e-02fe-46ec-965d-6008f78a2051.png (1.93 KB, 下载次数: 10)
2016-1-21 23:01 上传
咦,和web方式的目录结构不一样耶
不急不急,看到.zip压缩包没,解压之
365111e7-aa17-43e1-abb9-7cee350756cc.png (2.08 KB, 下载次数: 10)
2016-1-21 23:01 上传
发现还是没有index.html,但是有launcher文件夹,在调试版本下,index.html是放在launcher文件夹下的,那我们打开launcher看看
26ea5a8c-2718-4777-b4d1-302e8e24f008.png (2.02 KB, 下载次数: 10)
2016-1-21 23:01 上传
还是没有,怎么破,不急不急,打开native_require.js会发现
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">
index.html[egret.runEgret]->EgretEntry[runEgret]->EgretWeb[runEgret]->WebPlayer[init]->WebPlayer[start]->Player[start]->Player[initialize]->Main
顺便说一下,由于本人比较懒,这系列文章会心血来潮的更新,可能明天更一篇,也可能十天半个月都没反应,啦啦啦
ps:闹了个qq群,有兴趣的加进来一起讨论游戏制作啊,群号:534186107
更多推荐
所有评论(0)