DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> JavaScript綜合知識 >> 打灰機是怎樣煉成的
打灰機是怎樣煉成的
編輯: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條航線,性能就提升了10倍!!同理,對於敵機和玩家灰機的檢測也是如此處理。如此,性能提升20倍!!

  操作優化:

  實現玩家灰機的方向控制也是比較簡單的,檢測鍵盤事件的上下左右按鍵事件,對玩家灰機的x,y坐標做相應的增減即可。

  但是在游戲中我們會發現玩家灰機的移動很不流暢,如果把移動速度增大,則會出現一跳一跳的感覺,如果移動速度變小玩家灰機的移動卻很慢。這是因為鍵盤的事件響應頻率太慢,所以只要提高移動控制的頻率就可以解決這個問題了。類似上文所說的游戲循環,我們可以創建一個專門控制玩家灰機的移動的循環體,在循環體內不停檢測標志位direction的值,根據direction的控制玩家灰機的移動方向。而在鍵盤響應事件中依據玩家按下的鍵對direction賦予不同的值,其中direction的值0表示靜止,1表示向上移動,2表示向下移動,3表示向左移動,4表示向右移動。

  實現代碼如下:

鍵盤控制代碼
QQ截圖20131115124634

  現在玩家灰機的移動控制就流暢很多了。

  一款簡單的打灰機游戲就這樣煉成啦,最後我們再去打一把灰機吧。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved