萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> 打灰機是怎樣煉成的

打灰機是怎樣煉成的

   游戲循環:

  每一個游戲都是由獲得用戶輸入,更新游戲狀態,處理AI,播放音樂,還有畫面顯示這些行為組成。游戲主循環就是用來處理這個行為序列的。

  所以首先我們最基本的就是創建一個游戲主循環。對於javascript來說,實現這個游戲循環只有setTimeout和setInterval 這兩個方法可選了。

  那到底是setTimeout好還是setInterval 好呢。其實毫無疑問的,setTimeout比較好。setTimeout是在設定的時間後執行一次指定方法,而setInterval是每隔一定的時間久執行指定方法。可能很多人會存在疑問,這樣不是setInterval更好嗎,直接就可以實現循環了,setTimeout還要用遞歸實現循環。沒錯,setInterval實現循環更簡單,但是卻不是更好。

  因為:

  無論是setTimeout還是setInterval,觸發時,如果當前進程不為空,都得去排隊等待執行,這一點上是無差異的。

  區別是,setTimeout只需排一次隊,setInterval則需要按照預設的間隔時間,每到時間點都去排一下。

  setInterval去排隊時,如果發現自己還在隊列中未執行,則會被drop掉。也就是說,同一個Interval,在隊列裡只會有一個。

  因為隊列機制,無論是setTimeout還是setInterval,第一次觸發時的時間,只會等於大於預設時間,不可能小於。

  對於setInterval來說,如果執行時間大於預設間隔時間,很可能導致連續執行,中間沒有時間間隔,這是很糟糕的,很可能會耗費大量cpu。

  所以對於動畫來說,如果單幀的執行時間大於間隔時間,用setTimeout比用setInterval更保險。

  於是利用setTimeout這樣實現了游戲循環:

1 setTimeout(function(){  2 //循環體 3  setTimeout(arguments.callee, 10);  4 },10);

  不過,真的這樣簡單嗎?要知道javascript是單線程的,當要處理的事務比較多時,setTimeout的執行時間根本得不到保證,這樣在不同性能的浏覽器上就會有不同的表現了。這時我們可以利用時間差來控制循環體的執行時間。

01 var _last = new Date().getTime(); 02    03 setTimeout(function(){ 04    05 var _now = new Date().getTime(); 06    07 if(_now - _last > delay){ 08    09 _last = _now; 10    11 //循環體… 12    13 } 14    15 setTimeout(arguments.callee, 10); 16    17 },10);

  這樣,循環體執行的時間間隔就比較精准了。

  游戲幀:

  游戲循環有了,現在我們要明確的就是每個循環裡要做些什麼了。這裡的每個循環就是我們所說的幀了。在我們的打灰機游戲裡每一幀要做的事情無非就是下面這些 :

  移動敵機

  移動子彈

  碰撞檢測

  游戲結束檢測

  補充敵機

  移動敵機和子彈只要在當前的位置上加上當前的速度變量就可以了,比較簡單。

  我重點說說做碰撞檢測。

  碰撞檢測:

  打灰機游戲裡的碰撞檢測主要是檢測子彈和敵機,敵機和玩家灰機的碰撞。在這裡我們只做簡單的矩形碰撞檢測。在dom的世界全是方方塊塊的東東,至於飛機的形狀,我想說 不要在意這些細節。要知道,我們是在用javascript做游戲,還得兼容該死的IE6,性能才是最重要的。忽略灰機的形狀,這樣碰撞檢測就簡單了,只要根據兩個dom元素的位置和長寬判斷是否有重疊就可以了。不過更簡單的是,直接使用YUI裡面的inRegion方法就可以了,哈哈。

  既然如此簡單,興高采烈的開始代碼了。開開心心的寫個for循環,對每一架敵機和子彈做碰撞檢測,然後對每一架敵機和玩家灰機做碰撞檢測。大功告成,迫不及待的運行觀看效果,然後小伙伴們都驚呆了!chrome下灰機機卡得一頓一頓的,而IE6直接罷工了有木有!我還是高估了javascript的性能,當務之急是對碰撞檢測的性能做個優化。

  性能優化:

  每一屏內有十幾架飛機,子彈和玩家灰機都分別和敵機做碰撞檢測,則每一幀內要做上百次碰撞檢測。如果只對可能發生碰撞的進行檢測,每一幀的碰撞檢測可以減少到十次以內。但是怎麼知道哪些灰機是可能發出碰撞的呢。如果敵機可以出現在任意的位置上,那肯定是沒辦法做到的。所以只好把敵機固定在不同的航線上。如下圖所示,

打灰機是怎樣煉成的  三聯

  把游戲區域根據敵機的寬度劃分成一條條固定的航線,敵機會隨機出現在其中的一條航線上。於是,用子彈的x坐標除以敵機的寬度計算出子彈所處的航線,子彈只要和它所處的航線上的敵機作碰撞檢測就可以了。

  如果整個游戲區域分成10條航線

copyright © 萬盛學電腦網 all rights reserved