郭子豪,李燦蘋
(廣東海洋大學(xué)電子與信息工程學(xué)院,湛江 524008)
Unity3D是由丹麥Unity公司開發(fā)的游戲開發(fā)工具,作為一款跨平臺的游戲開發(fā)工具,從一開始就被設(shè)計成易于使用的產(chǎn)品[1]。Unity3D引擎[2]十分強大,可以開發(fā)2D、2.5D、3D游戲,同時在市場經(jīng)濟(jì)應(yīng)用上也十分廣泛,例如應(yīng)用于VR(虛擬現(xiàn)實)、3D設(shè)計、建筑業(yè)、醫(yī)療成像等方面[3]。在這種大勢所趨之下,市場越來越完善,Unity功能也越來越強大。
電子游戲自上世紀(jì)60年代誕生以來,短短的幾十年得到迅速的發(fā)展,極大地推動了軟硬件行業(yè)發(fā)展[4]。與此同時,互聯(lián)網(wǎng)迅速發(fā)展的今天,電子游戲具有很大的市場潛力,而5G時代的到來,更多互聯(lián)網(wǎng)企業(yè)開始涉及游戲制作、VR制作方面的業(yè)務(wù),更是促進(jìn)了電子游戲行業(yè)的發(fā)展。
利用Unity3D引擎制作的這款復(fù)古版2D像素游戲,很多90后可能都玩過,這款游戲每局操作時間短,按鍵簡單方便,工作學(xué)習(xí)之余能給人們帶來消遣,另外該款游戲最大的改進(jìn)是可以在PC端、移動設(shè)備端及PCE端等上運行,可以滿足各類人群的使用。
首先玩家進(jìn)入游戲后需要用鼠標(biāo)點擊畫面上的Start按鈕進(jìn)入游戲,然后有4秒的游戲倒計時畫面,倒計時結(jié)束后正式進(jìn)入游戲,如果玩家在游戲中被淘汰,畫面跳出Game Over定格3秒后將回到游戲開始界面;如果玩家勝利,將會彈出Win的慶祝畫面,按任意鍵回到開始界面;如果玩家要退出界面,可以直接點擊開始界面的Exit按鈕。
玩家通過W、A、S、D(或者對應(yīng)的方向鍵)控制吃豆人按照方向移動,吃掉關(guān)卡里的全部豆子即闖關(guān)成功,期間也要躲避敵人的攻擊,若是Pacman與敵人的路徑重合,玩家就會被淘汰。另外每隔10秒將從剩下的豆子中刷新一個超級豆子,Pacman吃到該豆子在3秒內(nèi)將會變成超級吃豆人,可以吃到敵人,敵人就會回到老巢。
《Pacman吃豆人》的計分面板由Remain、Eaten、Score組成,分別代表著剩余豆子,吃掉的豆子以及分?jǐn)?shù),其中吃掉一個普通豆子+100分,吃掉一個超級豆子+300分,吃掉一個敵人+500分。游戲也加入了音樂以及隨機刷新的超級豆子獎勵,增加和保證了游戲的趣味性以及平衡性,不至于玩家控制的Pacman在游戲迷宮里一直被敵人“追殺”,并且計分面板記錄了玩家的分?jǐn)?shù),可以增加玩家與其他玩家的互動性。
(1)玩家可以控制Pacman在迷宮內(nèi)按上下左右方向自由移動。
(2)敵人四個小鬼會隨機選擇預(yù)設(shè)路徑自動巡邏,可以吃掉Pacman。
(3)每隔10秒在剩下豆子中隨機刷新出一顆超級豆子,Pacman吃了超級豆子后在3秒內(nèi)變成超級Pac?man,可以吃掉敵人。
(4)游戲擁有計分面板,實時計算玩家得分。
(5)點擊Start后有倒計時以及倒計時音效,點擊Exit可直接退出游戲。
(1)游戲地圖的初始化
在Maze中添加Box Collider 2D組件,將迷宮的墻都包圍出來,如圖1所示,該組件用于檢測物體之間的碰撞情況,讓游戲里面的人物都無法穿過墻。
圖2 是Box Collider 2D組件的配置,其中is Trig?ger屬性默認(rèn)不打勾,它表示是否啟用觸發(fā)器。是否啟用觸發(fā)器主要與腳本有關(guān)系,啟動觸發(fā)器之后碰撞檢測會觸發(fā)腳本的相關(guān)方法,地圖不需要添加腳本也不需要做碰撞檢測,故不需要勾上is Trigger屬性。
(2)游戲人物的初始化
首先是Pacman,如圖3,先對Pacman的素材進(jìn)分割,然后制作成動畫,每個動畫對應(yīng)擁有一個動畫特效以及一個動畫狀態(tài)機,并且利用動畫狀態(tài)機設(shè)置動畫的Entry(初始狀態(tài))、AnyState(任意時刻)的狀態(tài)。在狀態(tài)機內(nèi)定義兩個Float類型的數(shù)值DirX和DirY,賦初值分別為1.0與0.0,表示Pacman向右的初始狀態(tài)。
同理,將Ghost按照Pacman的方法進(jìn)行設(shè)置,再向地圖里面添加Pacdot,把豆子的素材一顆一顆按照單位像素填進(jìn)地圖里,最后得到的游戲場景效果如圖4所示。
第一個游戲人物是玩家控制的主角:吃豆人Pac?man。
首先對Pacman的prefab預(yù)制體增加幾項組件:Circle Collider 2D、Rigidbody 2D。其中 Circle Collider 2D為圓碰撞器,如圖5所示,并將其半徑設(shè)為0.95,是為了避免其他誤差。Rigidbody 2D為剛體類型,如圖6所示,這種類型是為了物理仿真運動而設(shè)計的(讓物體看起來更像現(xiàn)實世界行為),它的運動受重力、質(zhì)量、其他因素的影響。因為此款游戲為2D像素游戲,故將Gravity Scale設(shè)置為0,并且凍結(jié)Z軸。
圖6 Rigidbody 2D剛體組件
然后編寫控制Pacman移動的C#腳本,將腳本放在Scr文件夾下,在Visual Studio 2017下編寫運行。腳本代碼中涉及到一些腳本生命周期的方法,即掛載到的游戲物體“從出生到死亡”所經(jīng)歷的一些事件。這些生命周期事件,是一些特定的方法,而且是由Unity引擎事先定義好,在游戲的運行過程中,由引擎自動調(diào)用。Start()方法是開始事件,只執(zhí)行一次;FixedUpdate()方法是固定更新事件,執(zhí)行N次,0.02秒執(zhí)行一次,所有物理組件相關(guān)的更新都在這個事件中處理,通過差值方法實現(xiàn)Pacman的移動。
下面是控制Pacman移動的核心代碼。
//使用差值移動的方法獲取到達(dá)目的地
Vector2 temp=Vector2.MoveTowords(transform.position,dest,speed);
//將剛體移動到目標(biāo)位置
GetComponent<Ridgidbody2D>().MovePosition(temp);
第二個游戲人物是游戲里的敵人:Blinky、Clyde、Inky、Pinky。
首先給 Blinky、Clyde、Inky、Pinky 四個人物均加上Circle Collider 2D以及Rigidbody 2D組件,并設(shè)置is Trigger以及將Gravity Scale設(shè)置為0和凍結(jié)Z軸。
然后在這些敵人對象中添加Ghost腳本組件。在對Ghost設(shè)置巡邏路徑時,應(yīng)將路徑做成預(yù)制件素材,這是為了更加方便地導(dǎo)入腳本方法和導(dǎo)入存儲著路徑坐標(biāo)的數(shù)組。其中GameObject類型的wayPointsGos[]數(shù)組存儲的是一組路線(waypoints1,2,3,4),ways集合存儲的是一組路線的具體某一位置。
下面的代碼主要是一種偽AI算法,實現(xiàn)的是Ghost按照固定的四組路線隨機地進(jìn)行巡邏。四組巡邏路徑區(qū)域分布在以Ghost老家為原點坐標(biāo),建立二維坐標(biāo)系的四個象限上,每一組路線就是一個位置的集合,選擇其中一組路徑,遍歷該組路徑。
if(transform.position!=ways[curr])
{
//ways[]數(shù)組存儲的是某一確定坐標(biāo)
Vector2 temp=Vector2.MoveTowards(transform.position,ways[curr],speed);
GetComponent<Rigidbody2D>().MovePosition(temp);
}else
{
curr++;
if(curr>=ways.Count)
{
curr=0;
//wayPointsGos[]數(shù)組存儲的是任意一組路線(waypoints1,2,3,4)
LoadPath(wayPointsGos[Random.Rage(0,wayPointsGos.length)]);
}
第三個游戲人物是游戲里的豆子Pacdot。
給780顆Pacdot prefab預(yù)制體都增加Box Collid?er 2D組件,勾上is Trigger以啟動觸發(fā)器,以便在腳本中通過調(diào)用OnTriggerEnter2D()方法來做碰撞檢測,此款游戲主要是對Pacman和Pacdot進(jìn)行碰撞檢測。
if(collider.gameObct.name=="Pacman")
{
//如果碰撞檢測為超級豆子
if(isSuperPacdot)
{
GameManager.Instance.OnEatPacdot(gameObject);
//調(diào)用OnEatSuperPacdot()函數(shù)實現(xiàn)對應(yīng)功能
GameManager.Instance.OnEatSuperPacdot();
//銷毀游戲?qū)ο?/p>
Destory(gameObject);
}
else
{
GameManager.Instance.OnEatPacdot(gameObject);
Destory(gameObject);
}
}
(1)游戲的UI交互(包括開始畫面、實時計分畫面、游戲輸贏效果提示)
StartPanel界面中Start和Exit按鈕分別代表進(jìn)入游戲和退出游戲。在GamePanel界面中添加Remain、Eaten、Score文本,分別用以顯示剩余的豆子、吃掉的豆子以及獲得的分?jǐn)?shù)。界面效果如圖7和圖8所示。
圖7 StartPanel界面
圖8 GamePanel界面
當(dāng)吃完所有的豆子后,取得勝利,實現(xiàn)的是隱藏GamePanel畫面,實例化winPrefab畫面,取消所有協(xié)程并將游戲狀態(tài)設(shè)置為false,效果如圖9所示。
當(dāng) Pacman被 Ghost吃掉后,游戲結(jié)束,隱藏GamePanel畫面,實例化gameOverPrefab畫面,并且畫面停留3秒后,回到游戲初始畫面,效果如圖10所示。
圖9 Win效果
圖10 GameOver效果
(2)游戲的音效交互(包括游戲背景音樂、游戲開始音效等)
音效在整個游戲過程中占有極其重要的地位,直接關(guān)系到玩家的感觀享受與游戲體驗。有特色的音效交互能夠非常生動地描繪出游戲所在場景的環(huán)境氛圍和背景氛圍,增強游戲的場景感,令人身臨其境[5]。
在該游戲里,主要有兩個音效:一個是背景音樂,另一個是游戲開始倒計時音效。其中背景音樂是給GameManager預(yù)制體中添加組件Audio Source,并且將素材里的bgm文件導(dǎo)入到該組件中,當(dāng)開啟GamePan?el游戲畫面時播放該bgm;倒計時音效是在游戲開始時點擊Start按鈕時,開始播放startClip音樂。
游戲開始界面測試:游戲開始界面以及倒計時界面播放背景音樂的畫面,點擊Start按鈕之后播放倒計時動畫。倒計時功能畫面,如圖11所示。
圖11 倒計時功能測試
游戲計分界面測試:游戲中計分板畫面,計分面板由Remain、Eaten、Score組成,分別代表剩余的豆子,吃掉的豆子以及分?jǐn)?shù),其中吃掉一個普通豆子+100分,吃掉一個超級豆子+300分,吃掉一個敵人+500分。計分UI系統(tǒng)測試界面如圖12所示。
圖12 計分UI系統(tǒng)測試
游戲主要功能測試:每隔10秒從剩下的豆子中刷新一個超級豆,Pacman吃到該豆子在3秒內(nèi)將會變成超級吃豆人,吃掉Superdot之后,Ghost會變虛,靜止在地圖的畫面上,在SuperPacman狀態(tài)下可以吃掉Ghost,Ghost就會回到初始位置上。吃到Pacdot效果和Ghost回到老家功能測試界面如圖13所示。
圖13 吃掉Superdot后的效果
游戲結(jié)束測試:游戲勝利以及游戲失敗畫面。如果玩家在游戲中被Ghost碰到,Pacman被淘汰,畫面將跳出Game Over畫面,定格3秒后將回到游戲開始界面,如果玩家將地圖上所有的Pacdot吃完,將會彈出Win的慶祝畫面,按任意鍵回到開始界面。游戲勝利畫面和游戲失敗畫面如圖9和圖10所示。
借助Unity3D引擎開發(fā)的2D復(fù)古游戲——《Pac?man吃豆人》,這款游戲從最初的游戲規(guī)則、場景及人物的設(shè)計,到場景、人物以及功能的實現(xiàn),再到UI以及音效的優(yōu)化,整個制作流程按照游戲開發(fā)規(guī)范進(jìn)行開發(fā),并且測試效果達(dá)到了功能設(shè)計的要求。
雖然這款游戲基本復(fù)原了童年的像素游戲,但是也存在很多不足,尤其是在對Ghost的移動控制,現(xiàn)階段只做到偽AI的巡邏路徑,可以優(yōu)化為更加智能的自動規(guī)劃路線。因此,此款游戲還有很大的優(yōu)化空間。