天天看點

《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻

本節書摘來自華章出版社《html5 2d遊戲程式設計核心技術》一書中的第3章,第3.1節滾動背景和監控幀頻,作者[美] 戴維·吉爾裡,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

第3章

圖形和動畫是視訊遊戲的基礎。能夠繪制圖形和圖像是創造平滑的、不閃爍的動畫最重要的技能之一,也是遊戲開發人員必須要掌握的能力。

動畫會持續地繪制動畫幀,一般每秒30~60次。這個速率稱為動畫幀速率。每一個動畫幀如同連環畫的一頁,每幀幾乎和上一幀一樣,僅僅存在着微小的差别,這樣就可以在遊戲快速顯示動畫幀時,創造出運動的效果。更多有關連環畫的内容請閱讀3.2節。

圖3.1顯示了一個單獨的動畫幀截圖。這個遊戲版本會保持這一狀态到本章結束,圖中顯示了背景和平台從右向左滾動時的動畫幀速率。

平台在動畫畫面的前景,是以它們的移動速度要比背景快得多,進而産生了深度假象,這個假象也稱為視差效應。

圖3.1 滾動背景和監控幀頻

《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻

在開發平台上,跑步小人并沒有移動。而且遊戲也沒有沖突檢測,實際上,跑步小人是浮在半空中的,在她腳下并沒有平台。

最後版本的snail bait遊戲在canvas元素左上角的圖示處将會顯示剩餘生命的數量。但是現在,snail bait遊戲在該位置顯示目前動畫的幀速率。

本章首先簡單地介紹canvas元素的二維api,然後讨論snail bait遊戲中一些重要動畫的實作。在本章中,你将會學習以下内容:

繪制canvas中的原始圖形和圖像(3.1節)

創造平滑的、無閃爍的動畫(3.2節)

實作遊戲主循環(3.3節)

計算幀速率(3.4節)

滾動遊戲背景(3.5節)

實作不受隐藏幀速率幹擾的動畫(3.6節)

反轉滾動方向(3.7節)

繪制單個動畫幀(3.8節)

使用視差效應模拟三維空間(3.9節)

在繼續之前,你也許想試着完成本章圖3.1顯示的遊戲版本,如果你做了嘗試,會發現代碼還是比較容易了解的。

canvas元素是立即模式的圖形系統,意味着當你提出要求時,它會立即繪制,然後立即忘記。其他圖形系統,例如svg,使用了保留模式的圖形系統,也即繪制時會保留一系列将要繪制的對象。由于不需要維護顯示清單,是以canvas元素運作速率要比svg快。然而,如果你想擷取一個使用者可以操作的對象清單,你必須在canvas元素的繪圖環境中自己完成該功能。

之前的注意事項提到了canvas元素會立即繪制出你指定的内容,此處需要進一步解釋。

當浏覽器調用snail bait遊戲的animate()方法繪制目前動畫幀時,canvas元素不是立即繪制出你指定的内容;相反,它會繪制一個背景canvas元素來代替目前的canvas元素。在animate()方法傳回之後,浏覽器通過一個圖形操作,複制背景canvas元素的整個内容到螢幕上。這種技術,也稱為雙緩存技術,該技術能夠讓動畫更加平滑,如果浏覽器第一時間将圖形繪制到canvas元素上,則不會有這樣的效果。

像apple的cocoa和adobe的illustrator一樣,canvas元素的api也是基于路徑的,即通過創造路徑來制作圖元,然後順序地繪制和填充該路徑。strokerect()和f?illect()方法分别可以很友善地繪制或填充矩形。

3.1 使用html5 canvas元素繪制圖形和圖像

canvas元素的二維繪圖環境提供了一個功能極為豐富的圖形api,可以讓你繪制從文本編輯器到平台視訊遊戲的任何内容。在寫作本書時,這個api包含了超過30種方法,snail bait遊戲大約隻使用了其中三分之一,如表3.1所示。

表3.1 canvas元素的二維繪圖環境方法

《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻
《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻

方法描述

arc (x,y,radius, start-angle,endangle, coun-terclockwise) 為目前路徑添加一個弧度。可以使用arc()方法給目前的路徑添加一段圓弧,通過指定0~2π或(0°~360°)的值來确定圓弧的角度

beginpath() 結束目前路徑并開始一個新的路徑

drawimage (image, sx, sy, sw, sh, dx,dy, dw, dh) 在目标canvas元素(目的地)的指定位置繪制指定圖像(源)的所有或者部分内容。實參中的s和d分别表示源和目的地,即sx代表source x,dh代表destination height,依此類推。除了圖像之外,源也可以是視訊或者其他canvas元素。目的地總是和上下文相關的canvas元素

可以調用帶有所有9個參數的drawimage()函數,也可以調用帶有3個或者5個參數的函數,

drawimage (image, sx, sy, sw, sh, dx,dy, dw, dh) 例如:drawimage (image, dx, dy)或者drawimage (image, dx, dy, dw, dh)。3個參數或者5個參數的版本會在canvas元素指定位置繪制出整個圖像。5個參數的版本允許你通過設定圖像的寬度和高度進行縮放。

9個參數的drawimage()函數允許你繪制全部或者部分圖像,并可以同時調節圖像的大小

f?ill() 使用目前填充風格填充路徑内部,可以是顔色、圖案或者過渡

f?illrect (x, y, w, h) 使用目前填充風格填充矩形

ispointinpath() 确定一個點是否位于目前路徑中,路徑可以是一個不規則的形狀

rect (x, y, w, h) 給目前路徑添加一個矩形框

restore() 恢複目前繪圖環境的狀态到上一次你調用save()時所存儲的狀态

