egret随笔-egret浅入浅出

•不知道有多人跟笔者一样,喜欢学各种技术,但是都不精,但也有一两项算是精的。

  
  从踏上了egret游戏开发的道路,就不得不学习各种技术了,因为,要精通egret,首先必须要会TypeScript,其次是JavaScript,如果只是简单点的HTML5游戏,那么学这两样就可以了。

  如果,你想再对web页面美化一下,你就要学html标记语言还有css样式,这样,一款简单的单机游戏就可以上线了。

  如果,你还想加个分数统计、数据采集之类的功能,那你就必须会一门动态网站语言了,php、jsp、asp.net、nodejs-web、golang-web或者其他。

  如果,你还想做网络版的egret游戏,那么,你还要学一门网络服务器语言,当然,这个选择是更多了,几乎每种语言都可以,只要协议支持,比如node.js-socket.io就是很好的websocket框架。

  最后一个如果,如果,你想把html5游戏打包成apk或者ipa,那你有两种途径,一种是自己写个app,然后在app里面放一个WebView或者UIWebView,然后指向你的html5游戏发布地址。这种加壳技术最简单了,如果你还要调用一些特殊的本地api,那么,你可以选择一下完善点的框架,比如Cordova,里面集成了几乎所有的可调用的api接口供js调用。

  但是这种加壳技术有局限性,因为要依赖于一个webview,也就是要看游戏流不流畅,就要看系统分配给webview的资源多不多了,显然,一个webview在android系统上的资源真是不够多,而且,android系统的webview真是不敢恭维,用的的chrome内核的老版本,ios的UIWebView却是时刻紧跟safari的步伐。如果要解决这个问题,可以自己下载最新的chrome源码,然后编译到app中,或者先对其进行优化和删减。

  app打包的另一种途径,就是native打包了,这种打包机制和webview打包是不一样的,并不是一个webview就能搞定的,需要解决js解析和渲染、音频、网络、交互等所有的之前通过一个webview全部包装的功能,在egret里,这些都被叫做Context。

这里写个个人见解:egret并不只是一个html5框架,他实则是一个js框架,框架层面,他调用了上述所说的Context,只是在不同的设备环境上,实现了这些Context定义的接口标准,然后让js框架去调用。
设想,如果你手上有一只蓝屏的老款诺基亚,想在里面运行一个你用egret写的贪吃蛇(想当年笔者能玩好多分啊!),可以呀,只要你去实现了那几个Context,就可以了,最关键的是,你要把一款js解析引擎搞进去,当然,那时候的手机根本吃不消。
这样使得开发者可以充分得去利用egret来实现一下天马行空的创想!

  实现这些Context,工作量是很大的,幸好egret研发团队已经帮你全部解决了:

  • js解析引擎>egret采用的是google开源的V8引擎,自称是最快的js引擎,而egret早期采用的是mozilla的SpiderMonkey引擎,一样是很优秀的js引擎。
  • 渲染Context>渲染上下文肯定是用OpenGL了,在android和ios上都能流畅渲染。
  • 音频Context>直接调用系统的音频解决方案即可
  • 网络Context>直接调用系统的网络接口即可
  • 交互Context>需要调用android或者ios上的Touch事件
  • 其他实现

•到底哪家强

  到了这里,你肯定想问egret和业内上很火的Cocos2d-x到底哪个更好呢?那肯定不能说哪个更好,因为各有千秋。

  在渲染方面,虽然都采用OpenGL,但是cocos2d-x却比egret快,为什么呢?因为egret为了抽象出底层的Context,所以把很多东西都交给了js,Context只做了渲染,而cocos2d-x则从头到脚都是c++写的,你说哪个渲染更花时间呢!

  但是,对于as3开发者的笔者来说egret更加亲和,因为egret的各种机制基本上是仿照as3设计的,使得我很快就能从as3转到egret(我就用过一次Ts转As代码的工具,为了看看Ts和As的差异),而后都是直接编写ts代码,直接上手。

其实在接触egret之前我自己动手写过简单的html5框架,很简单的东西,实现了as3的Graphics,内部机制还引以为傲地取名为命令队列,后来看了别人的框架才知道别人早就这么写了。。。
后来接触过一个国人写的html5框架,基于canvas和dom两种渲染方式的
“在去年三月份,某人接到了某人的邮件,说有个很隐秘的大案子要不要参与”,当时egret群里看到了这句话。后来那人成了egret的大牛。

  但是,egret的开发流真心挺亲民的,周边产品挺多,强大的GUI工具-EgretWing是笔者最喜欢的了,用as3+ane写的,自身采用的是Dom自己写的FlexLite框架。还有其他产品比如:引擎管理器、vs开发插件、资源管理器、材质编辑器、粒子系统编辑器、As3转TS工具、Chrome Inspection插件、龙骨Falsh pro插件(龙骨官方出品)

   里面笔者未提及的就是egret-runtime,这是对现有webview的一个插件式优化,egret-runtime其实是把webview中渲染低下的部分用OpenGL来渲染了,这样能提高帧率从而提升用户体验。但是这也有弊端,就是机子发热严重,耗电很快,所以这个要开发者自己去权衡。

  设想如果现在主流的android浏览器app都内置了egret-runtime,那玩起egret游戏来说,是不是很爽啊,白鹭公司也是蛮拼的,已经谈了几家公司了,只要通过这些app打开egret游戏页面,都会使用runtime加速渲染。

