偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

HTML5游戲引擎深度測(cè)評(píng)

移動(dòng)開(kāi)發(fā)
針對(duì)技術(shù)類產(chǎn)品對(duì)比,通常有多個(gè)維度進(jìn)行對(duì)比,不僅僅是技術(shù)層面,還有許多非技術(shù)層面的內(nèi)容會(huì)影響我們的使用結(jié)果。本文從如下幾個(gè)維度進(jìn)行多重對(duì)比。

最近看到網(wǎng)上一篇文章,標(biāo)題叫做《2016年 最火的 15 款 HTML5 游戲引擎》。目前針對(duì)HTML5游戲的解決方案已經(jīng)非常多,但誰(shuí)好誰(shuí)差卻沒(méi)有對(duì)比性資料。特意花了幾天時(shí)間,針對(duì)文章中出現(xiàn)的12款免費(fèi)開(kāi)源引擎做了一次相對(duì)完整的對(duì)比分析,希望能對(duì)大家有所幫助。

針對(duì)技術(shù)類產(chǎn)品對(duì)比,通常有多個(gè)維度進(jìn)行對(duì)比,不僅僅是技術(shù)層面,還有許多非技術(shù)層面的內(nèi)容會(huì)影響我們的使用結(jié)果。本文從如下幾個(gè)維度進(jìn)行多重對(duì)比。

  1. 2D與3D
  2. 編程語(yǔ)言
  3. 設(shè)計(jì)理念&功能
  4. 工作流
  5. 性能
  6. 學(xué)習(xí)資料
  7. 商業(yè)應(yīng)用

2D與3D、編程語(yǔ)言對(duì)比

2D與3D

游戲領(lǐng)域中,最直白的一種分類方法便是2D與3D的區(qū)分。通常我們都會(huì)認(rèn)為它們是游戲引擎領(lǐng)域兩類不同的產(chǎn)品。原文中提及的引擎確實(shí)是當(dāng)下最為流行的HTML5游戲引擎。很多引擎屬于2D、3D通吃類型,我們通過(guò)一個(gè)表格進(jìn)行對(duì)比。

編程語(yǔ)言

基于HTML5技術(shù)的游戲引擎,所需要的腳本必定是JavaScript,只有JavaScript腳本語(yǔ)言才能運(yùn)行于瀏覽器中。但目前市場(chǎng)上,出現(xiàn)了很多JavaScript代替品,例如TypeScript、CoffeeScript、LiveScript等等。不同語(yǔ)言直接的定位不同,語(yǔ)言哲學(xué)也不盡相同。一些游戲引擎在語(yǔ)言選擇上也頗有意思。

Engine 2D Render 3D Render JavaScript TypeScript
Three.js NO YES YES NO
Phaser YES NO YES YES
Pixi.js YES NO YES YES
Egret YES YES YES YES
enchant.js YES NO YES NO
craftyJS YES NO YES NO
Turbulenz YES YES YES YES
cocos2d-js YES NO YES NO
PlayCanvas NO YES YES NO
melonJS YES NO YES NO
Quintus YES NO YES NO
Hilo YES NO YES NO

結(jié)論

可以從表格中看出,下面三個(gè)引擎屬于2D和3D通吃類型。

  • Egret
  • Turbulenz
  • PlayCanvas

在Web游戲領(lǐng)域勝出的編程語(yǔ)言是JavaScript和TypeScript。但絕大部分HTML5游戲引擎還是采用JavaScript語(yǔ)言。只有4款引擎選擇支持TypeScript。

從當(dāng)前前端技術(shù)圈環(huán)境分析,未來(lái)可能很多前端框架或者引擎會(huì)推出響應(yīng)的TypeScript語(yǔ)言分支,從AngularJS宣布將使用TypeScript開(kāi)發(fā)開(kāi)始,TypeScript在很大程度上被前端認(rèn)可。不得不說(shuō)微軟在開(kāi)源圈這一仗打得漂亮。

設(shè)計(jì)理念&功能

架構(gòu)設(shè)計(jì)是一門(mén)大學(xué)問(wèn),對(duì)于開(kāi)源引擎架構(gòu)的設(shè)計(jì)模式主要取決于作者的程序哲學(xué)觀點(diǎn)和產(chǎn)品定位。將設(shè)計(jì)思路和功能放在一起對(duì)比討論,比單獨(dú)功能討論更有參考意義。一個(gè)引擎的功能并非越多越好,功能應(yīng)圍繞引擎定位而定,這樣的思路在一些引擎中體現(xiàn)尤為明顯,下面我們針對(duì)每個(gè)引擎一一分析。

Three.js

定位

Three.js項(xiàng)目創(chuàng)建時(shí)間是在2010年的4月24日,到目前位置,應(yīng)該算是比較老牌的開(kāi)源項(xiàng)目了。事實(shí)上Three.js定義并非一個(gè)游戲引擎。在Github主頁(yè)中,作者很明確的定義了Three.js的定位,叫做“JavaScript 3D library”。它僅僅是一個(gè)基于JavaScript語(yǔ)言的3D庫(kù)而已。當(dāng)然,你可以用它來(lái)做任何事情,無(wú)論是游戲,還是炫酷的3D展示。

設(shè)計(jì)理念

Three.js在設(shè)計(jì)之處希望創(chuàng)建一個(gè)非常輕量級(jí)的3D庫(kù),能夠幫助開(kāi)發(fā)者快速搭建基于HTML5的3D內(nèi)容。同時(shí),通過(guò)暴露簡(jiǎn)單的API,將3D內(nèi)容的開(kāi)發(fā)復(fù)雜性降至最低。