save() 存儲繪圖環境的狀态。可以使用restore()函數恢複該狀态。在調用save()和restore()之間做出的任何改變都是臨時的

stroke() 用目前的畫筆樣式繪制路徑的輪廓,可以是顔色、圖案或過渡

strokerect (x, y, w, h) 用目前的畫筆樣式繪制一個未填充的矩形

translate (x, y) 平移坐标系統。這是一個強大的方法,可以在許多不同的情況下使用。snail bait遊戲中的所有水準滾動都是通過調用該方法實作的

canvas元素的二維繪圖環境也有超過30種屬性,但snail bait遊戲僅使用了其中的少量屬性,如表3.2所示。

表3.2 snail bait遊戲中使用的canvas元素二維繪圖環境屬性

《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻

屬性描述

linewidth 線條的寬度以及圓、矩形、圓弧和曲線的輪廓厚度

f?illstyle 取值為任何有效的css顔色,例如rgb(0,0,0),#ffffff或者skyblue。用于填充形狀。除了顔色之外,也可以指定過渡或者圖案作為填充樣式

strokestyle 任何有效的css顔色字元串,用于繪制形狀輪廓或者線條。也可以指定過渡或者圖案作為筆畫樣式,使其與填充樣式保持一緻

globalalpha 所有圖形操作的不透明度,例如stroke(),f?ill()和drawimage(),但是要除去getimagedata()和putimagedata(),因為它們可以直接操作canvas元素的像素

在snail bait遊戲中,除了平台之外,其他所有内容都是圖像。背景、跑步小人、好家夥和壞家夥都是drawimage()方法繪制的遊戲圖像。

在最終完成的snail bait遊戲版本中,snail bait遊戲會使用sprite圖像表單來存儲遊戲用到的所有圖像,但在現階段,我們仍會使用單獨的圖像來繪制背景和跑步小人。

3.1.1 繪制背景

snail bait遊戲使用drawbackground()函數繪制背景。該函數的初始版本如程式清單3.1所示。

程式清單3.1 繪制背景(初始版本)

《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻

程式清單3.1中的drawbackground()函數會在canvas元素的(0,0)位置繪制背景圖像。這個位置是将圖像的左上角放到了canvas元素的繪圖區域的左上角。在3.5節中,我們将修改這個函數,讓背景可以水準滾動。

3.1.2 繪制跑步小人

第6章會介紹sprite對象,在這之前,snail bait遊戲使用drawrunner()函數來繪制跑步小人,如程式清單3.2所示。

程式清單3.2 繪制跑步小人

《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻

drawrunner()函數向drawimage()函數傳遞了三個參數:一個圖像源以及圖像在canvas元素中繪制的左側坐标和頂部坐标。左邊的坐标是一個常數runner_left;drawrunner()函數是通過從跑步小人所在平台的上邊緣坐标減去跑步小人的高度,來計算跑步小人頂部的坐标。函數減去跑步小人的高度使得跑步小人的腳站在平台上。你或許認為應該加上跑步小人的高度,而不是減去,但是canvas元素的坐标系是從頂部向底部增加的,是以如果要在canvas元素中向上移動一段距離,應該減少它的y坐标值。

3.1.3 繪制平台

snail bait遊戲的平台不是圖像,是以繪制它們需要使用多個canvas元素的api,僅僅調用drawimage()函數是無法完成平台繪制的,如程式清單3.3所示。

程式清單3.3 drawplatforms()函數

《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻
《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻

程式清單3.3中的javascript代碼定義了一個名為platformdata的隊列。隊列中的每一個對象都描述了一個單獨的平台。這些平台包含諸如left、width、height、track等屬性,這些屬性涵蓋了平台的位置資訊以及外觀資訊。

平台以水準軌迹移動,如圖3.2所示。

drawplatforms()函數會周遊platformdata數組,将數組中的每一個對象依次傳遞給drawplatform()函數,該函數會計算平台的頂部位置,設定環境變量,并繪制出平台矩形。

圖3.2 平台軌迹

《HTML5 2D遊戲程式設計核心技術》——第3章,第3.1節滾動背景和監控幀頻

drawplatform()函數使用canvas元素繪圖環境的strokerect()和f?illrect()方法來繪制平台矩形。它使用存儲在platformdata數組中的矩形對象的特征,設定環境線條的寬度、畫筆風格、填充樣式等資訊,并使用globalalpha屬性來設定平台的透明度。

現在,你已經了解了所有用于程式設計實作snail bait遊戲的canvas元素二維繪圖環境的内容。本書接下來的章節将會聚焦html5遊戲開發的其他方面,首先開始講解動畫。

當你設定canvas元素繪圖環境的屬性時,例如linewidth或f?illstyle,設定操作的作用将是永久的,這意味着它們将會影響到接下來你在canvas元素繪圖環境上執行的圖形操作。為了讓設定操作隻是臨時發揮作用,可以在save()方法和restore()方法之間完成圖像繪制,這樣就可以儲存和恢複繪圖環境的所有屬性。

snail bait遊戲所有的圖形對象(稱為sprite對象)都是資料驅動的,也即snail bait遊戲會通過包含sprite對象屬性的資料對象來建立它們,例如left,top等屬性,同platformdata隊列中的對象類似。sprite對象中繼資料提供了一個重要的解耦方式。例如,盡管snail bait遊戲在靜态隊列中存儲了sprite對象的中繼資料,但相同的中繼資料也可以由一個複雜的關卡生成器産生,這可以用于在遊戲運作時,根據遊戲狀态生成遊戲關卡。這樣的關卡生成器不需要在創造sprite對象時對snail bait遊戲的代碼做任何改變。

繼續閱讀