理想的狀態(tài)是,將游戲控制在60幀,這樣充分利用顯示器的能力,為用戶提供流暢的畫面。但是,通常情況下還是比較困難的,隨著游戲邏輯的復(fù)雜性,幀率一般情況下都會(huì)下降。如果可以有一種可視化的方法,幫助開發(fā)者去觀察每次RequestAnimationFrame的執(zhí)行時(shí)間,可以讓開發(fā)者及時(shí)的發(fā)現(xiàn)一些耗時(shí)的操作,盡量保證每次RequestAnimationFrame的執(zhí)行時(shí)間控制在16ms內(nèi)完成。
雖然目前還沒有發(fā)現(xiàn)同一的方法,但是Chrome提供了abut:tracing的標(biāo)簽頁,可以輔助開發(fā)者,去一探RequestAnimationFrame的究竟。不過,困難的是,如果想完全讀懂 about:tracing,需要對(duì)于chrome的架構(gòu)以及渲染方式非常熟悉,在加上GPU的原因,很難一下子完全理解整個(gè)頁面。
這里介紹一個(gè)簡單的用法,如下圖,是從我的同事Seth的Blog中復(fù)制的圖片,(如果想了解更多內(nèi)容,可以參考Box2D, Web workers, Better performance),可以注意到,圖中有兩個(gè)紅線,紅線之間的間隔是16毫秒,相信很容易想到,這是每幀執(zhí)行的最佳時(shí)間。在about:tracing頁面中,雙擊每個(gè)方塊,可以放大并出現(xiàn)每個(gè)函數(shù)的名字,按G,就可以立即出現(xiàn)兩邊的紅線。里面有個(gè)泛藍(lán)色的模塊,標(biāo)志W(wǎng)ebViewImp:animate,它就是負(fù)責(zé)執(zhí)行RquestAnimationFrame,貌似它的執(zhí)行時(shí)間沒有超過16ms,但是不幸的,因?yàn)樵趫?zhí)行完RequestAnimationFrame之后,瀏覽器還對(duì)于需要渲染的元素,執(zhí)行組裝和渲染操作,很明顯下圖中的渲染時(shí)間,超過了紅線的范圍,也就是超過了16ms,圖形渲染的效率自然會(huì)降低到60幀一下。
通過這個(gè)例子,可以看出,并不是把RequestAnimationFrame的執(zhí)行時(shí)間控制在16ms以內(nèi),就可以得到60幀率的渲染。還需要整體考慮,RequstAnimationFrame引起了多少元素的渲染,以及多大程度的重繪。
about:tracing是非常好用的頁面,有更多興趣的同學(xué),還請(qǐng)耐心學(xué)習(xí)chrome的渲染方式:
Trace Event Profiling Tool (about:tracing)
4) 頁面顯示API
RequestAnimationFrame很重要的優(yōu)點(diǎn),就是在Tab沒有被顯示的時(shí)候,可以暫停執(zhí)行,不消耗CPU資源。對(duì)于大部分的動(dòng)畫需求,是沒有問題的,但是也不能適應(yīng)于所有的場景,舉個(gè)例子,現(xiàn)在很多攻防類的游戲,在進(jìn)攻其他家城堡的時(shí)候,可以派兵進(jìn)行打仗。兩軍對(duì)陣的場景,通常是一段設(shè)計(jì)好的動(dòng)畫,有時(shí)候動(dòng)畫的時(shí)間還比較長,很多玩家會(huì)切換到其他頁面,用戶的本意是在其他網(wǎng)頁等待對(duì)戰(zhàn)結(jié)束。而RequestAnimationFrame控制的動(dòng)畫循環(huán),會(huì)因?yàn)榍袚Q到其他頁面,暫停執(zhí)行,從而違背了設(shè)計(jì)的初衷,也違背用戶的一些習(xí)慣??梢詮某绦蜻壿嬌媳荛_這個(gè)問題,比如人為加入一些計(jì)時(shí)器,按照時(shí)間播放相關(guān)的動(dòng)畫,但是這樣容易和主程序的循環(huán)出現(xiàn)邏輯上的混亂。幸運(yùn)的是,HTML5提供了Page Visibility的API。這個(gè)API可以在Tab被切換的時(shí)候,產(chǎn)生一定的回調(diào),從而可以讓開發(fā)者明確知道,目前頁面處于哪種顯示的狀態(tài)。
- function handleVisibilityChange() {
- if (document.webkitHidden) {
- if (playAnimation is true)
- //continue to do this animation
- }
- }
- document.addEventListener(“webkitvisibilitychange”, handleVisibilityChange, false);
上面是一段簡單的代碼,在發(fā)現(xiàn)頁面不被顯示的時(shí)候,可以執(zhí)行一些必須被執(zhí)行的動(dòng)畫。
5) Webworker的作用
現(xiàn)在很多的游戲,都利用到了Box2d或者其他重力引擎,而這種重力引擎的計(jì)算,相當(dāng)耗費(fèi)時(shí)間,如果將這些計(jì)算放在RequestAnimationFrame里面,很容易就會(huì)將每次執(zhí)行的時(shí)間,超過16ms。最好可以將這類高成本的計(jì)算,放在一個(gè)單獨(dú)的線程,每次RequestAnimationFrame只需要取到結(jié)果就可以了。
HTML5的webworker,剛好可以承擔(dān)這個(gè)角色。如上圖,是一個(gè)簡單的設(shè)計(jì)圖,box2d重力引擎,作為獨(dú)立計(jì)算的單元,存在于webworker內(nèi)部,利用setTimeout作為循環(huán)控制。在外部,RequestAnimationFrame控制動(dòng)畫的顯示。
具體的代碼和例子,可以參考:Box2D and Web workers for JavaScript developers
6) 毫秒精度的用處
RequestAnimationFrame最近剛推出了新的功能,可以提供微妙級(jí)別的精度,這個(gè)有什么用處呢?按照前面的說法,每秒60幀的顯示,每幀的具體時(shí)間為(1000毫秒/60),大約為16.67毫秒。如果只有毫米級(jí)別的精度,為了有效的控制RequestAnimationFrame的執(zhí)行時(shí)間,只能以整毫秒的精度,對(duì)RequestAnimationFrame進(jìn)行檢查,也就說,假設(shè)RequestAnimationFrame計(jì)劃在5.5毫秒后執(zhí)行,如果執(zhí)行到某一步,發(fā)現(xiàn)當(dāng)前時(shí)間已經(jīng)是5毫秒,雖然理論上也許還有0.5毫秒的時(shí)間可以使用,但是不能在進(jìn)行下一步的?,F(xiàn)在有了微秒級(jí)別的精度,可以做更精細(xì)的控制。下圖的解釋比較形象,上面是16.667每幀可以執(zhí)行的時(shí)間,下面是整毫秒數(shù)標(biāo)志的時(shí)間,顯然下面的圖,會(huì)浪費(fèi)很多的時(shí)間片。
目前,在chrome中,是通過window.performance.webkitNow()獲得高精度的時(shí)間的,相信不久的將來,很快就會(huì)變成標(biāo)準(zhǔn)performance.now()。
(未完待續(xù))
接上文:
HTML5游戲開發(fā) 之 循環(huán)的控制(1)
HTML5 游戲開發(fā) 之 資源加載篇(2)
HTML5 游戲開發(fā) 之 資源加載篇(1)
【網(wǎng)站聲明】本站除付費(fèi)源碼經(jīng)過測試外,其他素材未做測試,不保證完整性,網(wǎng)站上部分源碼僅限學(xué)習(xí)交流,請(qǐng)勿用于商業(yè)用途。如損害你的權(quán)益請(qǐng)聯(lián)系客服QQ:2655101040 給予處理,謝謝支持。