本文将分享如何用 JS 寫出一個 3D 賽車,我之前曾在技術交流會上也講過一次(這裡是當時用的 PPT),後來有同學回報說講得太深奧沒聽懂。其實 PPT 裡說的更多的是三維圖形的基礎知識,實作原理展現的稍微少一些,那麼本文将着重從實作原理這塊做一些補充。
先看賽車的示例:http://ucren.com/racing/,還是半成品狀态,很多功能沒有實作,不過目前也沒有後續的開發計劃。
準備工作:
1) 圖檔素材:圖檔素材是每一個網頁遊戲必不可少的,本遊戲中素材涉及到白雲、遠山、N 棵不同的樹、小車、時速表盤、時速表針以及其它一些背景圖檔等。為了實作延伸,這裡的白雲及遠山等圖檔素材一定要做成首尾相接看起來平滑的,中間不能出現交界痕迹,這樣的圖檔可以從網上找到素材,再用 PhotoShop 進行處理。
2) 矢量繪圖庫:矢量繪畫部分沒有必要自己從頭寫起,我們應該将關注點放在遊戲的業務邏輯部分,可以從網上找個自己用得順手的基礎庫,比如 excanvas、Raphael 等,如果不考慮浏覽器相容的話,也可以使用 HTML5 提供的 <canvas> 标簽。強力推薦 Raphael,Raphael 是一個全浏覽器監容的繪畫庫,她提供大部分常用基本圖形的繪制方法,以及支援通過 SVGPath 文法來描繪任意曲線,更甚的是,每一個圖形單元都對應一個 Raphael 對象,可以類似 JQuery 那樣的鍊式調用來對圖形單元進行操作,Raphael 的圖形渲染載體是浏覽器提供的原生 vml 或 svg,IE 下使用 vml,其它浏覽器使用 svg。
實作原理:
實際上賽車的實作過程中考慮了很多細節的問題,由于篇幅有限,這裡隻挑一些重點的來介紹。
1) 白雲及遠山:這兩個都是 <div> 的背景實作的,通過控制 <div> 樣式中的 backgroundPositionX 屬性來達到移動的目的,注意兩個特點:a、運動方向與小車行駛的方向相反(小車左拐時,雲和山向右移,反之則相反);b、由于白雲離觀察者的距離比遠山要遠,是以白雲運動的速度比山體要慢(本遊戲用的速度是 1:4)。在 IE6 下,變更 backgroundPosition 相關屬性的值會使背景圖檔重載,導緻界面上看起來閃爍,是以這裡要用 document.execCommand(“BackgroundImageCache”, false, true) 指令強制背景圖檔緩存。
2) 路面:路面最重要的構成是兩條貝賽爾曲線,貝塞爾曲線有幾個重要的參數——起點、控制點一、控制點二和終點,這樣的四個點即構成一條貝賽爾曲線。SVGPath 裡的 C 指令可以完成貝塞爾曲線的繪制。路面變換彎度是如何實作的呢?幸好 vml/svg 節點的 path 屬性是允許動态改變的,可以通過改變它的 path 來完成彎度的變化,這點 Raphael 庫提供了很大的便利。如果是 <canvas> 實作的話,需要不斷的重繪路面來達到目的。
3) 樹木:本遊戲中樹木是由 6 張圖檔随機産生的,它們由遠及近地運動來向玩家表達車子向前跑的狀态,運動是通過不斷改變樹木的坐标和大小實作的,這裡的坐标由路沿的兩條貝塞爾曲線來确定。樹木的運動有三個特點:a、離觀察者越遠的樹越小,是以運動使樹木不斷變大,同時也使相鄰樹木的間距變大;b、由于前面的過程,樹木的 y 坐标(top 值)不一定在逐漸增大,有時反而在減小;c、離觀察者近的樹,層次要位于離得遠的樹之上。
4) 車子:車子是由一張集合了 13 個可能出現的方向的圖檔組合而成(見上述圖檔素材部分),你可能會奇怪這樣的圖檔怎麼制作,其實很簡單,我是拿 3dsmax 軟體做成的,從網上找了一個 3d 車子模型,用 3dsmax 軟體改改樣子,并導出不同方向的圖檔,最終用 PhotoShop 合成。在網頁上,用這張圖檔做為一個 <div> 的背景,仍然是通過控制 <div> 樣式的 backgroundPositionX 屬性來達到車子變換方向的目的。本遊戲中車子在改變方向或位置的時候,将受到以下參數的影響:目前車速、人為加減速、自然減速(速度自然衰減)、被迫減速(碰擦路沿時)、彎道系數、左右方向鍵累積系數、離心力大小等,這些參數複合運算後的結果将決定車子目前應該處于的 x 坐标位置和方向。由于實作在不同的子產品中,這裡就不詳細說明這些運算了。
5) 時速表:時速表由表盤和表針組成,表盤是靜止的,表針是可以轉動的。轉動的原理是改變表針的 rotate 屬性,這點在 Raphael 庫也有也對應的方法實作,參見 Raphael 文檔中的 rotate 方法。為了更加逼真,指針加入了抖動政策,具體為:如果車子處于勻速狀态下,指針将在目前速度附近抖動,你可以将車子開滿 180km/h 看看效果。
6) 速度:這是本遊戲中最重要的參數之一,本遊戲中将速度量化為 0-1,1 為滿速,0 為靜止不動。速度參數将決定網頁上很多物件的移動:除了車子上述複雜過程外,還有白雲和遠山的位移速度、路面改變彎道的快慢程度、樹木運動的快慢、時速表指針旋轉的角度等。
關于實作原理就介紹到這裡,下面說說我原來的一些想法:
後續可以做的:
1) 小地圖:使路況與小地圖結合起來,模拟真實世界。
2) 起點和終點:這是一個賽車遊戲必備的。
3) 耗油:起跑時,油箱是滿的,在車子跑動過程中,結合速度、路況、玩家控制、阻力等因素來消耗汽油,在到達終點之前油用完就 Game Over,考驗玩家的駕駛水準。
4) 敵車:路上不可能隻有一個車子嘛。
5) 複雜路況:可以用草叢、沙地、小石頭、水坑等物體來複雜化路況,增加遊戲的難度和趣味性。
6) 路邊風景:結合小地圖,可以在路邊實作一些河流、建築物等,純樹木還是很單調的。
原文來自:http://stblog.baidu-tech.com/?p=1045