runtimeindex

•最后一个如果

  博文开头说了那么多如果,当然,最后一个如果才是关键,egret在实现完Context后,封装成了Android项目模版和xcode项目模版,以便开发者做native打包app使用。这时候,你就需要会另外两门语言了:Java和Obejctive-c了,还有就是各自的开发框架:android和cocoa。

  笔者在native打包之前稍微学过点android开发,算是有点基础,能做一些简单的应用,但是对于oc开发,那真是一无所知了,于是便从头学起,在win8.1上装了个vm,虚拟了个mac os,然后开始搞oc开发,打包ipa是ios开发的同事教笔者的(公司不给陪苹果机嘛,只能这样啦,嘘!)。于是第一款游戏诞生了,Zombie Infect,现已现身Google Play,App Store还在排队(两周了居然还在排队),html5版还未上线,需要等公司的平台出来。

  

Zombie Infect的三端实现:android、html5、ios

  如果接第三方库呢,先把库引入项目,然后通过java或者oc去调用,那什么去调用java和oc呢,因为他们不知道什么时候要调用呀,那就是egret提供的ExternalInterface了,和as3的有点像。他就是js和native开发语言的桥梁了,通过他,我们就可以实现各种本地api的调用而是的游戏更加健全了。笔者封装了一遍扩展接口,现已实现

  • navigateToUrl:用浏览器打开网页,在android和ios上都适配了
  • closeApp:关闭app,android有效
  • showBanner:显示admob广告条
  • hideBanner:隐藏admob广告条
  • ShowInterstitial:显示admob插页广告
  • jumpApp:为了做应用推荐了,在android端会打开google play或者其他应用商店,如果提供了下载链接可以直接下载app到本地,ios端直接打开app store
  • share:facebook分享接口

  以上接口都是各种百度各种google才得到的答案啊,还要写java和oc,确实有点辛苦。

•吐槽一下

  然后再吐槽一下android版的项目模板,用的是eclipse项目,这没什么不对,但是,要接第三方库就不方便了呀,笔者接admob的时候,硬生生地放着Intellij Idea不用,而用eclipse完成开发,因为官方的教程里加入admob库是用eclipse为例的,idea的没教,然后只会android基础的笔者就不会了。官方没给Gradle编译的项目模板,还好现在笔者通过查阅古籍资料已经把eclipse项目转为Idea的项目了,编译也改为Gradle了,Gradle解决依赖确实很方便,已经投入使用,笔者将在下一篇博文里表述笔者的转化过程。

•开发经历和累积-小盆宇们坐正了

  真正投入egret游戏开发已经有半年多了,也有了自己一套项目模板了,不是用官方的egret create来创建项目,而是通过ctrl+c和ctrl+v来创建新项目了,适当的时候egret upgrade一下模板项目,项目模板里沉淀了一下工具类和一些对egret的扩展:

项目模板

Alien库

  egret游戏项目的构架可以随你的开发习惯来定,我个人是非常赞赏egret的gui框架的,Dom将as3版的FlexLite改成了egret版的,配合EgretWing做游戏UI,那真是非常舒服的一件事。

  所以,也决定了我的项目会用到gui模块,所以会先把gui模块编译到项目中:把{"name": "gui"}加入到egretProperties.json的modules节点中,然后运行命令egret build -e编译一次引擎。

  因为egret目前为止只提供了简单的功能,并没有Scene场景这一说(据说以后会有的),所以需要自己去添加实现,在我的项目模板中已经实现了SceneManager功能在AlienLib中,支持切换特效,也可以自己写切换特效,还支持场景资源组依赖,可以动态加载场景需要的资源组。对于本地存储,egret将html5的localStorage和native整合了,同一为egret.localStorage,这样就解决了本地存储的适配,笔者则在他的基础上再次做了一次小封装,在getItem和setItem的时候对key做了处理,因为html5的localStorage是和站点host挂钩的,如果同一个站里放了多个游戏,而都是用score这个key来存储的,那就乱套了。

  个人建议,游戏主体不要涉及gui的逻辑,游戏主体最好继承自egret.DisplayObjectContainer,我的习惯是一个class GameStage extends egret.DisplayObjectContainer{}类,然后所有游戏表现逻辑都在这个GameStage类中,再加一个GameModel类来处理数据逻辑,一个GameData用来存放一些游戏数据,一个GameConfig用来存放一些普通配置(配置不要用json了,比较死,建议用js来写动态配置,更加灵活,native打包也不会被修改,因为resource目录先的文件全是暴露的,不安全)、一些关卡配置或一些语言包配置,一个skins文件夹用来存放EgretWing的皮肤文件,一个Views文件夹存放所有gui的视图类,包括组件、弹出面板和场景。

  笔者的习惯是新建一个ScenePlay皮肤,在里面添加一个UIAsset,命名为gameStageContianer,写一个名为ScenePlay的类继承自SceneBaseclass ScenePlay extends alien.SceneBase {},然后重写他的createChildren():void方法,将gameStage实例放到UIAssetthis.gameStageContainer.source = this._gameStage = new GameStage(this.onGameResult.bind(this));,最后,通过事件或者callback来完成GameStage和ScenePlay之间的交互。

