iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
Modern Web

PixiJS青銅玩家系列 第 21

【LV. 21】PixiJS青銅玩家:helper function - hitTestRectangle()

  • 分享至 

  • xImage
  •  

▉ 前言

這裡將利用教程所提供的"Treasure Hunter Game"來直接學習PixiJS中的語法。"Treasure Hunter Game"的程式碼 ---> Click Here !

系統提示:「Live as if you were to die tomorrow. Learn as if you were to live forever.——Gandh」,PixiJS青銅玩家還卡關於自定義function階段,僅獲得經驗提昇等級。

▉ 主線任務:helper function - hitTestRectangle( )

▍任務說明

hitTestRectangle()這個函數就是碰撞偵測,他在這個遊戲的作用在於:

  1. 當explorer與blobs相撞時要做扣血的動作
  2. 當explorer碰到treasure時要拾起寶箱

▍作法

function hitTestRectangle(r1, r2) {
  let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;
  hit = false;

  r1.centerX = r1.x + r1.width / 2; 
  r1.centerY = r1.y + r1.height / 2; 
  r2.centerX = r2.x + r2.width / 2; 
  r2.centerY = r2.y + r2.height / 2; 

  r1.halfWidth = r1.width / 2;
  r1.halfHeight = r1.height / 2;
  r2.halfWidth = r2.width / 2;
  r2.halfHeight = r2.height / 2;

  vx = r1.centerX - r2.centerX;
  vy = r1.centerY - r2.centerY;

  combinedHalfWidths = r1.halfWidth + r2.halfWidth;
  combinedHalfHeights = r1.halfHeight + r2.halfHeight;

  if (Math.abs(vx) < combinedHalfWidths) {
    if (Math.abs(vy) < combinedHalfHeights) {
      hit = true;
    } else {
      hit = false;
    }
  } else {
    hit = false;
  }
  return hit;
};

▍分析

首先從程式碼可看見hitTestRectangle(r1, r2)可以接收兩個參數,參數r1與r2分別可以放不同的sprite,用來偵測這兩個sprite是否有接觸。

如果互相接觸的話,則hitTestRectangle(r1, r2)此函數將回傳true。

因此我們可以透過if條件句,搭配hitTestRectangle(r1, r2)做使用:

if (hitTestRectangle(cat, box)) {
  //There's a collision
} else {
  //There's no collision
}

接著進到這串函式之中來看看,一開始先將hit變數設置為false(尚未發生碰撞)

hit = false;

***

再來我們先另外對以下四件事額外做命名(如此一來,使用上可以使可讀性更高,也會相對更方便):
1. 找到r1, r2兩個sprite的中心點:

r1.centerX = r1.x + r1.width / 2; 
r1.centerY = r1.y + r1.height / 2; 
r2.centerX = r2.x + r2.width / 2; 
r2.centerY = r2.y + r2.height / 2; 

2. 找到r1, r2兩個sprite的一半高度及一半寬度:

r1.halfWidth = r1.width / 2;
r1.halfHeight = r1.height / 2;
r2.halfWidth = r2.width / 2;
r2.halfHeight = r2.height / 2;

3. 找到r1及r2中心的距離:

vx = r1.centerX - r2.centerX;
vy = r1.centerY - r2.centerY;

4. 分別算出r1及r2一半高度的總和與一半寬度的總和:

combinedHalfWidths = r1.halfWidth + r2.halfWidth;
combinedHalfHeights = r1.halfHeight + r2.halfHeight;

定義好上方一些屬性、變數後,再進到最後的if條件句,看看hitTestRectangle()是如何判斷r1、r2是否互相接觸。

if (Math.abs(vx) < combinedHalfWidths) {
    if (Math.abs(vy) < combinedHalfHeights) {
      hit = true;
    } else {
      hit = false;
    }
} else {
hit = false;
}

***

if條件句這部份會用圖片做說明。
Step 1
首先,必須判斷x軸方向是否互相碰撞,是則進入下一個if條件句判斷,否則回傳hit為false:

Step 2
再來,判斷y軸方向是否碰撞,是則代表在x及y軸方向雙重確認有碰撞到,否則回傳hit為false:

***

知道他的條件句判斷的大方向後,我們來細看他判斷的內容:
首先,我們得先了解Math.abs(),在MDN中有非常清楚的說明,簡單來說他就是一個JS的函式,會回傳其絕對值。(Math是一個物件,.abs()Math的其中一個方法)

再來,我們將看看碰撞前、碰到當下、碰撞,三者狀況下Math.abs(vx)conbinedHalfWidthsMath.abs(vy)conbinedHalfHeights的關係。(不過這裡僅以x軸方向作為說明,y軸方向的想法是一樣的)

另外會以圖片說明代替文字說明,這個部份用文字說明有點障礙...

1. 碰撞前
Math.abs(vx)大於conbinedHalfWidths

2. 碰撞當下
Math.abs(vx)等於conbinedHalfWidths

3. 碰撞
Math.abs(vx)小於conbinedHalfWidths


▉ 結語

今天的部份最耗時的地方竟然是畫圖...不畫圖其實有點南理解那些算式之間的關係,明天將進入下一個自定義函數--randomInt()。


參考資料


上一篇
【LV. 20】PixiJS青銅玩家:helper function - contain()
下一篇
【LV. 22】PixiJS青銅玩家:helper function - randomInt()
系列文
PixiJS青銅玩家30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言