本節書摘來自華章出版社《html5 2d遊戲程式設計核心技術》一書中的第1章,第1.1節,作者[美] 戴維·吉爾裡,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。
3.5 滾動遊戲背景
除跑步小人外,snail bait遊戲中的所有物體,在遊戲運作時都會在水準方向上滾動。本節将讨論這個滾動功能的實作。
3.5.1 平移坐标系
每一個canvas元素都包含兩個部分:html元素以及繪圖區域,如圖3.3所示的一個畫框和一片繪圖區域。
繪圖區域有一個坐标系,這樣你就可以在指定的位置上繪制圖形,如圖3.3中的文字,它位于坐标(150,100)。可以使用程式清單3.11中的代碼,在canvas元素中繪制那段文本。
圖3.3 canvas元素(畫框)和它的繪圖區域

程式清單3.11 在繪圖區域中繪制文本
坐标系的原點,即位置(0,0),預設是在canvas元素的左上角。x坐标從左向右增加,y坐标從上向下增加,如圖3.3所示。x和y坐标的方向是不能改變的,但是坐标系的原點不是固定的。可以移動它,如圖3.4所示,如同移動畫框下面的繪圖區域一樣。
圖3.4 平移坐标系
在圖3.4中,坐标系向左平移了100個像素。平移坐标系并繪制文本的代碼在程式清
單3.12中給出。
程式清單3.12 設定背景偏移量
傳遞給context.translate()的兩個參數代表了在水準方向和垂直方向上移動坐标系的像素距離。在這個例子中,我們僅僅沿水準方向平移了坐标系,但context.translate()函數可以在兩個方向平移。
注意,和圖3.3中原始位置相比,盡管圖3.4中的文字具有相同的坐标,但是相對于canvas元素向左移動了一些距離。反過來說,canvas元素相對于文字,向右移動了一些距離。很明顯,移動來自于坐标系的平移。
可以在繪圖區域的任意位置進行圖形繪制,但是如果超出了canvas元素的範圍,超出部分的圖形将變得不可見,如圖3.5所示。
圖3.5 超出畫框(canvas元素)的繪制沒有效果
程式清單3.13給出了圖3.5中坐标系平移用到的代碼。
程式清單3.13 設定背景偏移量
前面的代碼将坐标系平移到足夠靠左的位置,這樣canvas元素中僅有部分文字是可見的。
正如前面讨論的那樣,通過持續地平移坐标系,并在相同的坐标值下進行重新繪制,你就可以創作出明顯的運動效果。這就是snail bait遊戲滾動背景和其他物體的方法。
3.5.2 滾動snail bait遊戲的背景
snail bait遊戲的背景圖像如圖3.6所示。
snail bait遊戲将繪制背景兩次,并且将其首尾相連,以适應滾動,如圖3.7所示,圖中藍色的線(中間的線)并沒有在遊戲中畫出,僅代表了兩個背景的連接配接。
??圖3.6 背景圖像
??圖3.7 兩次繪制背景
drawbackground()函數如程式清單3.14所示。
程式清單3.14 繪制遊戲背景
drawbackground()函數被draw()函數調用,snail bait遊戲會在每一個動畫幀中調用draw()函數。drawbackground()函數使得坐标系向左平移backgroundoffset個像素,繪制背景兩次,并将它們首尾相連,然後平移坐标系到drawbackground()函數調用前的初始位置。為了滾動背景,snail bait遊戲會持續地增加backgroundoffset的值。增加該值的影響如圖3.8所示,從右向左滾動的半透明區域代表圖像不在螢幕上顯示的部分。canvas元素坐标系從右向左移動。
持續地向左平移坐标系,會使canvas元素中的遊戲背景表現出向左移動的效果,正如你在圖3.8中看到的那樣。
背景圖像有1103像素寬,而遊戲canvas元素隻有800像素寬。當遊戲開始時,backgroundoffset的值為零,兩個背景唯一可見的部分是位于(0,0)處的圖像的前四分之三,如圖3.8頂部的截圖所示。繪制在位置(background.width,0)上的剩餘四分之一圖像以及另一個圖像,初始時是不可見的,因為它們位于canvas元素邊界之外。
遊戲開始一段時間後,backgroundoffset不再是零,坐标系向左平移很大一段距離,如圖3.8中部的截圖所示。然而,畫在(background.width,0)處的背景還是不可見的。
圖3.8 增加backgroundoffset值的影響
在滾動的最後階段(圖3.8的底部截圖),backgroundoffset等于背景圖像的寬度值,背景可見的部分和滾動開始時可見的部分是完全一樣的。此時,snail bait遊戲會重新将backgroundoffset的值設定為零,重新回到圖3.8的頂部截圖所示的狀态。
有意思的是,位于(background.width,0)位置後四分之一處的背景圖像是不可見的。因為canvas元素和背景圖檔的大小不比對。如果兩者有相同的寬度,畫在位置(background.width,0)上後四分之一的背景圖像,在特定的時間點上,是可以顯示出來的。
前面的圖像可能不是很明顯,但好在背景圖像有一個特點很适合作為遊戲背景:圖像左側邊緣和右側邊緣垂直方向的一列像素點是一樣的,如圖3.9所示。
如果沒有一樣的邊緣,在兩個背景圖像交彙的地方,會産生一條明顯的不連續線,就像圖3.7和圖3.8中的藍色線那樣。
目前滾動snail bait遊戲背景還有一個問題沒有解決:即遊戲是如何調整backgroundoffset變量來控制背景滾動的?這個問題将留到下一節再解決,我們現在可以先不考慮潛在的幀速率變化,使用一個恒定的速率來滾動背景。
為了産生平滑的滾動效果,請確定背景圖像具有一樣的邊緣。