通常,游戲和桌面Windows程序不同(掃雷等桌面游戲除外),它不能依靠消息驅(qū)動(dòng),因?yàn)橛螒蛲ǔV挥幸粋€(gè)畫(huà)面,而且需要高速更新。因此,游戲只能靠時(shí)鐘驅(qū)動(dòng)。大部分游戲都在一個(gè)時(shí)鐘驅(qū)動(dòng)下定時(shí)渲染一幀畫(huà)面。此外,游戲需要接收用戶(hù)輸入,處理游戲事件(比如碰撞檢測(cè)等),可能還需要AI計(jì)算,這些任務(wù)都必須巧妙地在兩幅畫(huà)面切換的時(shí)間段里處理完畢,因此,一個(gè)高效而靈活的調(diào)度器就是游戲進(jìn)程的核心。
調(diào)度器由時(shí)鐘驅(qū)動(dòng)器和任務(wù)治理器組成。
時(shí)鐘驅(qū)動(dòng)器負(fù)責(zé)在需要的時(shí)候向調(diào)度器提供準(zhǔn)確的虛擬時(shí)間,虛擬時(shí)間流逝時(shí),游戲就運(yùn)行,虛擬時(shí)間停止時(shí),游戲就暫停,虛擬時(shí)間還可以比真實(shí)時(shí)間慢或者快,以便調(diào)節(jié)游戲運(yùn)行速度,所有的任務(wù)都依靠虛擬時(shí)間,并且它們不知道時(shí)鐘是否暫停,這樣就大大簡(jiǎn)化了時(shí)間的表示和運(yùn)算,我們可以隨時(shí)暫停時(shí)鐘從而能夠方便地調(diào)試。
任務(wù)治理器維護(hù)一個(gè)任務(wù)列表,并且知道下一個(gè)即將運(yùn)行的任務(wù)是什么。一共有3種任務(wù):
調(diào)度器的作用便是把時(shí)鐘提供的虛擬時(shí)間按固定時(shí)間段(比如20ms)分成若干幀,在一個(gè)幀的時(shí)間段里,依次調(diào)度所有的幀任務(wù)和定時(shí)任務(wù),最后執(zhí)行渲染任務(wù),從而完成一個(gè)完整的幀。
我們?yōu)槭裁床挥枚嗑€程來(lái)執(zhí)行這些任務(wù),把調(diào)度功能交給操作系統(tǒng)呢?第一,通常游戲中會(huì)有很多個(gè)任務(wù),為每個(gè)任務(wù)創(chuàng)建線程是不經(jīng)濟(jì)而且低效的,很多任務(wù)只執(zhí)行一次,大量開(kāi)銷(xiāo)被花在線程的創(chuàng)建和銷(xiāo)毀上,而且我們很難控制多線程同步。第二,由于操作系統(tǒng)通常是搶先式多任務(wù),我們無(wú)法得知一個(gè)任務(wù)是否會(huì)被另一個(gè)任務(wù)中斷或者能否在一幀內(nèi)完成。
調(diào)度器就像是在模擬一個(gè)線程治理器,它必須非常靈活,首先,調(diào)度器依次執(zhí)行隊(duì)列中的任務(wù),可以精確計(jì)算每個(gè)任務(wù)花費(fèi)的時(shí)間。假如用戶(hù)硬件配置不高,執(zhí)行一個(gè)完整的幀花費(fèi)的時(shí)間多于預(yù)算,則可以在下一個(gè)幀里跳過(guò)不必要的任務(wù)(比如關(guān)閉特效,特效任務(wù)就是可以跳過(guò)的),假如執(zhí)行一個(gè)完整的幀花費(fèi)的時(shí)間小于預(yù)算,則可以多執(zhí)行一些任務(wù),比如多畫(huà)一些特效或多做一些AI運(yùn)算等,這些都由調(diào)度器自動(dòng)調(diào)節(jié)。
調(diào)度器的另一個(gè)功能是實(shí)現(xiàn)平滑地添加和刪除任務(wù),通常游戲中的任務(wù)更新都很頻繁。假如使用多線程,則線程的創(chuàng)建和銷(xiāo)毀將耗費(fèi)大量時(shí)間。
調(diào)度器執(zhí)行一幀的流程如下:
由于只需要用到很少的API,我決定用J2SE來(lái)寫(xiě)內(nèi)核,這樣便于調(diào)試,等測(cè)試無(wú)誤再移植到MIDP上。
參考:Marshall:"Game PRogramming Gems 3"
待續(xù) :)
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注