渲染環(huán)境上,Three.js支持WebGL和CCS3D兩種渲染模式。從當(dāng)前使用量和標(biāo)準(zhǔn)普及程度來(lái)做分析看,開(kāi)發(fā)者更加傾向于WebGL渲染方式。

功能

文本主要想對(duì)2D游戲引擎做深入分析,所有沒(méi)有對(duì)Three.js的功能與那些流行的3D引擎加以對(duì)比。

Pixi.js

定位

很多人第一眼看到Pixi.js官網(wǎng),都會(huì)不自覺(jué)的認(rèn)為這是一款游戲引擎。但在主頁(yè)中作者對(duì)于Pixi.js的定義為“2D WebGL renderer with canvas fallback”,翻譯為中文是一款依賴于canvas的WebGL渲染器。所以當(dāng)你看到Pixi.js提供了為數(shù)不多的功能時(shí),請(qǐng)不要驚訝,因?yàn)樗皇且豢钿秩酒鳌?/p>

設(shè)計(jì)理念

Pixi.js的設(shè)計(jì)理念很多程度來(lái)源于它的定位,只做渲染器,要把渲染功能做到最強(qiáng)。而這樣的定位,則會(huì)讓Pixi.js成為其他引擎的渲染內(nèi)核。你經(jīng)常能看到一些游戲引擎,或者產(chǎn)品都基于Pixi.js而開(kāi)發(fā)。

最求極致的渲染性能是Pixi.js的首要任務(wù),為了讓Pixi.js更加易于使用,作者在API設(shè)計(jì)上更加參考非常成熟的2D渲染架構(gòu) —— Flash,并且提供的API也盡量參考了ActionScript。

例如創(chuàng)建一個(gè)顯示對(duì)象,在Pixi.js中被封裝為 PIXI.Sprite。如果需要顯示圖像,借助 PIXI.PIXI.Texture紋理進(jìn)行渲染數(shù)據(jù)填充。最終設(shè)置顯示對(duì)象的坐標(biāo),代碼看起來(lái)就像下面這樣。

 

  1. var stage = new PIXI.Container(); var texture = PIXI.Texture.fromImage('bunny.jpg'); var bunny = new PIXI.Sprite(texture); bunny.position.x = 80; bunny.position.y = 60; stage.addChild(bunny); 

Pixi.js中的顯示架構(gòu)完全參考Flash設(shè)計(jì),所有顯示對(duì)象組合為一個(gè)樹(shù)狀數(shù)據(jù)結(jié)構(gòu),但內(nèi)部已針對(duì)WebGL渲染方式進(jìn)行過(guò)優(yōu)化,上層使用起來(lái)和Flash并無(wú)太大差別。

功能

游戲引擎中的功能,我們可以細(xì)分非常多分類,一篇文章無(wú)法講解所有分類細(xì)節(jié)講解明白。我將所有功能做了一個(gè)二級(jí)分類,方便分析。

Phaser

定位

刻意將Pixi.js放在前面分析,因?yàn)镻haser本身并沒(méi)有自己的渲染核心。就像Pixi.js的定位不一樣,Phaser的定位是 "Desktop and Mobile HTML5 game framework",中為稱之為“桌面與移動(dòng)端的HTML5游戲框架”。Phaser并不把自己定義為Engine,而是框架。所以,當(dāng)你看到Phaser的功能設(shè)計(jì)和它的渲染內(nèi)核時(shí)就不會(huì)經(jīng)驗(yàn)了。

設(shè)計(jì)理念

因?yàn)閷⒆约憾ㄎ粸橛螒蚩蚣?,所以Phaser在游戲功能方面顯得相當(dāng)全面,你能想得到的絕大部分功能Phaser已經(jīng)替你實(shí)現(xiàn)了。在渲染方面,Phaser并沒(méi)有自己的渲染內(nèi)核,而是直接引用了Pixi.js。這確實(shí)是個(gè)明智之舉,因?yàn)镻ixi.js在渲染性能方面非常強(qiáng)悍。前面已經(jīng)提及編程語(yǔ)言,游戲開(kāi)發(fā)本身邏輯復(fù)雜,算法較多,Phaser提供對(duì)TypeScript的支持也是非常明知的。

架構(gòu)方面,Phaser進(jìn)行非常多的高度封裝。就顯示部分而言,如果你使用過(guò)Pixi.js就是發(fā)現(xiàn),設(shè)計(jì)思路本身差別不大,但API使用起來(lái)則方便很多。Phaser為一準(zhǔn)備好了游戲所需要的一切。當(dāng)我們像創(chuàng)建一個(gè)游戲界面時(shí),可以在Phaser初始化時(shí)針對(duì)不同階段進(jìn)行定制。

 

  1. var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update }); 

正向上面這行代碼,Phaser為我們定義了 preload 、 create 、 update 等方法,使用時(shí)只需要填寫(xiě)callback函數(shù)即可。在資源加載時(shí),Phaser會(huì)為你調(diào)用 preload 回調(diào)。 當(dāng)畫(huà)面刷新時(shí),可以調(diào)用 update 回調(diào)。

其他方面,信號(hào)和插件系統(tǒng)算是Phaser的最大特色了。

功能

