白鹭php源码,egret 2D引擎源码分析(二) 创建播放器
本帖最后由 fightingcat 于 2016-7-16 00:26 编辑
上一篇讲到了引擎的入口runEgret为每一个播放器标签(就是index.html中看到的那个
之前web.WebPlayer初始化时调用了sys.Player的start方法:
[mw_shl_code=actionscript3,true]
/**
* @private
* 启动播放器
*/
public start():void {
/// ……
if (!this.root) {
this.initialize();
}
$ticker.$addPlayer(this);
}
[/mw_shl_code]
root声明的类型是DisplayObject,如果root未设置,就调用initialize初始化:
[mw_shl_code=actionscript3,true]
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);
}
DEBUG && $error(1002, this.entryClassName);
}
}
else {
DEBUG && $error(1001, this.entryClassName);
}
}
[/mw_shl_code]
这里就是根据index.html中播放器标签的data-entry-class属性指定的类名获取入口类,创建一个对象并作为sys.Player的root节点,然后加入stage的子节点中。
初始化完后调用了$ticker.$addPlayer(this)注册并运行播放器。这里再一次用到了sys.$ticker,前面说过它是sys.SystemTicker的单例。事实上除了驱动sys.Player,sys.SystemTicker管理了所有需要循环更新的逻辑,以及广播ENTERFRAME事件,无论是egret.setTimeout还是Tween都使用了sys.SystemTicker来注册每帧更新事件。
源码位于 egret/player/SystemTicker.ts 中:
[mw_shl_code=actionscript3,true]
/**
* @private
* 注册一个播放器实例并运行
*/
$addPlayer(player
layer):void {
if (this.playerList.indexOf(player) != -1) {
return;
}
if (DEBUG) {
egret_stages.push(player.stage);
}
this.playerList = this.playerList.concat();
this.playerList.push(player);
}
[/mw_shl_code]
只是把sys.Player加入到列表中(不知为何用concat复制了个新的列表),那么sys.SystemTicker是如何驱动sys.Player运行的呢?还记得前面第一次用到$ticker是在引擎的入口runEgret()里吧,其中启动了一个循环不断调用$ticker.update,所以接下来看sys.SystemTicker的update方法:
[mw_shl_code=actionscript3,true]
public update():void {
var t1 = egret.getTimer();
var timeStamp = egret.getTimer();
for (var i = 0; i < this.callBackList.length; i++) {
if (this.callBackList.call(this.thisObjectList, timeStamp)) {
$requestRenderingFlag = true;
}
}
/// 接下
[/mw_shl_code]
这里遍历了一个callBackList并执行其中的回调函数,这个列表就是除了播放器外,其他逻辑注册的更新事件(见$startTick方法)。如果回调函数返回true,则表示需要立即触发渲染,$requestRenderingFlag是egret.sys命名空间下的公共变量,控制后面是否执行渲染逻辑。(code review技巧:在wing3.x或者vscode中选中一个符号(变量、属性、方法或类)并按shift+F12可以查看使用到这个符号的代码,可以自己看一下都有哪些功能注册了这个事件回调。)
[mw_shl_code=actionscript3,true]
/// 接上
this.lastCount -= 1000;
var t2 = egret.getTimer();
if (this.lastCount > 0) {
if ($requestRenderingFlag) {
this.render(false, this.costEnterFrame + t2 - t1);
}
return;
}
this.lastCount += this.frameInterval;
this.render(true, this.costEnterFrame + t2 - t1);
var t3 = egret.getTimer();
this.broadcastEnterFrame();
var t4 = egret.getTimer();
this.costEnterFrame = t4 - t3;
}
[/mw_shl_code]
代码稍微简化了一下,去掉了一些不必要的局部变量(个人觉得这种优化有限却降低可读性)。
这里的变量命名不是很好,frameInterval是指以60帧为基准相对当前帧率的倍数(因为runEgret中的循环是以60帧为准的,这里相当于跳帧处理),lastCount是一个计数器,初始为frameInterval,每次减1,当大于0时说明需要跳帧,但如果$requestRenderingFlag为真就调用this.render方法主动渲染一次。否则(lastCount<=0),说明发生了跳帧,lastCount再加上frameInterval。为了消除误差,涉及的量都乘以了1000,所以这里lastCount是-1000而不是1,frameInterval也是大于1000的整数。大概这就是egret所谓的滑动跑道模型吧,其实并没有什么高深的……
再来看$render方法(省略了一些调试相关的代码):
[mw_shl_code=actionscript3,true]
$render(triggerByFrame: boolean, costTicker: number): void {
this.callLaters();
this.callLaterAsyncs();
var dirtyList = this.stage.$displayList.updateDirtyRegions();
var drawCalls = this.stage.$displayList.drawToSurface();
/// 调试相关
}
[/mw_shl_code]
这里先调用了两个方法:callLaters和callLaterAsyncs,作用就是执行egret/player/utils/callLater.ts中callLater和$callAsync注册的延迟回调,从实现上看这两个方法完全一样,除了后者注释为私有,可能是考虑语义上的区分。另外其中有释放和创建数组的操作,不过由于对象生命周期很短可能并不会影响性能。
后面两句看函数名就可以知道,分别是更新舞台显示列表的脏区域,以及绘制舞台显示列表到sys.RenderBuffer。之前跳过了sys.DisplayList,接下来就可以分析sys.DisplayList的实现了。
小结,egret引擎启动流程
引擎从runEgret函数开始启动,先启动一个60帧每秒的循环,并调用sys.$ticker.update(),sys.$ticker是sys.SystemTicker的单例对象,负责管理所有每帧回调。
然后遍历页面上所有拥有"egret-class"CSS类的标签,并为其创建web.WebPlayer。
web.WebPlayer初始化监听用户输入事件,创建Stage和sys.RenderBuffer(实际的实现是web.CanvasRenderBuffer或web.WebGLRenderBuffer)。
web.WebPlayer把创建的RenderBuffer的canvas加入播放器标签,并设置基本的CSS属性。
web.WebPlayer用上一步创建的Stage和sys.RenderBuffer创建sys.Player,并调用其start方法启动播放器。
sys.Player在start中初始化,根据传入的选项创建主类(通常是Main),设置为播放器的根节点,并加入舞台。
sys.Player在start中初始化完毕,调用 sys.SystemTicker(通过单例sys.$ticker)的$addPlayer方法注册播放器。
sys.SystemTicker在update中处理每帧更新回调,并通过滑动跑道的方式调用所有sys.Player实例的render方法。
sys.Player在render中执行延迟回调,更新Stage的显示列表的脏区域,绘制Stage的显示列表到sys.RenderBuffer。
以上就是egret 2D引擎(Web)从启动、创建播放器到驱动播放器更新和渲染的流程框架。下一篇开始分析显示列表是如何更新和渲染DisplayObject的。
白鹭php源码,egret 2D引擎源码分析(二) 创建播放器相关推荐
- 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇...
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- 【Android FFMPEG 开发】OpenSLES 播放音频 ( 创建引擎 | 输出混音设置 | 配置输入输出 | 创建播放器 | 获取播放/队列接口 | 回调函数 | 开始播放 | 激活回调 )
文章目录 I . FFMPEG 播放视频流程 II . OpenSLES 播放音频流程 III . OpenSLES 播放参考 Google 官方示例 IV . OpenSL ES 播放代码 ( 详细 ...
- ios网易云音乐源码、动画引擎源码等
iOS精选源码 自己维护的框架, 超级多功能 图片选择SDK:支持多选,相册选择,预览,网络图预览 一款可以简单实现长按拖拽重排的 UICellCollectionView Cell框... 动画引擎 ...
- 支持Unity引擎!Visbit推出Web VR播放器云服务
Visbit实现了VR视频云服务在移动端的全面覆盖. 据悉,Visbit网页端VR播放器基于Web VR开发,并推出VR开发引擎Unity的SDK.要知道,四大主流浏览器Chrome.Firefox. ...
- 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java杨佑川音乐播放器908v6
大部分步骤是 1.确定选题 选题的确定需要查阅大量的资料,要搞清楚自己大概想要研究的方向是什么.可以选择自己感兴趣的学科或者强势的学科进行研究,同时要多和毕业指导老师多交流,征求老师的意见和建议,最后 ...
- 明月浩空播放器php源码,【Emlog插件】明月浩空音乐播放器
[摘要] 资源简介:明月浩空-Html5浮窗音乐播放器是基于QQ音乐.酷狗音乐.网易云音乐等歌曲ID全自动解析的Html5音乐播放器程序依靠服务器强大的接口功能,只需要一个歌曲... 资源简介: 明月 ...
- Google原生输入法LatinIME引擎初始化流程分析(二)
引擎初始化首先是在Java层调用native的初始化方法,Java层调用如下: private void initPinyinEngine() {byte usr_dict[];usr_dict = ...
- 2022-10-24 ClickHouse 源码解析-查询引擎经典理论
ClickHouse 源码解析: 综述 ClickHouse 源码解析: MergeTree Write-Path ClickHouse 源码解析: MergeTree Read-Path Click ...
- Android视频直播源码开发直播平台、点播播放器哪家强?
Android视频直播源码开发直播平台.点播播放器哪家强? 最近在项目中要加入视频直播和点播功能,那么问题来了,我需要一个播放器来播放视频流,那该如何选择呢?除了原生的VideoView(VideoV ...
最新文章
- 不用Office自动化技术,给Word文档中填充赋值
- python基础知识点-Python入门基础知识点(基础语法介绍)
- Modular_exponentiation模幂运算
- 2.1 0/1分类问题-机器学习笔记-斯坦福吴恩达教授
- boost::fusion::find_if用法的测试程序
- getSerializableExtra
- 武汉.NET俱乐部12月活动图片及课件下载
- 何为领导力 —— 《Working Backwards》书评
- BCH码(BCH code)详细分析
- 如何在word中的图片上画圈标注_word文字下怎么画圈标记
- HTML5期末大作业:直播网站设计——仿在线媒体歪秀直播官网模板html源码(11个页面) HTML+CSS+JavaScript 期末作业HTML代码...
- Android_Provision
- 实现阿里云视频直播流程
- 说话人性别识别——语音检测初探
- java 获取流 丢失_java文件流数据丢失问题
- jdk14下载与安装教程(win10)超详细
- AVFI Carla安装踩坑记录
- 默哀STAND SILENTLY!
- dxf geojson 转换,如何将CAD(DWG)文件转换为GeoJSON?
- 锂电池的六个主要参数