本節書摘來異步社群《cocos2d 跨平台遊戲開發指南(第2版)》一書中的第1章,第1.11節,作者: 【印度】siddharth shekar(謝卡)譯者: 武傳海 責編: 胡俊英,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
在本部分,我們将向遊戲中添加視差效果(背景滾動效果),它是遊戲中非常流行的一種效果。在視差效果中,相比于背景中的對象,前景中的對象移動得更快,背景中的對象移動得要慢很多,借此産生立體感與運動錯覺。
回想一下以前的電影片段,其中的英雄或主角保持靜止不動,他們看上去就像在騎馬一樣,背景不斷循環,讓人産生錯覺,以為英雄在場景中真地向前移動,如圖1-31所示。
下面我們将實作一個非常簡單的視差效果,其中所有的背景對象(例如,樹、灌木、草)都以相同的速度進行移動。為了實作這一效果,我們隻要擷取背景圖像,并讓它在一個循環中不斷移動即可。
視差效果實作如下:針對背景圖像,我們将使用兩個精靈,而不是一個精靈,在遊戲開始時把它們沿水準方向并排放在一起,如圖1-31中的第一幅圖所示。第一個精靈可見,第二個精靈在螢幕之外,最初玩家并不能看到它。
當遊戲開始時,兩個精靈将以一定的速度朝x軸的負方向移動,即向螢幕左側移動。兩個精靈以相同的速度移動,是以當遊戲開始時,精靈1将慢慢地向左逐漸移出螢幕,随之精靈2将一點點地在螢幕顯現出來。
一旦精靈1完全移出螢幕,它将快速移到精靈2的右側,即精靈2在遊戲開始時所處的位置上。
上述過程将在一個循環中不斷重複進行。兩個精靈總是向螢幕左側移動。當一個精靈從螢幕左側移出螢幕之後,它将立即移動到螢幕右側,并且繼續向左一點點地移動。
在為視差滾動建立資源,編寫視差效果代碼時,有幾點需要各位牢記。首先,當為視差效果建立資源時,所使用的圖像應該是連續的。例如,當你觀看前面的第二幅圖像時,會看到背景中的山脈好像是連續的。即使sprite 1與sprite 2是兩幅不同的圖像,當把它們放在一起時,它們看上去就像單獨的一張圖像。同樣的現象也出現在山腳下的淡綠色灌木叢上。灌木叢的左半部分位于sprite 1中,右半部分位于sprite 2中,當把它們并排在一起時,它們就會一起組成一棵完整的灌木,讓人産生一種它們本來就是一棵單獨灌木的錯覺。
第二點要注意的是圖像之間的接縫。即使把圖像無縫銜接在一起,并且讓精靈以相同的速度移動,有時在精靈之間仍然可能會觀察到有縫隙存在。盡管這不是一個非常普遍的問題,但是在一些架構中它可能會出現。為了防止出現這一問題,你可以把圖像稍微拉伸一點點,使圖像精靈彼此略微發生重疊,通常玩家覺察不到這種細微的變化。另一個方法是采用手工方式把精靈放置到螢幕精靈的末端,并且必要時做适當的調整,把精靈之間的接縫彌合。
上面這些就是視差滾動效果背後涉及到的主要理論。接下來,讓我們一起編寫代碼,實作簡單的視差滾動效果。
首先,采用類似于建立hero類的方式,建立cocostouchclass類型的檔案,并且将其命名為parallaxsprite。
打開parallaxsprite.h檔案,添加如下代碼。
在上述代碼中,我們先建立了幾個變量,這些變量後面會用到,例如變量_winsize和_center,前一個變量用來擷取遊戲運作裝置的螢幕分辨率的大小,後一個用來計算螢幕中心。
接着,我們又建立了兩個ccsprite類型的變量,持有兩張圖像,在視差效果中用來不斷循環。
然後,我們添加了一個_speed變量,用來指定圖像移動與循環的速度。
類似于hero類,在parallaxsprite類中,我們也建立了一個initwithfilename函數,它使用給定的檔案名對類進行初始化。另外,我們也添加了一個float類型變量,用來指定精靈的速度。
此外,我們還需要一個update函數,它在 1 秒内會被調用60次,用來在類中更新兩個精靈的位置。
以上就是parallaxsprite.h檔案的所有代碼,接下來,轉到并打開parallaxsprite.m檔案。
在parallaxsprite.m檔案中,添加如下代碼:
在上述代碼中,我們首先實作initwithfilename函數。在initwithfilename函數中,先初始化超類,擷取_winsize。接着,通過把視窗的寬度與高度分别除以2計算出螢幕中心,再把speed的值賦給_speed變量。
然後,建立_sprite1和_sprite2兩個變量,在spritewithimagenames中,通過filename變量傳入檔案名字元串。
請注意,_sprite1被放置到螢幕中心,_sprite2被設定到螢幕之外,橫坐标與_spirte1相差一個螢幕寬度,縱坐标與_spirte1相同。
最後,把兩個精靈添加到類中。
接下來,我們開始實作update函數,添加代碼如下:
首先,我們分别為兩個精靈計算它們在x軸上的新位置,計算時先擷取精靈目前位置的x值,再用它減去精靈的移動速度。之是以這樣做,是因為我們希望在每次調用update函數時讓精靈沿着x軸的負方向進行移動。
接着,我們把新坐标分别指派給兩個精靈,其中x值為上面計算得到的值,y值保持原值不變。
然後,檢測圖像的右邊緣對于玩家是否仍然可見,還是已經移出螢幕左側之外。如果是這樣,我們就把精靈放到脫屏位置上,即縱坐标不變,橫坐标與另一個精靈相距一個螢幕寬度,以確定兩個精靈之間不會出現縫隙。
在代碼中,我們使用了if-else語句,這是因為每次隻會有一個精靈移出螢幕左側邊界。
下面讓我們一起看一下如何使用parallaxsprite類。在mainscene.h類中,引入parallaxsprite.h檔案,建立一個parallaxsprite類型的變量psprite,代碼如下:
然後,在mainscene.m檔案中,移除本章開始時用來添加背景精靈的代碼,添加如下代碼:
正如前面我們所做的那樣,我們把bg.png檔案指派給psprite,此外,我們又指定了速度值為5。
請注意,不必手工調用parallaxsprite類的update函數,每一幀它都會被自動調用執行。而且,你也不必像以前那樣排程它,開始時update函數會被自動初始化。
到此為止,我們已經編寫好了所有代碼,運作代碼,我們将會看到如圖1-32所示的背景滾動效果。