Phaser功能眾多,但絕大部分應(yīng)用其他第三方作為實(shí)現(xiàn)。

Egret

定位

Egret算是HTML5游戲引擎中的新起之秀,其定位已不單純?yōu)镠TML5游戲引擎。官方將其定位為“游戲解決方案”,同時(shí)也并未過(guò)多提及HTML5。究其原因在于Egret不僅僅提供了一個(gè)基于HTML5技術(shù)的游戲引擎,更是提供了原生打包工具和眾多周邊產(chǎn)品,使其成為“解決方案”。

設(shè)計(jì)理念

這里單獨(dú)分析Egret Engine這個(gè)產(chǎn)品,其語(yǔ)言使用TypeScript,有2D和3D版本。在架構(gòu)設(shè)計(jì)上,同Pixi.js一樣,參考了Flash成熟的2D架構(gòu)體系。API方面,也參考了ActionScript。不僅如此,由于TypeScript的緣故,在事件系統(tǒng)中,也仿照ActionScript實(shí)現(xiàn)了 addEventListener 這樣的事件注冊(cè)機(jī)制。

內(nèi)核方面,Egret Engine采用了模塊化的設(shè)計(jì)。這樣可以將不同的功能進(jìn)行解耦。更加有趣的是,F(xiàn)lash中引以為傲的自動(dòng)臟矩形技術(shù)在Egret Engine中也被實(shí)現(xiàn)。在canvas模式下,臟矩形會(huì)是渲染性能得到提升,比其他引擎更加有優(yōu)勢(shì)。

如果你會(huì)Flash,那么Egret Engine對(duì)你來(lái)說(shuō)不需要過(guò)多的學(xué)習(xí)即可上手。

功能

Egret Engine由于模塊化設(shè)計(jì)的原因,將不同功能放到了不同模塊中。這些模塊以庫(kù)的形式提供,下面表中是所有支持模塊的總和,但不含平臺(tái)API部分,例如微信API的封裝。

enchant.js

定位

enchant.js并非一個(gè)引擎,而是一個(gè)框架。同時(shí),enchant.js也不僅僅用于游戲,還可以用于app。

設(shè)計(jì)理念

鑒于支持游戲開(kāi)發(fā)和APP開(kāi)發(fā),這個(gè)框架必定會(huì)顧全一些東西,不能在游戲方面放開(kāi)手腳。架構(gòu)設(shè)計(jì)上,沒(méi)講所有的元素全部按照OOP方式設(shè)計(jì),內(nèi)部使用實(shí)踐驅(qū)動(dòng),并有效的結(jié)合了異步處理。游戲方面則僅僅對(duì)動(dòng)畫(huà)相關(guān)功能做了支持。enchant.js框架提供了一套插件機(jī)制,你可以將使用到的功能模塊作為插件注入到enchant.js框架中。

enchant.js還特意提供了一個(gè)在線的圖像庫(kù),方便開(kāi)發(fā)者免費(fèi)使用其中的素材。當(dāng)從游戲效果來(lái)看,以小游戲居多。

功能

enchant.js框架自身提供的功能非常有限,如果需要其他功能,必須自己擴(kuò)展或者尋找響應(yīng)的插件。

craftyJS

定位

craftyJS將自己定義為針對(duì)JavaScript游戲的框架。

設(shè)計(jì)理念

由于框架的定位,craftyJS在設(shè)計(jì)上提供了一些系統(tǒng)級(jí)別支持,例如將canvas和Dom兩種渲染方式封裝為同一套API,盡量小的文件體積,實(shí)體組件系統(tǒng),顯示對(duì)象封裝,碰撞檢測(cè),事件系統(tǒng),還有很多功能組件模塊。所有的模塊都依賴于實(shí)體組件系統(tǒng)的設(shè)計(jì)。

在實(shí)際測(cè)試中,craftyJS在API上的設(shè)計(jì)思路也是使用起來(lái)最為不舒服的一個(gè)。

功能

Turbulenz

定位

Turbulenz引擎實(shí)際上是為自己的游戲渠道中的游戲提供的游戲引擎。因?yàn)楹妥陨砬澜壎?,所以在引擎中提供了很多l(xiāng)ow level API。借助這些底層API,可以呼叫Turbulenz游戲渠道中的一些系統(tǒng)級(jí)別功能。

設(shè)計(jì)理念

由于Turbulenz引擎更多的為自己設(shè)計(jì),更多的提供runtime支持,從嚴(yán)格意義上將,Turbulenz引擎不算是純正的HTML5游戲引擎。為了滿足其自身渠道的需求,Turbulenz引擎力求增加更加完整的功能,同時(shí)提高其運(yùn)行性能。

功能

由于Turbulenz對(duì)很多功能做了擴(kuò)展,同時(shí)推出Low Level API和 High Level API。這里不再對(duì)其中龐雜的系統(tǒng)進(jìn)行功能分析,大家如果有興趣可以到其官網(wǎng)查看。

cocos2d-js

定位

cocos2d-js是喊著Cocos2D-X的金鑰匙出身的,它僅僅是Cocos2D-X的一個(gè)HTML5實(shí)現(xiàn)的分支。

設(shè)計(jì)理念

cocos2d-js和Cocos2D-X的設(shè)計(jì)理念相同,你能夠看到所有的API以及語(yǔ)法都完全參考Cocos2D-X。國(guó)內(nèi)對(duì)于Cocos2D-X已經(jīng)非常了解,這里就不做過(guò)多介紹。

