控制遊戲的速度 (轉)

worldblog發表於2007-12-02
控制遊戲的速度 (轉)[@more@]

  隨著速度的飛速增長,的執行速度越來越快。但這在某些情況下卻未必是件好事。遊戲在不同的機器上,或者在不同的環境下執行不能保持相同的恰當速度困擾著許多遊戲員。尤其有些RPG遊戲,在比較高檔的機器上執行,按一下鍵盤,遊戲中的主角便走的比飛還快。即使這沒有給玩家帶來麻煩,也是在挑剔的玩家眼中所不能容忍的。               

   也不是說一個遊戲必須在所有的機器上都必須保持相同幀數,即使是想實現也不切實際。其實只要保證遊戲角色運動的頻率差不多就可以了。馬上你就會想到以一定的頻率去控制遊戲裡的物體的運動。一個直接的想法是直接將控制放在時鐘中斷函式中。不過細想一下……別開玩笑了,這樣絕對不行。時鐘中斷函式不能太複雜,必須保證中斷函式的簡潔。除了這個,想想在保護下(現在的遊戲都是保護模式的)時鐘中斷函式所觸及的資料,函式都要鎖住,這會帶來多少問題!              

  所以比較現實的方法是做兩個計數器。一個放在時鐘中斷裡以固定頻率遞增,而另一個隨著每次遊戲迴圈遞增。前一個量表示到目前為止應當做完了遊戲迴圈的次數,它通常遞增速度應當大於前者;而後一個則是已經做完的遊戲迴圈的次數。在遊戲程式的主迴圈裡,我們將反覆比較這兩個量,如果實際做的遊戲迴圈次數落後了,就讓它繼續做,直到趕上應當做的數量。否則我們就應該馬上停止,這個時候可以等待或去做其它的事,比如顯示一幀圖片。為什麼選擇畫一幀圖片?部分原因是,這個工作通常比較慢,需要一段時間,這樣使得實際遊戲迴圈數量又落後於應當做的遊戲迴圈數量;另外還有部分原因是這個過程還包括了等待螢幕垂直回掃的過程,在這段時間裡,時鐘中斷函式也在以正確的頻率遞增計數器。當然,我們就不能在兩個計數器相等時馬上繼續處理了;而必須等到畫完了圖以後。但是當我們花完了圖,也可以清楚的知道需要做多少次遊戲迴圈來跟上應當做的數量。            

下面給出上述演算法的粗略的例子程式:
(引用 Grorge Foot 所著的 9.4.3 節的例子)

volatile int target_cycle; void target_incrementor() { target_cycle++; } END_OF_FUNCTION (target_incrementor); int actual_cycle; int end_game; void game_l() { LOCK_VARIABLE (target_cycle); LOCK_FUNCTION (target_incrementor); install_int_ex (target_incrementor,BPS_TO_TIMER(cycles_per_sec)); end_game = 0; actual_cycle = target_cycle = 0; /* 初始化 */ do { draw_one_frame(); /* 畫一幀圖 */ while (target_cycle > actual_cycle) /*如果實際的要做的落後*/ do_one_game_cycle(); /* 進行遊戲迴圈 */ } while (!end_game); }

draw_one_frame 畫一幀畫, 如果需要還要進行垂直回掃同步. do_one_game_cycle 為完成一個遊戲迴圈, 並累加 `actual_cycle'.
cycles_per_sec 變數儲存每秒鐘進行的目標遊戲迴圈的數量.
如果你用過ease.com/~cloudwu/text/allegro.htm">Allegro. 其他的應該沒什麼問題, 關於程式中涉及的Allegro函式,
請自行查閱

本文參考 George Foot 所著的
Section 9.4.3 Regulating game speed

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987366/,如需轉載,請註明出處,否則將追究法律責任。

相關文章