《割繩子》HTML 5版背后的開發故事
啟示
在IE9中作為一個HTML5應用來運行,從原始的iOS源碼改寫而來。Cut the Rope 是一款人見人愛的小游戲。所以我們有了個點子,即通過使用HTML5將這款游戲放到網上以便讓更多的人能接觸到它。
為了做到這一點,微軟的IE團隊和ZeptoLab團隊(游戲的開發者)以及Pixel Lab的專家們合作以便將Cut the Rope 的網絡版本實現。最終效果要能將游戲毫不失真地翻譯成網絡版本,并且能展示出HTML5的強大功能:畫布提供的繪圖、基于瀏覽器的音頻和視頻、CSS3風格以及WOFF字體的個性。
51CTO推薦專題:HTML 5 下一代Web開發標準詳解
如果你想玩一下Cut the Rope 的HTML5版本,就去下面這個網址吧:www.cuttherope.ie.
我們覺得HTML5版本的游戲讓網絡更有趣了,同時,它也展示了IE的上一個版本因支持開放標準而顯示出的長處。因此,我們想要分享一些開發 Cut the Rope 過程中的技術細節,以便幫助構建你自己的HTML5站點,并最終為Windows 8 Store做準備!
從Objective-C到 JavaScript
在將Cut the Rope應用到一個新平臺上的時候,我們希望我們保留了這個游戲的獨特的物理特性、動作以及風格。所以,在開始的時候,我們想要改寫iOS版本(而不是重寫)。我們仔細分析了用Objective-C寫成的原始版本,發現工程量很大,并且很復雜。iOS版本包含大約15,000行代碼(不包括庫!)代碼中最復雜的部分是動作、動畫以及繪圖引擎。它們本身就很復雜,使事情變得更為復雜的是這三塊之間耦合度很高,并經過了大量優化。
這是個令人生畏的工作:要將這些代碼在瀏覽器上實現,而又不喪失原先的獨特個性以及很高的質量。為了完成這個工作,我們賭上了Javascript。
在過去,Javascript一直被人看做是速度很慢的語言。坦白講,這種說法在最初的確是對的。老的Javascript引擎是為處理簡單的“腳本”(scripting)類型的工作設計的(如它的名字所示)。然而,在現在,Javascript引擎已經經過大量優化了。整合進just-in-time等功能以后,Javascript執行速度已經可以接近底層代碼執行速度了。
除此以外,我們知道使用Javascript編程不同于——并且需要的思維方式也不同于——用編譯型語言編程。當我們將這個游戲從Objective-C改寫過來的時候,我們知道應該充分利用Javascript編程的不同以及優點。
一個明顯的例子是在Javascript中缺少structs。Structs是相關屬性的輕量級的聚合。使用Javascript對象來聚合一系列屬性是很容易的,但是這和使用一個合適的struct是很不同的。第一個不同是一旦structs被賦值給一個變量或則傳遞到一個函數的時候,它都會被復制。因此,一個使用如Objective-C這樣的編譯型語言編寫的函數可以修改以參數形式傳過來的struct的值,而又不改變原來調用函數中的值。即使是在同一個函數中,將一個不同的值賦給struct也會將值復制一遍。而Javascript對象,是通過引用傳遞的。所以一個函數修改了一個對象參數的時候,原調用函數也能看到這個變化。
一個用來模仿structs的簡單的方式是每當將Javascript對象作為賦值對象或者參數傳遞的對象時都創建一個副本對象。在底層語言(native languages)中,使用structs的開銷是很小的。但在Javascript中創建一個對象則會有很大開銷,因此我們要非常小心,減少創建對象的次數。特別是在賦值的時候,我們盡可能地復制單個屬性,而不是創建一整個新的對象實體。
另一個例子是Objective – C代碼庫面向對象的本質。與傳統的基于對象的繼承不同,JavaScript提供了基于原型屬性(Prototype property)的繼承。這是對基于對象的繼承的一個高度簡化的形式,與傳統的Objective – C這樣面向對象的語言不兼容。幸運的是,有各種各樣的類庫,可以幫助你寫的面向對象編程(OOP)風格的JavaScript代碼,我們使用的類庫是一個非常簡單的由John Ressig寫的。 (需要注意的是,ECMAScript5,最新版本的JavaScript的規范,也提供了對一些類的支持,但我們選擇不使用它,因為我們對該版本的語言不熟悉,而我們的開發進度非常緊張)。
除了將代碼從Objective-C改到Javascript,我們還需要將圖像代碼從OpenGL改到HTML5的Canvas API。總體上說,這一切都進行地很順利。Canvas是一個很快的渲染表面,特別是在一個API由硬件加速的瀏覽器中(比如IE9)。
一個使用帆布API完成的aliased lines來畫繩子的例子。令人驚訝地是,我們遇到了好幾個地方,都是Canvas比在移動版本Cut the Rope中使用的OpenGL ES提供了更多功能的。一個例子是畫anti-alias lines。在使用OpenGL畫anti-aliased lines的時候,需要將一條線鑲嵌到一個三角形地帶中,并且將末端的渾濁部分褪色以完成透明化。而在HTML5的canvas中,anti-aliasing lines的繪制是由line API自動完成的。這意味著我們實際上需要從OpenGL版本中去掉一些代碼。將OpenGL代碼中的三角形頂點數組解約掉可以提供更好性能。
最終,我們有幾乎15,000行代碼在瀏覽器中執行(它已經被最小化了,所以如果你在瀏覽器中查看源代碼的時候,你會看到少得多的代碼)。考慮到這么多代碼帶來的復雜性,Denis Morozov(ZeptoLab開發部門的總監,the Director of Development at ZeptoLab)在開始的時候問了一個問題:HTML5能給我們我們所需要的速度和性能嗎?
為了回答這個問題,我們創建了一個早期的“性能”里程碑,在這里,我們集中精力去得到游戲運行時難度最高部分的最小版本。也就是說,我們想要看一下繩子看起來是什么樣子的,以及我們是否能在瀏覽器中處理復雜的物理引擎。
Performance性能
項目開始以后三個星期,我們最終有了物理和繪圖引擎的基本部分,以及一個簡單的用于啟動動畫的計時器。現在,我們可以在游戲場景中呈現出一些繩索,一顆星星,以及一個Om Nom sprite。不錯的進步!第四周的時候,我們加入了一些基本的和鼠標的互動,這樣,我們就能真正開始玩游戲了。我們在開發的過程中一直都在測試性能,并且希望ZeptoLab的團隊能夠給我們一些反饋。
當我們把這些代碼和ZeptoLab分享的時候,他們對這些代碼在瀏覽器中的性能表現感到驚喜(尤其是游戲的速度和平滑度)。說句實話,我們一直都提著一口氣呢。我們希望Javascript能快點,因為物理計算非常復雜,并且有實時性要求。這是一個很好的例子,證明了人們過去認為Javascript很慢的觀點實際上是錯的。最新的Javascript引擎是非常快的。
在這個項目中,我們在IE9中預覽了游戲。當你加載了游戲的時候,IE9的Chakra JavaScript引擎在一個后臺線程中將代碼進行了預編譯——就像一個編譯器編譯Objective-C 或者 C++一樣。然后,它實時將編譯過的代碼(字節碼)發送給游戲線程去執行。執行速度幾乎和本地執行速度一樣。令人驚訝的是,這樣的性能是來自于Javascript引擎,我們不需要在代碼中做任何特殊處理。