功能

cocos2d-js的功能提供的相當(dāng)完整,你在游戲中需要的功能幾乎都能夠找到。

PlayCanvas

定位

PlayCanvas主要用于3D渲染,本文還是以2D討論為主,對(duì)PlayCanvas的分析就不做過(guò)多分析。

melonJS

定位

melonJS是一個(gè)輕量級(jí)的HTML5游戲框架,并且通過(guò)插件機(jī)制擴(kuò)展其功能。

設(shè)計(jì)理念

melonJS在所有的功能設(shè)計(jì)上都是輕量級(jí)的,你可以看到很多功能,并且在此基礎(chǔ)之上搭建你自己所需要的功能模塊。melonJS對(duì)于Tiled Map支持非常好,在兼容性方面也是melonJS關(guān)注的重點(diǎn)。

功能

Quintus

定位

Quintus將自己定位為簡(jiǎn)單好用的JavaScript游戲引擎,同時(shí)支持移動(dòng)和PC端。

設(shè)計(jì)理念

Quintus設(shè)計(jì)為模塊化和輕量化,盡量使用簡(jiǎn)潔友好的JavaScript語(yǔ)法。在JavaScript的API結(jié)構(gòu)設(shè)計(jì)中,盡量使用標(biāo)準(zhǔn)的OOP模式。Quintus還借助了jQuery,并通過(guò)jQuery插件實(shí)現(xiàn)事件和一個(gè)選擇器的語(yǔ)法。語(yǔ)言設(shè)計(jì)層面上Quintus沒(méi)有設(shè)計(jì)限制使用傳統(tǒng)的繼承,這使得其中得組件模型更加容易被復(fù)用。

功能

Quintus自身并不支持WebGL,同時(shí)提供的功能也較少,在Github中排名也很靠后。

Hilo

定位

Hilo這個(gè)引擎來(lái)源于阿里前端團(tuán)隊(duì),從官網(wǎng)的主頁(yè)上看,這個(gè)引擎的定位比較模糊。Hilo作為一個(gè)跨終端的互動(dòng)小游戲解決方案,同時(shí)有稱綜合解決方案。從它的演變來(lái)看,Hilo屬于阿里前端在實(shí)踐總總結(jié)出來(lái)的一套工具庫(kù)。整體引擎并非最初有計(jì)劃設(shè)計(jì)構(gòu)想。

設(shè)計(jì)理念

從Hilo支持的特性上看,Hilo的設(shè)計(jì)思路更加偏向與前端開(kāi)發(fā)者,而非游戲開(kāi)發(fā)者。Hilo提供了多種模塊范式的包裝版本,實(shí)際上在滿足不同前端開(kāi)發(fā)者習(xí)慣。這些特性完全是前端工程師所偏好的內(nèi)容,對(duì)于游戲來(lái)講,這些內(nèi)容可能優(yōu)先級(jí)并非最高,作為阿里內(nèi)部團(tuán)隊(duì)的常用引擎,對(duì)于阿里來(lái)說(shuō)應(yīng)該非常合適,應(yīng)用場(chǎng)景做簡(jiǎn)單營(yíng)銷互動(dòng)小游戲足以。

功能

Hilo功能相對(duì)比較簡(jiǎn)單,對(duì)于游戲開(kāi)發(fā)來(lái)說(shuō),缺失功能較多。

工作流

對(duì)團(tuán)隊(duì)開(kāi)發(fā)來(lái)講,工作流搭建是非常重要的,我個(gè)人比較看重這點(diǎn)。如果是小型團(tuán)隊(duì)或者個(gè)人開(kāi)發(fā)者可能對(duì)此需求并不大。當(dāng)項(xiàng)目規(guī)模變大時(shí),一個(gè)好的工作流會(huì)事半功倍。

因?yàn)橐娴墓δ懿煌?,所以涉及的工具也?huì)有所差異,這里就不再做表對(duì)比了。

Three.js

3D并不在本篇文章的討論范圍之內(nèi),同時(shí)Three.js也并非游戲引擎,不存在游戲開(kāi)發(fā)工作流一說(shuō)。這里簡(jiǎn)單介紹一下Three.js所提供的在線編輯器。

Three.js提供的在線編輯器應(yīng)該是基于Three.js開(kāi)發(fā)的,功能不多,但相當(dāng)小巧。

Pixi.js

Pixi.js作為一個(gè)渲染器,其工具支持也是相當(dāng)清爽,除了一個(gè)程序庫(kù)之外,沒(méi)有提供任何工具。

Phaser

Phaser和Pixi.js一樣,沒(méi)有提供任何工具支持,在其官網(wǎng)上只是推薦了兩個(gè)代碼編輯器。還提供了一個(gè)簡(jiǎn)單的在線代碼編輯器。

Egret

Egret提供的工具非常多,也復(fù)合其解決方案的定位。在Egret整個(gè)體系下你可以看到如下工具支撐。

Egret Wing:Egret出品的一個(gè)IDE編輯器。在提供代碼編輯功能的同時(shí),還內(nèi)置可視化的UI編輯器。與Egret Engine中的GUI、EUI框架配合使用。

ResDepot:這是個(gè)小工具,用來(lái)配置游戲資源加載表。如果游戲資源多的話,用這個(gè)小工具拖拽一下就完成了。

TextureMerger:一個(gè)紋理合并的小工具,功能有點(diǎn)像TexturePacker。

DragonBones Pro:針對(duì)Egret中骨骼動(dòng)畫(huà)解決方案提供的DragonBones動(dòng)畫(huà)編輯器。

Egret Inspector:一個(gè)基于Chrome瀏覽器的插件,可以針對(duì)Egret游戲進(jìn)行調(diào)試。

Egret iOS & Android Support:這兩個(gè)東西可以將你的HTML5游戲打包成原生APP。

還有一些其他的工具,但定位與游戲開(kāi)發(fā)不同,有興趣可以去它的官網(wǎng)看。

從上面的分析看出,Egret在工作流的支持上做的還是非常完成的,從Wing的代碼編寫(xiě),到ResDepot和TextureMerger的資源整合,再到Inspector調(diào)試,和原生打包。游戲開(kāi)發(fā)過(guò)程中的每個(gè)環(huán)節(jié)基本都有工具支撐。

enchant.js

enchant.js 沒(méi)有提供任何工具支撐,在官網(wǎng)中也沒(méi)有任何相關(guān)支持工具的介紹。

craftyJS

craftyJS也沒(méi)有提供任何工具支撐,僅僅是一個(gè)開(kāi)源代碼庫(kù)。

Turbulenz

Turbulenz在你下載的目錄中包含了很多工具,大部分與格式轉(zhuǎn)換相關(guān)。所有工具均為命令含小工具,沒(méi)有提供任何可視化操作軟件支持。

cocos2d-js

Cocos2d-js近年來(lái)變化很大,但對(duì)于JS這個(gè)分支的支持卻少之又少。前一段時(shí)間新出了一個(gè)工具叫做Cocos Creator。我沒(méi)有具體使用過(guò),但看截圖仿佛有Unity3D的影子。從介紹中看,應(yīng)該對(duì)游戲支持還是不錯(cuò)的,編輯方面目前還欠缺。

PlayCanvas

PlayCanvas也提供了一個(gè)在線編輯器,不過(guò)是針對(duì)它的3D功能。編輯器看上去和Three.js提供的在線編輯器份很相似。這里直接借用官方文檔中的截圖給大家看一下。

melonJS

melonJS除了源碼庫(kù)以外,也沒(méi)有提供任何工具支持。但在其官方主頁(yè)中,包含幾個(gè)其他編輯器的連接。比如著名的Tiled地圖編輯器等。

Quintus

Quintus沒(méi)有提供任何工具支撐。

Hilo

Hilo沒(méi)有提供任何工具支撐。

總結(jié)

結(jié)果并不出乎意料,對(duì)于開(kāi)源游戲引擎來(lái)講,維護(hù)庫(kù)就是耗費(fèi)作者很大一部分精力,更何況去制作編輯器之類的軟件產(chǎn)品。很多引擎都會(huì)依賴一些比較流行的第三方工具,例如Tiled、TexturePacker等等。雖然可以實(shí)現(xiàn)功能,但整個(gè)工作流搭配起來(lái)還是多多少少會(huì)有一些問(wèn)題。只有Egret和Cocos2D-js提供了相關(guān)可視化編輯工具。而這兩對(duì)于工作流的理解則完全不同。從產(chǎn)品中不難看出,Cocos2D-JS更像Unity3D,提供一個(gè)大而全的軟件給開(kāi)發(fā)者用。Egret則是什么角色用什么工具,將產(chǎn)品按照角色劃分,針對(duì)不同角色和開(kāi)發(fā)流程中的各個(gè)環(huán)節(jié)進(jìn)行產(chǎn)品設(shè)計(jì)。

相對(duì)來(lái)說(shuō),Egret的這種方式使得每個(gè)工具更加垂直,能夠做的功能也更加深入,不會(huì)讓工具顯得臃腫。而Cocos Creator則力求完整,一個(gè)軟件解決所有事情。

性能

性能測(cè)試上,我只針對(duì)2D游戲引擎做了一個(gè)渲染壓力測(cè)試。

測(cè)試內(nèi)容為同屏渲染對(duì)象數(shù)量相同的情況下進(jìn)行幀頻數(shù)據(jù)對(duì)比,為了保證測(cè)試的公平性,我使用同一臺(tái)電腦,相同版本的Chrome瀏覽器進(jìn)行測(cè)試,游戲場(chǎng)景尺寸均為800*600,顯示的圖片也為同一張。每個(gè)引擎進(jìn)行同屏5000、10000、20000個(gè)顯示對(duì)象渲染。

其中craftyjs引擎渲染出現(xiàn)問(wèn)題,這里不作數(shù)據(jù)對(duì)比。
Quintus引擎不支持WebGL渲染模式,因此這里頁(yè)不作數(shù)據(jù)對(duì)比。
Phaser渲染內(nèi)核使用Pixi.js,因此Phaser渲染數(shù)據(jù)參考Pixi.js結(jié)果。

所有引擎編寫(xiě)的代碼大致相同,開(kāi)始做for循環(huán),創(chuàng)建定量顯示對(duì)象,然后在循環(huán)中對(duì)每個(gè)顯示對(duì)象做旋轉(zhuǎn)操作。

測(cè)試代碼如下:

Pixi.js

 

  1. var renderer = PIXI.autoDetectRenderer(800, 600,{backgroundColor : 0x1099bb}); document.body.appendChild(renderer.view); var stage = new PIXI.Container(); var texture = PIXI.Texture.fromImage('bunny.jpg'); var tnum = 5000; console.log("render Object Number:",tnum); var bunnys = []; for(var i=0;i<tnum;i++) {     var bunny = new PIXI.Sprite(texture);     bunny.position.x = Math.random()*800;     bunny.position.y = Math.random()*600;     stage.addChild(bunny);     bunnys.push(bunny); } animate(); function animate() {     requestAnimationFrame(animate);      for(var i=0;i<tnum;i++)     {        bunnys[i].rotation += 0.1;     }     renderer.render(stage); } 

Egret

 

  1. class Main extends egret.DisplayObjectContainer {     public constructor() {         super();          this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);     }      private tnum:number = 100000;     private bunnys:egret.Bitmap[] = [];      private onAddToStage(event:egret.Event)      {         console.log("render Object Number:",this.tnum);         this.stage.dirtyRegionPolicy = egret.DirtyRegionPolicy.OFF;         RES.getResByUrl('resource/bunny.jpg',this.onComplete,this,RES.ResourceItem.TYPE_IMAGE);     }      private onComplete(event:any)     {         var img:egret.Texture = <egret.Texture>event;         for(var i:number=0;i<this.tnum;i++)         {             var bunny = new egret.Bitmap(img);             bunny.x = Math.random()*800;             bunny.y = Math.random()*600;             this.addChild(bunny);             this.bunnys.push(bunny);         }         this.addEventListener(egret.Event.ENTER_FRAME, this.animate,this);     }      private animate(evt:egret.Event)     {         for(var i:number=0;i<this.tnum;i++)         {             this.bunnys[i].rotation += 1;         }     }  } 

enchant.js

 

  1. enchant(); window.onload = function () {    var game = new Game(800, 600);     game.fps = 60;    game.preload('bunny.jpg');    game.onload = function() {     var tnum = 100000;     console.log("render Object Number:",tnum);     var bunnys = [];       var scene = new Scene();       game.pushScene(scene);       for(var i=0;i<tnum;i++)         {             var sprite = new Sprite(50, 50);             sprite.image = game.assets['bunny.jpg'];             sprite.x = Math.random()*800;             sprite.y = Math.random()*600;             scene.addChild(sprite);             bunnys.push(sprite);         }         game.addEventListener('enterframe', function() {           for(var i=0;i<tnum;i++)             {                bunnys[i].rotation += 1;             }         });    };    game.start(); }; 

Turbulenz

TurbulenzEngine = WebGLTurbulenzEngine.create({     canvas: document.getElementById("canvas") }); var graphicsDevice = TurbulenzEngine.createGraphicsDevice({}); var draw2D = Draw2D.create({     graphicsDevice: graphicsDevice });  var bgColor = [1.0, 1.0, 0.0, 1.0];   var tnum = 50000; console.log("render Object Number:", tnum); var bunnys = []; for (var i = 0; i < tnum; i++) {     var sprite = Draw2DSprite.create({         width: 50,         height: 50,         x: Math.random() * 800,         y: Math.random() * 600,         color: [1.0, 1.0, 1.0, 1.0],         rotation: Math.PI / 4     });      bunnys.push(sprite); }  var texture = graphicsDevice.createTexture({     src: "bunny2.jpg",     mipmaps: true,     onload: function (texture) {         if (texture) {             for (var i = 0; i < tnum; i++) {                 var sprite = bunnys[i];                 sprite.setTexture(texture);                 sprite.setTextureRectangle([0, 0, texture.width, texture.height]);             }          }     } });  var PI2 = Math.PI * 2; var rotateAngle = PI2 / 360; // 1 deg per frame  function update() {      if (graphicsDevice.beginFrame()) {         graphicsDevice.clear(bgColor, 1.0);          draw2D.begin();          for (var i = 0; i < tnum; i++) {             var sprite = bunnys[i];              sprite.rotation += rotateAngle;             sprite.rotation %= PI2; // Wrap rotation at PI * 2              draw2D.drawSprite(sprite);         }          draw2D.end();          graphicsDevice.endFrame();     } }  function render() {     var tnum = 5000;     console.log("render Object Number:", tnum);     for (var i = 0; i < tnum; i++) {         sprite.position.x = Math.random() * 800;         sprite.position.y = Math.random() * 600;     } }

