我們准備開始設計游戲內核。
通常,游戲和桌面Windows程序不同(掃雷等桌面游戲除外),它不能依賴消息驅動,因為游戲通常只有一個畫面,而且需要高速更新。因此,游戲只能靠時鐘驅動。大部分游戲都在一個時鐘驅動下定時渲染一幀畫面。此外,游戲需要接收用戶輸入,處理游戲事件(比如碰撞檢測等),可能還需要AI計算,這些任務都必須巧妙地在兩幅畫面切換的時間段裡處理完畢,因此,一個高效而靈活的調度器就是游戲進程的核心。
調度器由時鐘驅動器和任務管理器組成。
時鐘驅動器負責在需要的時候向調度器提供准確的虛擬時間,虛擬時間流逝時,游戲就運行,虛擬時間停止時,游戲就暫停,虛擬時間還可以比真實時間慢或者快,以便調節游戲運行速度,所有的任務都依賴虛擬時間,並且它們不知道時鐘是否暫停,這樣就大大簡化了時間的表示和運算,我們可以隨時暫停時鐘從而能夠方便地調試。
任務管理器維護一個任務列表,並且知道下一個即將運行的任務是什麼。一共有3種任務:
調度器的作用便是把時鐘提供的虛擬時間按固定時間段(比如20ms)分成若干幀,在一個幀的時間段裡,依次調度所有的幀任務和定時任務,最後執行渲染任務,從而完成一個完整的幀。
我們為什麼不用多線程來執行這些任務,把調度功能交給操作系統呢?第一,通常游戲中會有很多個任務,為每個任務創建線程是不經濟而且低效的,很多任務只執行一次,大量開銷被花在線程的創建和銷毀上,而且我們很難控制多線程同步。第二,由於操作系統通常是搶先式多任務,我們無法得知一個任務是否會被另一個任務中斷或者能否在一幀內完成。
調度器就像是在模擬一個線程管理器,它必須非常靈活,首先,調度器依次執行隊列中的任務,可以精確計算每個任務花費的時間。如果用戶硬件配置不高,執行一個完整的幀花費的時間多於預算,則可以在下一個幀裡跳過不必要的任務(比如關閉特效,特效任務就是可以跳過的),如果執行一個完整的幀花費的時間小於預算,則可以多執行一些任務,比如多畫一些特效或多做一些AI運算等,這些都由調度器自動調節。
調度器的另一個功能是實現平滑地添加和刪除任務,通常游戲中的任務更新都很頻繁。如果使用多線程,則線程的創建和銷毀將耗費大量時間。
調度器執行一幀的流程如下:
由於只需要用到很少的API,我決定用J2SE來寫內核,這樣便於調試,等測試無誤再移植到MIDP上。