1. 程式人生 > >如何開發優秀的HTML5遊戲?-迪斯尼《尋找奧茲之路》遊戲技術詳解(一)

如何開發優秀的HTML5遊戲?-迪斯尼《尋找奧茲之路》遊戲技術詳解(一)

        前言

        迪斯尼《Find Your Way to OZ》這個貼近地氣的遊戲我在最新一期《程式設計師》雜誌的《從HTML5移動應用現狀談發展趨勢》這篇文章裡有所提及,它借用了近期上映的《魔境仙蹤》電影的設定(設定來自於經典故事《綠野仙蹤》,看過這個電影的同學們會深有感觸),構建了一個等同的巨集大遊戲世界。同時迪斯尼又和谷歌合作,把它作為Chrome瀏覽器效能和HTML5技術的一個show case。對於這樣一個使用了WebGL 3D、攝像頭、3D音效等多種先進技術、支援桌面和移動端、品質出色的HTML5遊戲,瞭解它背後的實現原理和技巧必然對於我們來說有著非常巨大的參考意義。


        這篇文章我早就想翻譯出來,幫助大家更好的瞭解HTML5在遊戲開發裡的應用和國外的應用情況,但是這篇文章實在太長,所以只能分次刊載,以饗讀者。

        此教程在我近期HTML5介紹的文章中難度可稱高階,適合有一定經驗的開發者閱讀和學習。

        介紹

        “尋找奧茲之路”是迪斯尼為谷歌Chrome帶來的全新體驗。它讓你在互動的旅程中穿越堪薩斯馬戲團,然後通過一個巨大的風暴到達奧茲王國。


        我們的目標是結合瀏覽器的技術能力,以建立一種充滿樂趣、身臨其境的體驗,使用者可以與電影之間形成一個強大的聯絡。

        這個遊戲的工作實在是太龐大,所以我們只能列出一些章節,把我們認為有趣的技術故事寫出來。教程的難度隨著進度會逐漸增加。

        我們有很多人努力工作來建立更好的體驗,但是太多無法一一列舉。請訪問該網站,體驗整個頁面下的完整故事。

        預覽

        在PC端《尋找奧茲之路》是一個豐富的身臨其境的世界。我們把3D和傳統的電影製作靈感結合起來,創造一個好幾層的接近現實的場景效果。其中最突出的技術是用Three.js引入WebGL,使用CSS3特性來定製著色器和DOM動畫元素。除此之外,getUserMedia API(WebRTC)增強了互動體驗,允許使用者直接從攝像頭新增自己的形象,以及WebAudio帶來了3D音效。

        但是這種技術體驗的神奇之處在於它們是如何融合為一體的。這也是面臨的主要挑戰之一:如何把視覺效果和互動元素融合在一起來建立一個一致的場景?這種視覺的複雜性非常難以管理:很難說清楚我們在任何一個時間需要開發什麼場景。

        為了解決視覺效果和優化這一問題,我們大量使用了一個控制面板,用於捕獲我們正在檢查的那個時間點的所有相關設定。在瀏覽器中可以實時修正場景中的一切,例如亮度,縱向深度,伽瑪線等等。任何人都可以在體驗中嘗試調整重要引數的值,參與並發現什麼效果最好。

        在分享我們的祕密之前,我要提醒你,它可能會導致崩潰。確保你沒有正在瀏覽什麼重要的東西,並且在訪問該網站的網址時新增?debug=on。等待網站載入,一旦你進入後按Ctrl+I鍵,會看到右手邊出現一個下拉選單。如果取消選中“退出相機路徑”選項,你可以使用A、W、S、D鍵和滑鼠在空間中自由的移動。


        我們不會詳述這裡的所有設定,但是我們鼓勵你試驗:按鍵顯示不同的場景中不同的設定。在最後的風暴場景中有一組額外的按鍵:Ctrl+A,可以切換播放的動畫。在這個場景中,如果你按Esc(退出滑鼠鎖定功能),再次按下Ctrl+I鍵可以進入風暴場景的特殊設定。看看四周,並且擷取一些像下面這樣的漂亮明信片。


        要做到這一點以確保其對我們的需求具有足夠的靈活性,我們採用了一個很棒的名為dat.gui的框架(可以在這裡看看過去關於如何使用它的教程)。它允許我們能夠迅速改變暴露給遊客的設定。

        有點像繪景

        許多經典的迪士尼電影和動畫建立場景意味著合併不同的層。有外景層、單元動畫層,以及物理設定層和通過玻璃繪畫獲得的頂層:這種技術稱為繪景

        在許多方面我們創造的體驗的結構是相似的,即使有些“層”遠遠超過了靜態的視覺效果。事實上,它們根據更為複雜的計算影響事物看起來的方式。然而,至少在大畫面的水平,我們處理檢視,將一個合成到另外一個之上合。在頂部,你看到一個UI層,其下是3D場景:它由不同的場景元件組成。

        頂部介面層使用DOM和CSS 3建立。事件通訊使用Backbone路由器+ onHashChange HTML5事件來控制哪塊區域響應動畫。(專案原始碼:/develop/coffee/router/Router.coffee)。

        教程:Sprite表和視網膜支援

        我們依賴一種有趣的優化技術,把多個介面層影象合併為一張單獨的PNG來減少伺服器請求。在這個專案中,介面由多於70 張的影象組成(不包括3D紋理),並且全部預載入以減少網站延​​遲。你可以在這裡看到最新的Sprite表

        下面是我們如何發揮Sprite表優勢的一些技巧,在視網膜裝置上如何使用它們,以及如何將介面儘可能設定的簡潔而整齊。

        建立Sprite表

        我們使用TexturePacker來建立任何你需要的Sprite表格式。在這種情況下,我們採用EaselJS,它非常整潔,並且可以用於建立動畫Sprite。

        使用生成的Sprite表

        一旦建立了Sprite表,你應該看到這樣的一個JSON檔案:

{
   "images": ["interface_2x.png"],
   "frames": [
       [2, 1837, 88, 130],
       [2, 2, 1472, 112],
       [1008, 774, 70, 68],
       [562, 1960, 86, 86],
       [473, 1960, 86, 86]
   ],

   "animations": {
       "allow_web":[0],
       "bottomheader":[1],
       "button_close":[2],
       "button_facebook":[3],
       "button_google":[4]
   },
}

        其中:

  •         images指向sprite表的地址
  •         frames是每個UI元素的座標[x, y, width, height]
  •         animations 是每項內容的名稱

        請注意,我們已經使用了高清影象來建立Sprite表,然後我們只需通過調整影象尺寸為一半來建立正常版本。

        融合一切

        現在,我們只需要一段Javascript程式碼來使用它。

var SSAsset = function (asset, div) {
  var css, x, y, w, h;

  // Divide the coordinates by 2 as retina devices have 2x density
  x = Math.round(asset.x / 2);
  y = Math.round(asset.y / 2);
  w = Math.round(asset.width / 2);
  h = Math.round(asset.height / 2);

  // Create an Object to store CSS attributes
  css = {
    width                : w,
    height               : h,
    'background-image'   : "url(" + asset.image_1x_url + ")",
    'background-size'    : "" + asset.fullSize[0] + "px " + asset.fullSize[1] + "px",
    'background-position': "-" + x + "px -" + y + "px"
  };

  // If retina devices

  if (window.devicePixelRatio === 2) {

    /*
    set -webkit-image-set
    for 1x and 2x
    All the calculations of X, Y, WIDTH and HEIGHT is taken care by the browser
    */

    css['background-image'] = "-webkit-image-set(url(" + asset.image_1x_url + ") 1x,";
    css['background-image'] += "url(" + asset.image_2x_url + ") 2x)";

  }

  // Set the CSS to the DIV
  div.css(css);
};

        這是你如何使用它的程式碼:

logo = new SSAsset(
{
  fullSize     : [1024, 1024],               // image 1x dimensions Array [x,y]
  x            : 1790,                       // asset x coordinate on SpriteSheet         
  y            : 603,                        // asset y coordinate on SpriteSheet
  width        : 122,                        // asset width
  height       : 150,                        // asset height
  image_1x_url : 'img/spritesheet_1x.png',   // background image 1x URL
  image_2x_url : 'img/spritesheet_2x.png'    // background image 2x URL
},$('#logo'));

        如果要多瞭解一些可變畫素密度,你可以看看Boris SMUS的這篇文章

        3D內容管道

        環境體驗建立在WebGL層之上。當你想到一個3D場景,最棘手的問題之一是要如何確保你從建模,動畫和特效這些領域都可以建立最富有表現潛力的內容。從許多方面來說,這個問題的核心是內容管道:用一個定好的程式從3D場景來建立內容。

        我們想創造一個令人振奮的世界,所以需要一個可靠的程序幫助3D藝術家來建立它。他們將需要給予他們的三維建模和動畫軟體儘可能多的表達自由,而我們將需要通過程式碼將它們呈現在螢幕上。

        我們在這類問題上已經工作了一段時間,因為過去每次我們建立了一個3D網站,所以發現之前使用工具的一些限制。後來我們創造了這個被稱為3D Librarian工具,正準備要把它應用到真正的工作上。

        這個工具有一些歷史:它最初是為了Flash誕生的,它會允許你把一個大的Maya場景作為一個單一的壓縮檔案為拆包執行時進行優化。這是最優的原因是因為它有效的把場景包裝為基本相同的資料結構,在渲染和動畫時進行操作。這樣在檔案載入時只需要做很少的解析。Flash中的解包速度非常快,因為檔案是AMF格式,Flash能夠原生​​解壓。在WebGL中使用相同的格式,需要CPU多做一些工作。事實上,我們不得不重新建立一個解壓資料JavaScript程式碼層,這基本上會將這些檔案解壓,並重新建立WebGL所需的資料結構。解壓整個3D場景是對CPU有一些負擔:解包遊戲的場景1在中高階機上需要約2秒鐘。所以為此我們在“場景設定”時間(實際上是場景出現之前)用Web Workers技術來實現,所以不會影響使用者的體驗。

        這個方便的工具可以匯入3D場景:模型、紋理和骨骼動畫。你可以建立一個單一的庫檔案,它稍後能被3D引擎所載入。

        不過我們曾經遇到一個問題,現在用WebGL來處理。因此,我們建立了一個特定的JavaScript層,使用3D庫來壓縮3D場景檔案,並把它們翻譯成正確的WebGL能理解的格式。

        教程:要有風

        在“尋找奧茲之路”中一個反覆出現的主題就是風。劇情的主線由弱到強的風所串起。

        狂歡節的第一個場景相對平靜。經歷各種場景,使用者逐漸體驗強風,最後來到最終的場景,風暴中。

        因此,重要的是提供一個身臨其境的風的效果。

        為了實現這種效果,我們在3個狂歡節的場景中填充比較軟的物件,例如帳篷和氣球。


        (待續)

        轉載請註明:來自蔣宇捷的部落格(http://blog.csdn.net/hfahe)