cocos2d-js

 

  1. window.onload = function(){     cc.game.onStart = function(){         //load resources         cc.LoaderScene.preload(["bunny.jpg"], function () {             var tnum = 100000;               console.log("render Object Number:",tnum);               var bunnys = [];             var MyScene = cc.Scene.extend({                  onEnter:function () {                     this._super();                     var batchNode = cc.SpriteBatchNode.create("bunny.jpg");                     this.addChild(batchNode);                     for(var i=0;i<tnum;i++)                     {                       var sprite = cc.Sprite.create("bunny.jpg");                       sprite.setPosition((Math.random()*800), (Math.random()*600));                       batchNode.addChild(sprite);                       bunnys.push(sprite);                     }                     this.scheduleUpdate();                 },                 update:function () {                    for(var i=0;i<tnum;i++)                     {                       bunnys[i].setRotation(bunnys[i].getRotation()+1);                     }                     this.scheduleUpdate();                 }             });             cc.director.runScene(new MyScene());         }, this);     };     cc.game.run("gameCanvas"); }; 

melonJS

 

  1. var PlayScreen = me.ScreenObject.extend( {     onResetEvent: function() {         me.game.world.addChild(new me.ColorLayer("background", "#5E3F66", 0), 0);         for (var i = 0; i < 5000; i++) {             me.game.world.addChild(new Smilie(i), 3);         }     } });  var Smilie = me.Sprite.extend({     init : function (i) {         this._super(             me.Sprite,             "init",             [                 (-15).random(800),                 (-15).random(600),                 {                     image: me.loader.getImage(game.assets[0].name)                     ,width : 50                     ,height : 50                 }             ]         );         this.rotation = 0;         this.alwaysUpdate = true;     },      update : function () {         this.rotation += 3/180*Math.PI;         thisthis.angle = this.rotation ;         return true;     },}  ); 

Hilo

  1. function init(){     var stage = new Hilo.Stage({         renderType:'canvas',         container: gameContainer,         width: 800,         height: 600     });     var sum = 5000;     var bitmaps = [];     var ticker = new Hilo.Ticker();    ticker.addTick(stage);    ticker.start(true);      for(var i = 0; i < sum; i++) {             var bmp = new Hilo.Bitmap({             image: 'images/hero.jpg',             rect: [0, 0, 50, 50],             x: Math.random()*800,             y: Math.random()*600             }).addTo(stage);             bitmaps.push(bmp);     }      function animate() {         requestAnimationFrame(animate);         for(var i = 0; i < sum; i++) {                     bitmaps[i].rotation += 0.1;         }     }     animate(); } 

我的電腦配置如下:

最終測(cè)試結(jié)果

Engine 5000 Display 10000 Display 20000 Display
Pixi.js 60fps 60fps 60fps
Egret 60fps 45fps 24fps
enchant.js 7fps 4fps 2fps
Turbulenz 60fps 60fps 60fps
cocos2d-js 60fps 32fps 15fps
melonJS 4fps 崩潰 崩潰
Hilo 12fps 6fps 3fps

結(jié)論

按照上述測(cè)試方法,我們可以對(duì)引擎性能排名做一個(gè)大致排列:

第一名:Pixi.js 和 Turbulenz
第二名:Egret
第三名:Cocos2d-js
第四名:Hilo
第五名:enchant.js
第六名:melonJS

最后放出一張測(cè)試時(shí)效果圖

學(xué)習(xí)資料

通常情況下,我們都會(huì)選擇一個(gè)資料較全的產(chǎn)品進(jìn)行學(xué)習(xí)使用,畢竟使用過(guò)程中會(huì)遇到各種各樣的問(wèn)題?,F(xiàn)在游戲引擎的文檔,討論組等都已經(jīng)成為了產(chǎn)品標(biāo)配。下面這個(gè)表格就對(duì)各個(gè)引擎的這些“標(biāo)配”做一個(gè)對(duì)比。

Engine Document API Document examples forum IRC&Other Language
Three.js YES YES YES 第三方 YES EN
Phaser YES YES YES 第三方 YES EN
Pixi.js YES YES YES 第三方 YES EN
Egret YES YES YES YES YES CN
enchant.js YES YES NO NO NO JP EN
craftyJS YES YES NO 第三方 NO EN
Turbulenz YES YES YES 第三方 第三方 EN
cocos2d-js YES YES YES YES YES CN EN
PlayCanvas YES YES YES YES YES EN
melonJS YES YES YES NO YES EN
Quintus YES YES NO YES NO EN
Hilo YES YES YES NO NO CN

結(jié)論

從上面對(duì)比表格可以看出,絕大部分引擎在文檔教程方面做的還是比較深入的,但完成程度不同。大部分都為英文文檔,對(duì)于國(guó)內(nèi)的開(kāi)發(fā)者來(lái)說(shuō)可能學(xué)習(xí)起來(lái)成本略高。其中兩個(gè)支持中文的引擎Egret、Hilo均為國(guó)人產(chǎn)品,這兩款引擎在文檔方面,Egret做的相當(dāng)優(yōu)秀,開(kāi)發(fā)者可以從它的edn.egret.com中查閱大量中文資料。

在學(xué)習(xí)難度上,Egret算是最為簡(jiǎn)單的,無(wú)論從完整度還是中文普及度上。

商業(yè)應(yīng)用

這部分對(duì)比是在商業(yè)產(chǎn)品應(yīng)用中的占比情況。一個(gè)引擎被商業(yè)產(chǎn)品應(yīng)用廣泛的情況下,足以證明此引擎具備商業(yè)產(chǎn)品使用價(jià)值。通俗的講,別人能用這玩意做出游戲,你也能。所以針對(duì)這兩方面進(jìn)行一下粗略的分析。

我對(duì)國(guó)外的HTML5游戲市場(chǎng)完全不了解,這個(gè)市場(chǎng)分析的東西太大,不好做評(píng)價(jià)。就分析一下國(guó)內(nèi)的,簡(jiǎn)單看一下到底哪個(gè)引擎用的多。

我用了國(guó)內(nèi)比較火的HTML5游戲平臺(tái)新浪微博作為數(shù)據(jù)采樣基礎(chǔ),一個(gè)人實(shí)在精力有限,不可能做的完整。由于客戶端對(duì)游戲地址進(jìn)行了加密,無(wú)法直接獲取。所以用了一些調(diào)試工具來(lái)看游戲網(wǎng)頁(yè)的標(biāo)記,以此判斷游戲到底使用什么引擎制作。

最終統(tǒng)計(jì)結(jié)果如下:

游戲名稱 引擎 游戲名稱 引擎 游戲名稱 引擎
CEO養(yǎng)成計(jì)劃 純HTML5 全民把妹 Egret 鬼吹燈 laya
一夜成名 純HTML5 決斗西游 Egret 邊鋒斗地主 cocos
上吧主公(萌喵闖三國(guó)) 純HTML5 呆呆忍者村 cocos 少女戰(zhàn)機(jī) Egret
三國(guó)魂 Egret 全民穿越之宮 Egret 蟲(chóng)蟲(chóng)大戰(zhàn) createjs
傳世霸業(yè) cocos 召喚師學(xué)院 cocos 我欲封天H5 Egret
傳奇世界 Egret 全民狂戳 Egret 萌戰(zhàn)姬 Egret
全力游戲 Egret 全民魔魔噠 cocos 我們的萌萌 Egret
全員加速中 Egret 戰(zhàn)神 cocos 藥水英雄 cocos
全民宮斗 純HTML5 全民首富 純HTML5 愚公移山 Egret
坦克風(fēng)云 Egret 無(wú)限穿越 cocos 覺(jué)醒吧MT cocos
大主宰 cocos 星愿城市 cocos 悟空歸來(lái) – 西游神傳 Egret
大俠歸來(lái) Egret 深海保衛(wèi)戰(zhàn) Egret 美人心計(jì) Egret
大大大掌門(mén) Egret 泡泡奧特曼 Egret 德州撲克H5 Egret
天天賺錢(qián) Egret 暴走大亂斗 Egret 經(jīng)典瑪麗h5 Egret
小鳥(niǎo)情人OL 純HTML5 狂掛傳奇 Egret 少年,好功夫 Egret
少女H計(jì)劃 Egret 盜墓英雄 Egret 秘密魔法花園 cocos
少女H計(jì)劃2 Egret 神傳 Egret

一共找了50款游戲,如上面表格。50款引擎,使用純HTML5開(kāi)發(fā)的6款,使用Egret開(kāi)發(fā)的30款,Cocos2d-js的14款,laya的1款,createjs的1款。

統(tǒng)計(jì)結(jié)果如下:

不難看出,Egret 和 Cocos2D-js聯(lián)合瓜分了大部分市場(chǎng)。而Egret占比居然過(guò)半,達(dá)到58%。看來(lái)Egret在國(guó)內(nèi)HTML5游戲市場(chǎng)還是非常強(qiáng)悍的。

總結(jié)

  1. Three.js:作為老牌的3D庫(kù),它已經(jīng)有眾多案例,在PC多網(wǎng)頁(yè)3D中是目前不錯(cuò)的選擇。
  2. Phaser:文檔教程,和案例方面都很不錯(cuò),功能也算的上豐富。非常適合獨(dú)立游戲開(kāi)發(fā)和小團(tuán)隊(duì)使用。
  3. Pixi.js:作為渲染器,其渲染性能絕對(duì)是非常優(yōu)秀的,游戲功能方面支持很差,適合極客程序員把玩。
  4. Egret:性能不錯(cuò),在工作流方面支持非常優(yōu)秀,適應(yīng)中度和重度HTML5游戲開(kāi)發(fā),有較多商業(yè)項(xiàng)目驗(yàn)證,非常適合商業(yè)團(tuán)隊(duì)使用。
  5. enchant.js:性能偏差,不太推薦。
  6. craftyJS:文檔教程等方面不太完善,很難找到對(duì)應(yīng)技術(shù)支持,不推薦。
  7. Turbulenz:性能極佳,但捆綁其自身業(yè)務(wù),不太適合國(guó)內(nèi)市場(chǎng)。
  8. cocos2d-js:老牌引擎,其性能在排名中居中,工作流支持相對(duì)完整,推薦。
  9. PlayCanvas:重度3D游戲開(kāi)發(fā)引擎,本文不對(duì)3D做推薦。
  10. melonJS:性能不理想,不推薦。
  11. Quintus:不支持WebGL模式,性能較差,不推薦。
  12. Hilo:阿里前端團(tuán)隊(duì)作品,偏向于前端開(kāi)發(fā)工程師,與游戲?qū)I(yè)開(kāi)發(fā)距離較大,推薦做HTML5營(yíng)銷小交互的使用。

 

責(zé)任編輯:李英杰 來(lái)源: 簡(jiǎn)書(shū)
相關(guān)推薦

2015-07-08 16:38:10

Cocos游戲引擎

2013-03-06 15:05:44

移動(dòng)瀏覽器移動(dòng)游戲HTML5

2015-07-24 17:08:24

2014-12-30 17:13:51

HTML5

2013-10-21 15:24:49

html5游戲

2014-04-17 09:54:47

HTML5JavaScript

2015-07-10 10:27:21

Cocos游戲開(kāi)發(fā)引擎

2012-03-06 10:56:32

HTML 5

2013-06-24 14:55:30

HTML5

2011-12-09 20:25:16

HTML5

2015-06-26 11:51:26

HTML5JavaScript

2013-03-06 16:14:16

UCHTML5游戲引擎

2012-05-25 12:50:46

HTML5AppCan

2015-02-28 09:31:25

HTML5JavaScript

2016-04-18 16:58:17

游戲H5市場(chǎng)

2014-11-12 16:00:12

火舞游戲

2012-04-01 10:02:00

HTML5

2013-01-08 11:00:20

IBMdW

2012-05-03 14:29:53

HTML5

2014-09-24 15:50:05

騰訊X5Egret Runti
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)