如果GameStage非要和GUI直接打交道,比如内外特效:在GameStage里的一个星星要飘到Gui的星星槽里,那只能通过坐标传递,把GameStage中星星的坐标给ScenePlay,让ScenePlay播放一遍飘动过程,记得把GameStage里的星星隐藏掉。

•Native Code - js通信

  如果你是用webView给游戏打包的,那么通信就用webView的js接口,比较简单的。

  如果你是用Support打包的,那么就要用到Egret提供的接口了。这个接口是历经重重磨难的,为什么呢?从第一版的一个ExternalInterface类,演变到了现在层层包装的版本,其实是一样的。据官方认识透露,做这么多调整是为了迎合一些第三方平台的胃口,这些第三方平台固执己见,坚持不改动自己的接口,所以只能egret来修改了。以上说的是android版的接口,ios版的一直没变,还是朴实无华的ExternalInterface类。

  目前,android版通信接口为直接调用EgretGameEngine的实例提供的方法,有四个:

  1. public void enableEgretRuntimeInterface(),用来启动通信接口,是必须的。
  2. public void setRuntimeInterface(String var1, final Object var2),用来添加接口,其中第一个参数为接口方法名,即js直接调用的方法名,第二个参数是一个Object实例,这个Object实例需要有一个callBack方法,下文会说明。
  3. public void setRuntimeInterfaceSet(HashMap var1),用途和2差不多,只是为了方便集中添加接口。
  4. public void callEgretInterface(final String var1, final String var2),调用js方法,第一个参数为接口方法名,第二参数为参数,参数仅支持文本。

  对于第二个方法中的Obectj实例,也是经历了很多变革。起初,这个参数类型并不是Object,而是IExternalInterface接口,是需要实现这个接口的类才行,实现这个接口需要实现一个void call(String args)的方法,这个方法就是js在调用java时唯一调用的方法,参数类型依然是String。后来为了迎合第三方平台,这个接口被去掉了,成了纯Object类即可,但是必须要有一个callback方法(b是小写的),egret内部用了反射来调用这个方法,坑爹的是,这个方法现在又改了,成了callBack(B是大写的),据透露是egret内部某程序员搞的,至此,这个方法已经没人改动了,那就这样吧。

•最后,我来介绍一下IDE,我只能介绍我用过IDE了,选择很多

  • sublime text:挺简洁的编辑器,很适合代码编写,但是我只是拿他来编写简单的代码,大项目涉及到各种变量跟踪、大纲查询、集成编译等
  • notepad++:在大学里的时候用过,当时来说是个好东西了,比notepad好至少,还能装插件,可以直接把代码通过ftp插件提交到服务器
  • Aptana:这个IDE估计很少人用过吧,他就是一个eclipse的插件,适合做web开发,前端和后端皆可,eclipse的编辑模式是我至今都爱不释手的。他还捆绑了很多实用插件,用起来确实很上手
  • Visual Studio:我个人很不喜欢,但做网站的时候也用过,egret开发者可以安装egret-vs插件,就可以更快捷地开发egret游戏了
  • WebStorm:如果说eclipse是高材生,那么webstorm就是很帅的高材生了,同位java开发的IDE,webstorm被jetbrain包装得如此帅气,各种爽翻了的插件
  • Intellij Idea:和webstorm一样都是jetbrain家族的ide,那还是在做as3页游开发时候用的IDE了,我就是从eclipse家族转到idea家族的,从eclipse转到idea,改了一些习惯,快捷键习惯。

  那么我推荐的WebStorm了,他自带了TypeScript的插件,还可以自定义File Watch,实时编译Ts为js。还有一个好处就是,他可以添加External Tools,就是添加外部工具,并且绑定了快捷键,就可以一键实现很多命令组了,比如笔者就“一键”实现了egret的编译:

  打开File>Settings>Tools>External Tools,就可以添加工具了,如图

添加一个Tools>

•在开发中不断地提高自己,累积开发经验,才是学习技术的快乐所在。

  

  浅出完毕,下课,走着!

 

2016/07/03添加:

  只怪笔者当初愚笨,觉得Egret Native的实现方式很精明,其实这中实现方式在笔者现在的项目里开始露出杂毛了,这个种底层抽象程度过高的方式,导致script code比重过高,而native code比重减少,导致运行效率跌落很多,项目做大了,同志们你们就知道了。所以笔者正在开始跳坑,试试跳进其他引擎的坑瞧瞧!

 

转载请注明原地址http://www.cnblogs.com/rockyf/p/analysis-of-egret.html

posted @ 2015-04-23 20:22  RockyF  阅读(13672)  评论(6编辑  收藏  举报