項目早期幀率檢測結果(注意幀率上限是60FPS)我們在Javascript上打的賭成功了,因此,我們將注意力轉向了硬件和瀏覽器。由于IE的硬件加速堆棧以及我們在 Disney Tron和其他一些HTML5站點上積累的經驗,我們對于游戲在測試機器上的完美表現毫不擔心。我們很輕易地達到了上限60 FPS(幀/每秒)。但是,我們想要確認游戲在其他硬件和其他瀏覽器上也能表現得很好。下面是我們經過一些初步測試后所看到的結果。
根據測試數據,我們將30 FPS(幀/每秒)設置為最小閾值。當瀏覽器速度低于這個閾值的時候,我們將會通知用戶。他們仍然可以玩這個游戲,但是我們會通知他們在游戲中他們可能會感覺到一些遲緩現象。這確保了這個游戲能支持不同硬件和軟件,并且提供給玩家我們所能提供的最好體驗。
我們想要指出兩件事情。第一件事,這個游戲的現有版本在桌面PC機和Mac機上使用鼠標玩時效果是最好的。我們還沒有加入對觸屏輸入的只支持,但在未來的版本中,我們會考慮這一點。
第二件事,現有的Chrome版本(version 16)有一些已經為大家所知的和媒體播放相關的問題,使得Cut the Rope中的聲音飄忽不定。我們進行了深入調研,試圖用不同格式(包括WebM)重新編碼媒體文件,但是沒有找到一個合適的格式或者MIME配置或者其他任何方案來有效解決這個問題。這個問題看起來是瀏覽器的bugs以及已經為大家所知的問題。更重要的是,盡管聲音時斷時續,游戲玩起來還是非常有意思的。考慮到這一點,我們一方面可以說IE9的用戶能免費得到一個很棒的應用,另一方面,Chrome以及一些Firefox用戶可能會遇到一些聲音上的問題,但他們會注意到我們退回使用了一個flash插件來確保聲效和音樂都能正常工作。
工具
關于HTML5的一件很好的事情是你不需要學習一門新的語言來利用這項新技術的強大功能。如果你知道并且懂得Javascript,那么你就能實現一個現代瀏覽器所能實現的所有功能。你甚至可以創建一個像這個游戲一樣的你自己的游戲!
代碼編輯器以及開發環境

