iT邦幫忙

2023 iThome 鐵人賽

DAY 22
1
Modern Web

什麼!在網頁上也可以寫遊戲?系列 第 22

[Day 22] 射飛鏢實作篇-浮動飛鏢、生成其他飛鏢

  • 分享至 

  • xImage
  •  

繼昨天在遊戲舞台中設置了飛鏢,並讓飛鏢會跟隨鼠標轉動之後,今天我們還要讓飛鏢會根據鼠標而稍微移動位置,並且實作本次遊戲的重點之一,射飛鏢。

浮動飛鏢

首先我們要來讓飛鏢跟隨鼠標而改變位置,但並不是讓飛鏢直接黏著鼠標,而是讓飛鏢會跟隨鼠標所在的方向稍微移動一下而已,詳細的樣子可以參考 [Day 20] 射飛鏢實作篇-事前規劃、舞台設定 總結下方的預覽影片。

同樣在事件 移動飛鏢 中,由於要改變位置,所以新增動作 更新顯示物件,這一次 物件的ID 選擇 dart 也就是飛鏢的容器,這樣就能夠讓本體與影子一起移動,這就是當初使用容器的目的。

接著勾選 設定位置,由於 設定方式 中的其他方法都不太適合我們,所以使用預設就好,接下來我們要通過數學的方式來計算飛鏢應在的位置,我知道很多人看到數學兩個字心臟就開始發作了,但不用擔心,我們只會用到簡單的加減乘除而已。

先說說我們要怎麼決定飛鏢的位置,其實就是讓飛鏢往鼠標的方向靠近一點點而已,鼠標離的越近,浮動的距離就越短,鼠標離的越遠,距離就越長,因此我們的步驟如下:

  1. 先算出鼠標到飛鏢原點之間相差多少距離,且 x 軸和 y 軸要各自分開計算。
  2. 從這段距離取一小段出來。
  3. 讓飛鏢原點加上這一小段距離。

如此一來我們就可以算出以飛鏢原點為基準,往滑鼠處位移的目標點了,事不宜遲,趕快來完成吧!

我們昨天將飛鏢的原點設置在 (320, 800) 的位置,所以這是第一個點,第二個點自然就是鼠標的位置,但怎麼知道鼠標在哪呢?事件表有提供一個預設的變數物件,能夠讓我們隨時讀取到鼠標的位置,那就是 mouse,且裡面包含了 xy 這兩個屬性,所以我們只要使用 {mouse.x} 即可,y 亦同。

因此第一步的公式就是 {mouse.x} - 320,由於我們是從飛鏢原點往鼠標位置稍微移動,所以目標點為鼠標位置,要放在前面,這樣算出來的正負號才不會相反,舉個例子,你在 10 我在 7,而 10 - 7 = 3,所以我要移動 3 格,也就是 7 + 3 才會到你的位置,如果今天寫成 7 - 10 = (-3),我移動了 -3 格反而會跑到 4 去,方向就反了,這樣是不是比較好理解呢。

接下來第二步為了取一小段出來,我們只要將其乘上一個小數點即可,例如 ({mouse.x} - 320) * 0.15,用更淺顯易懂的方式來解釋的話,就是把這一段距離拿個 15% 來使用,也就是乘以 0.15 的意思。

最後一步就是將第二步的結果,各自加回原點的值,所以最後的公式就如下:
x: 320 + ({mouse.x} - 320) * 0.15
y: 800 + ({mouse.y} - 800) * 0.15

設定好後儲存動作,並測試一次,就可以看到如上圖的效果了。

射飛鏢

接下來我們要實作按住飛鏢,將鼠標移出放開時射出飛鏢的部分。

首先先新增一個事件 按住飛鏢重覆次數 為 -1,接著新增觸發 滑鼠點擊 用來偵測滑鼠左鍵按下,觸發時機 設為 按下滑鼠按鍵(down) 後儲存,由於是要按住飛鏢,所以我們還需要一個檢查來判斷鼠標是否在飛鏢上,新增檢查 滑鼠懸浮於物件的IDdart檢查方式懸浮其上

接下來我們要在這個事件裡紀錄當下鼠標的位置,之後放開滑鼠時,才能計算之間的距離,以決定飛鏢的射速,因此新增動作 儲存全域變數tap_x = {mouse.x}tap_y = {mouse.y},x、y 要分別儲存,所以會有兩個動作。

事件結果如下圖。

接著我們要來處理滑鼠放開的時候,新增一個事件 放開飛鏢,同樣重複 -1 次,觸發也是利用滑鼠點擊來偵測左鍵放開,故觸發時機要設為 放開滑鼠按鍵(up),完成後儲存。

