這篇內容,主要會講解,如何讓玩家進行移動,在解釋的過程中,會接觸到碰撞遮罩、Nine Slice、鍵盤事件,等等的相關設定。
本篇教學所使用的系統是Windows 10,如果有按鍵相關的說明,會用Windows的系統來解釋。如果你用的是Mac系統,再麻煩自行換成相對應的按鍵。
在學習本篇內容之前,最好具備以下的前置知識,以免看不懂這篇教學的內容。
本次的版本,將具備以下的功能:
在這個版本做完之後,我們就能依照矩形和牆壁,來規劃夠種物件的尺寸大小。但為了方便此處的教學,我會直接告知物件的尺寸,各位可以依照這個尺寸來實作。
等到下一篇的教學,我才會講解,要如何去規劃和測試,遊戲中的各種物件尺寸。
這邊要先請各位,準備一個寬高為720*100,以及一個80*80的矩形圖片,尺寸的單位是pixel。
我個人是習慣使用PS,來製作2D素材,接著再導入專案當中。當然,你也可以使用Sprite的繪圖功能,來把素材製作出來。
這邊我會分享,資產(Asset)的命名方式,以及相關的參數設定,如果你還沒有屬於自己的命名規則,可以稍微參考一下。要直接抄也無妨,但是要看的懂才行。
建立一個Sprite,將他命名成「spr_player」,這表示玩家操作的矩形。接著把720*100的素材匯入(Import)到spr_player裡面。
碰撞遮罩的設定,基本上使用預設值即可。然後把Fps設定成0,確保這個Sprite不會產生動畫。
原點則是設定成Middle Centre,這表示物體的正中心。
建立一個Object,將他命名成「obj_player」,這表示玩家操作的物件。接著把Sprite的參數,設定成「spr_player」。
建立一個Sprite,將他命名成「spr_wall」,這表示牆壁。接著把80*80的素材匯入到spr_wall裡面。
碰撞遮罩的設定,基本上使用預設值即可。然後把Fps設定成0,確保這個Sprite不會產生動畫。
原點則是設定成Top Left,這表示物體的左上角。
牆壁的部分,我們需要設定Nine Slice(我不知道這個要怎麼翻譯),設定的方式,麻煩參考下面的圖片:
這個設定,主要是改變拉伸圖片時,圖片的顯示方式,預設的狀況下是使用Stretch,也就是一般的拉長和縮短。
Repeat的模式,則是會變成重複,我們所選擇的切片範圍(Selected Slice)。右邊其實有顯示的預覽圖,各位可以拉伸一下,應該就能夠明白了。
至於為何要設定成這樣,這會留到房間的設定時,再進行說明。
建立一個Object,將他命名成「obj_wall」,這表示牆壁的物件。接著把Sprite的參數,設定成「spr_wall」。
找到預設的Room,並將他重新命名成「rm_stage_01」,這表示第一關的房間。
將房間的寬高,設定成5120*2880,勾選Enable Viewports。
設定Viewport 0,勾選Visible,Camera的寬高,設定成5120*2880,Viewport的寬高,設定成1600*900。
點選Background的圖層,並在左側找到Colour的參數,這個能改變背景的顏色。預設是黑色的,可以選一個順眼的顏色,我自己是選淡灰色。
在房間的右上角,有個Grid Options的選項,是個很小的倒三角符號,點開來後,能夠調整格線的設定。
麻煩把Grid X和Grid Y改成80的大小,格線顏色選一個喜歡的就好,然後Snap的功能要記得勾選,這樣才會有「黏貼」格線的功能。
另外,這個格線的設定,是每個圖層都有,而且都能獨立設定,所以上面的這些設定,煩麻請先選到Instances的圖層,再來做設定。
不然在Background上面做設定,其實沒什麼幫助,因為我們的物件,只能放在Instances的圖層上面。
在Instances的圖層上,建立一個玩家的實體,座標設定成(1920, 2640),其餘的參數保持預設。
在Instances的圖層上,建立一個牆壁的實體,座標設定成(0, 0),接著用滑鼠,把牆壁的寬度,拉到跟房間同寬。
此時各位可以觀察一下,當我們把牆壁設定成Repeat之後,上面的這一整排牆壁,其實只需要使用「一個實體」就能完成了。
要是沒有這樣設定,那麼就要建立一大堆的實體,才能鋪滿牆壁,這樣不管是設計關卡,或是管理,都會非常的麻煩。
接著把剩下的牆壁給補上,擺放的方式,請參考下面的圖片(中間直立的牆壁,X座標為3840):
鍵盤事件的運作邏輯,類似於「基地台」的概念,簡單來說,當我們按下按鍵時,遊戲就會「發送訊號」給所有的實體(Instance)。
至於實體要不要做出反應,就得看有沒有設定,相對應的程式碼。要是沒有設定,那就不會做出任何反應。
這個做出反應的程式碼,理論上可以寫在,任何的物件事件(Object Event)裡面。
在這次的範例中,我會把移動的程式碼,寫在「Key Down」的事件裡面,不過,有的人會把他放在Step事件裡面,這邏輯本身是沒有問題的。
只是放在不同的事件裡面,程式碼就會有一些細節上的差異,像是放在Step裡面的話,就還要多一個,偵測移動方向的變數(Variable),Key Down就不需要。
Key Down的特色是,只要我們一直按著不放,那程式碼就會一直觸發,所以很適合用在玩家的移動上面。
另一個跟他類似的,叫做Key Press,這個事件功能是:每按一次按鍵,才會觸發一次。雖然不適合用在玩家的移動,但在「發球」的時候,我們可以使用到他。
在obj_player的物件裡,加入Create事件,並放入以下的程式碼:
//移動速度
move_speed = 60 ;
move_speed
表示每次「移動的距離」,單位是Pixel,數值可以是任意大小,這邊設定成60,是我自己覺得合適的速度大小。
在obj_player的物件裡,加入Key Down - Left事件,並放入以下的程式碼:
//沒碰到牆就移動
if (!place_meeting(id.x - move_speed , id.y , obj_wall)) {
//往左移動move_speed的距離
id.x -= move_speed ;
}
place_meeting(x, y, obj)
的用途,是用來偵測,當實體「移動」到指定的座標時,實體是否有跟物件(or實體)發生碰撞。
在使用這個函式(Function)時,需要注意物件是否有設定碰撞遮罩,如果沒有設定遮罩的話,這個函式就無法發揮作用。
基本上物件只要有設定Sprite,就會有碰撞遮罩,除非沒有設定Sprite,那就要額外設定遮罩的功能(製作計時器時,會講解到這部分的設定)。
整個移動的邏輯很簡單,就是先檢查玩家,往左移動move_speed
的距離後,會不會和obj_wall
發生碰撞。
如果不會碰撞,那就讓玩家的座標,往左移動move_speed
的距離。
各位可以先執行(Run)一下程式碼,此時應該會發現,往左移動的時候,並不能完全的貼在牆壁上,而是會出現一道短短的空氣牆。
其中的原因是,當玩家和牆壁的距離,小於move_speed
的時候,玩家就不會再繼續移動了(因為下一步就會撞到牆壁)。這就導致畫面上產生了一道,短短的空氣牆。
為了解決這個問題,我們將移動的程式碼,修改成以下的樣子:
//沒碰到牆就移動
if (!place_meeting(id.x - move_speed , id.y , obj_wall)) {
//往左移動move_speed的距離
id.x -= move_speed ;
} else {
//小於move_speed的距離,會出現隱形牆,把移動條件改成撞到牆為止
while (!place_meeting(id.x - 0.1 , id.y , obj_wall)) {
id.x -= 0.1 ;
}
}
當距離小於move_speed
的時候,就讓玩家改成用0.1的距離,慢慢前進,直到撞到牆壁為止。
由於無法得知,到底要移動幾次,因此使用while迴圈,是比較合適的方法。
上面這一段的設定,是往左移動,往右移動也是一樣的邏輯,只是原本的「-」號,要通通改成「+」號,因為是要往右移動。
以下是往右移動的程式碼:
//沒碰到牆就移動
if (!place_meeting(id.x + move_speed , id.y , obj_wall)) {
//往右移動move_speed的距離
id.x += move_speed ;
} else {
//小於move_speed的距離,會出現隱形牆,把移動條件改成撞到牆為止
while (!place_meeting(id.x + 0.1 , id.y , obj_wall)) {
id.x += 0.1 ;
}
}
將這段程式碼,放到obj_player的Key Down - Right事件裡。
🔔如果內容對你有幫助,可以按個喜歡,這樣就能讓更多人,接觸到這些棒棒的內容🔔
✨祝各位也能開心的做出好遊戲✨