Visual Web Developer 2010 Express可以免費下載使用,是一款很棒的編輯器,即使是對有經驗的Web開發者來說也是如此。

分析器截圖,圖中內容是對Calc2PointBezier函數中花費的不合比例的時間(Calc2PointBezier函數是用來計算繩子每節的位置)。
有一些很好的免費工具,可以讓我們更容易地使用Javascript和HTML5。我們的大多數開發工作都是在Visual Web Developer 2010(“快捷”版本可以在這里免費獲得)中完成的。這是一個非常健壯的Web編輯器,帶有Javascript以及CSS自動完成功能。更好的一點是:它是免費的!我們在Windows7的IE9上完成了我們的大多數測試,并且我們也時不時在Firefox、Chrome、Safari以及IE10的開發者嘗鮮版。總體上說,主流瀏覽器對于我們所使用的HTML5的特性都有比較一致的實現。在大多數情況下,我們在IE9上測試通過的特性在其他地方也運行得一樣好。
清查我們的資源加載器(Resource Loader)!
Cut the Rope有一個非常獨特的細節化的視覺風格——有很多圖片、音頻和視頻,并且花費也很小。最終達到的效果就是這個游戲比一般的網站要大很多。綜合起來說,它大概有6MB(而一般的網站是200-300K)。這些多媒體資源要花費一段時間才能下載,而如果資源沒有下載到位,我們看不到網頁上的內容,我們是無法開始游戲的。在一個典型的網頁中,如果你缺掉了一兩幅圖,它仍然是可以運行的,但在HTML5的API(drawImage)中,如果圖像無法獲取的話,這一API就會崩潰。
為了解決這個問題,我們想要創建一個資源加載器,用來下載頁面所需要的所有內容,并且當下載完成后,給我們一個好的反饋。這一點小代碼能做很多很棒的事情:
1.它屏蔽了不同瀏覽器之間對下載處理的不同以及它們告知你進度的方式的不同。
2. 它能讓你決定事物下載的順序(你可能會想要先下載大文件,或者你想要在下載游戲圖形之前先下載所有菜單圖像)。
3.最終,它可以智能提醒你事物的到達,這樣就可以通知用戶進度情況,甚至可以開始部分游戲。
創建這些類型的庫是很難做好的。由于我們對于這些庫的效果感到十分滿意,因此我們想要分享我們的資源加載器的代碼給你。最終的成果形式是PxLoader,一個Javascript的資源加載器庫,你可以使用它為HTML5應用、游戲、站點制作預加載器。它是開源免費的。你可以從頁面頂端抓取它,或者點擊這里。
IE中的性能工具
另外一個在開發過程中不可或缺的工具是IE9中的Javascript分析器(JavaScript Profiler)。分析器能讓你發現你的代碼中的熱點以及瓶頸。在我們第一次做性能評估的時候,我們發現在一些機器上我們一直困在了20或者30幀/每秒,這使得我們幾乎要放棄了。
我們做了一些最初的代碼檢查,但是什么都沒有檢查出來。我們使用分析器加載了游戲,發現我們在satisfyConstraints()函數上花了太多時間。這個函數是用來計算有關繩子的一些物理性質的數字。我們用來改寫的Objective-C版的實現是用遞歸實現的,遞歸每加深一層,就會傳遞一個新的對象。
通過Microsoft的一些指導,我們決定將遞歸函數替換成一個“解開”的循環版本。結果是驚人的。我們在每一個瀏覽器中都看到了10倍以上的性能提升。坦白說,如果沒有IE9的分析器工具,我們永遠都不可能發現這一點。
下一步是什么?
九月,Microsoft展示了一個Windows8的開發者嘗鮮版。在這一聲明以后,HTML5將會更有趣,因為Metro風格的應用可以用好幾種開發工具集開發,包括HTML5。這意味著Web開發者可以將為Web所寫的代碼拿來很容易地無縫移植到Windows8中。為在線應用的投資將來可以在Windows Store中得到實實在在的回報。
事實上,只要再做一點點工作,我們就能將HTML5應用移植到Windows8的Metro風格應用中。可以在這篇博文中讀到關于 Cut the Rope以及它整合到Windows Store中的內容。
我們非常開心看到開發者使用HTML5構建的應用。你可以下載IE9并且可以在www.beautyoftheweb.com找到一些其他的很漂亮的站點,或者在dev.windows.com下載開發者嘗鮮版的Windows 8。
要保持關注,因為這只是一個開始……還會有更多驚喜的!
原文:http://www.webapptrend.com/2012/01/1477.html
【編輯推薦】