同樣的我們需要多一個檢查來確保我們曾經按下飛鏢,由於我們在按下飛鏢後新增了變數,因此可以利用檢查 變數是否存在,用途顧名思義,在 用來尋找變數的鍵名(Key) 中填入 tap_x 即可,完成後儲存檢查,因為 tap_xtap_y 是同時新增的,所以只要檢查其中一個即可,待我們處裡完需要這兩個變數的動作之後,就會將其刪除了,因此下次要重複觸發這個動作之前,就得再重新按下飛鏢一次。

接著我們要來建立即將飛出去的飛鏢,因此要來重複昨天 建立圖層佈局 的步驟了,但有幾個地方不太一樣要注意,這一次我們是要將飛鏢放進遊戲物件圖層,所以我們要在 父節點的物件ID 選擇 gameRoot,然後我希望射出去的飛鏢在原本的飛鏢底下,所以 父節點的子物件順序位置 設為 1,不過這就看個人喜好,不設定也可以。

下來 圖片佈局 的步驟就和昨天差不多,忘記的人可以翻回去看看,但還是有幾點不太一樣:

  1. 由於這些物件是會重複生成的,所以物件代碼都要在結尾加上 * 符號,就跟我們之前製作光暈任務時的角色代碼一樣,詳細可以參考 [Day 04] 事件表實作 - 動作篇
  2. 容器 dart* 的位置建議設置在舞台以外的地方,這是因為待會我們會用動作將這個飛鏢與原飛鏢的位置、角度進行同步,所以暫時先放在玩家看不到的地方待命。

接著我們要先來同步飛鏢的角度,同樣使用動作 更新顯示物件,這裡的 物件的ID 就比較特別了,我們可以在這裡同樣填入 dart* 來讀取物件,但是對於容器內的 dart_clip* 等,就必須先經過容器本身才能夠讀取,所以我們要寫成 dart*.dart_clip* 才能讀取飛鏢的本體,接著就跟昨天設置影子的角度一樣,設定旋轉角度 填入 {dart_clip.rotationDeg} 即可,接著重複此步驟,完成 dart*.dart_shadow* 的角度同步。

接著再新增第三個更新顯示物件,用來將 dart* 的位置,同步到 dart 上,因此物件的 ID 為 dart*,而 設置位置 的 x、y 分別為 {dart.x}{dart.y},完成後儲存。

接下來就是今天最重要的部分了,我們要讓飛鏢飛出去,同樣的新增更新顯示物件,物件 ID 為 dart*,在設置位置中,設定方式 有一個 朝一個方向移動方向 就是飛鏢的角度 {dart_clip.rotationDeg},重點是 距離 該怎麼算呢?

首先我們要先算出我們曾經按下飛鏢的鼠標位置,到當前鼠標位置的距離,這裡的距離就跟上面的不一樣了,是真正的兩點之間的距離,所以會應用到國中教過的數學公式——兩點距離公式,忘記的人我在這裡補上公式,沒學過的人也不要緊,可以先抄起來就好,之後再慢慢研究。

原理暫時就不細談,以免有人突然心肌梗塞就不好了,總之我們會需要用到我們在 [Day 15] 事件表中的數學函數 中介紹到的數學函數,讓我們來把上面的數學公式寫成事件表的數學式吧。

sqrt(pow({mouse.x} - {tap_x}, 2) + pow({mouse.y} - {tap_y}, 2))

我們的點 2 是滑鼠當下的位置,點 1 則是之前儲存在變數的滑鼠位置,先將點 2 的 x 減去點 1 的 x,以及點 2 的 y 減去點 1 的 y,接著利用 pow(x, y) 將各自的結果平方後相加,再利用 sqrt(x) 將相加後的結果開根號,就可以得到兩個點之間的距離。

如果直接使用這個計算結果,那麼飛鏢就只會移動到滑鼠當下的位置而已,我們要用少少的力,就可以丟出遠遠的飛鏢,因此還要將這個計算結果乘以一個倍數,例如我是乘以 2.5,最終位置的設定結果就如上圖。

接著問題來了,直接使用這個動作改變物件位置不是會讓物件瞬間移動到指定位置嗎?沒錯,所以這個動作還有一個額外的功能,但我們先在此打住,因為今天的內容量有點過多了,明天再繼續往下介紹。

CG 範例事件表

總結

今天實作了讓飛鏢跟隨鼠標位置而移動的浮動飛鏢,以及實作了按下鼠標放開後生成飛鏢的功能,還計算了飛鏢飛出後的停止點,只是目前的飛鏢會在一瞬間改變位置,沒有中間飛出的動畫過程,因此明天我們會繼續來解決這個問題。


上一篇
[Day 21] 射飛鏢實作篇-設置飛鏢、轉動飛鏢
下一篇
[Day 23] 射飛鏢實作篇-飛鏢投擲動畫、Easing 函數(補間動畫)
系列文
什麼!在網頁上也可以寫遊戲?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言