碰撞檢測,用來檢查兩個精靈是否接觸。html
Pixi 沒有內置的碰撞檢測系統, 因此這裏咱們使用一個名爲 Bump 的庫,Bump 是一個易於使用的2D碰撞方法的輕量級庫,可與 Pixi 渲染引擎一塊兒使用。它提供了製做大多數2D動做遊戲所需的全部碰撞工具。git
要開始使用 Bump,首先直接用 script 標籤,引入 js 文件github
<script src="https://www.kkkk1000.com/js/bump.js"></script>
複製代碼
而後建立它的實例算法
let b = new Bump(PIXI);
複製代碼
變量 b 如今表明 Bump 實例。可使用它來訪問 Bump 的全部碰撞方法。數組
hit 方法是一種通用碰撞檢測功能。它會自動檢測碰撞中使用的精靈種類,並選擇適當的碰撞方法。這意味着你沒必要記住要使用 Bump 庫中的許多碰撞方法的哪個,你只須要記住一個 hit 。可是爲了不 hit 方法最後產生的效果和你想象的不同,最好仍是要了解一下 Bump 庫中其餘的方法。函數
如下是 hit 方法最簡單的使用形式:工具
b.hit(sprite1, sprite2);
複製代碼
若是兩個精靈碰撞到了,就返回 true,沒有碰撞到,則返回 false。post
查看示例學習
在碰撞檢測時,Bump 的方法默認精靈是矩形的,使用矩形碰撞檢測的算法,若是你想讓方法把一個精靈當作圓形,使用圓形碰撞檢測的算法,須要將精靈的 circular 屬性設置爲 true 。動畫
anySprite.circular = true;
複製代碼
若是你使用 hit 方法檢測兩個圓形精靈是否碰撞,你還須要將兩個精靈的 diameter 屬性設置爲 true 。
若是你但願精靈對碰撞做出反應,使它們不重疊,請將第三個參數設置爲 true 。
b.hit(sprite1, sprite2, true);
複製代碼
這個防止重疊的功能,對於製做牆壁,地板或任何其餘類型的邊界很是有用。
若是你想讓精靈碰撞後反彈,請將第四個參數設置爲 true。
b.hit(sprite1, sprite2, true, true);
複製代碼
注意:
若是須要精靈反彈,精靈還必須有速度屬性,也就是 vx 和 vy 屬性。
設置第五個參數爲 true 使 hit 方法使用精靈的全局座標。在檢測不一樣父容器的精靈之間的碰撞時,這頗有用。
b.hit(sprite1, sprite2, true, true, true);
複製代碼
精靈的全局座標是相對於畫布左上角的位置。 精靈的局部座標是相對於其父容器的左上角的位置。
若是要檢查點對象是否與精靈碰撞,將點對象做爲第一個參數,以下所示:
b.hit({x: 200, y:120}, sprite);
複製代碼
點對象是一個具備 x 和 y 兩個屬性的對象,x 和 y 表示了畫布中一個點的座標。
hit 方法還容許你檢查精靈和精靈組之間的碰撞。只需將精靈組做爲第二個參數便可。在此示例中,精靈組是 spriteArray。
b.hit(sprite, spriteArray, true, true, true);
複製代碼
你將看到 hit 方法自動遍歷精靈組中的全部精靈,並根據參數中的第一個精靈檢測它們。這意味着你沒必要本身編寫 for 循環或 forEach 循環。
你還可使用回調函數做爲第六個參數。這對於檢查單個精靈和精靈組之間的碰撞特別有用。若是發生碰撞,回調函數將運行,你能夠訪問碰撞返回值和碰撞中涉及的精靈。下面是如何使用這個特性來檢測一個名爲 sprite 的精靈和一個名爲 spriteArray 的精靈組之間的碰撞。
b.hit(
sprite,
spriteArray,
true, true, true,
function (collision, platform) {
//collision 表示 sprite 的哪一邊發生碰撞
//platform 表示 sprite 正在碰撞的精靈組中的精靈
console.log(collision);
console.log(platform);
}
);
複製代碼
這是一種執行復雜碰撞檢測的簡潔方式,能夠爲你提供大量信息和低級控制,但沒必要手動遍歷數組中的全部精靈。
hit 方法的返回值會與你正在檢查的精靈的種類相匹配。例如,若是兩個精靈都是矩形,而且 hit 方法的第三個參數是 true,碰撞後,返回值表示參數中第一個矩形發生碰撞的一側,若是沒有發生碰撞,返回值就是 undefined 。
示例:
let collision = b.hit(rectangleOne, rectangleTwo, true);
message.text = "參數中第一個矩形的碰撞側是: " + collision;
複製代碼
hit 方法只是 Bump 的許多低級碰撞方法的高級包裝器。若是你更喜歡使用較低級別的方法,接下來會列出全部的這些方法。
最基本的碰撞檢測是檢查點對象是否與精靈碰撞。hitTestPoint 方法將幫助你解決這個問題。
hitTestPoint 方法須要兩個參數:
名稱 | 描述 |
---|---|
point | 具備 x 和 y 屬性的點對象,x 和 y 表示了畫布中一個點的座標 |
sprite | 精靈 |
示例:
let collision = b.hitTestPoint(
{ x: 180, y: 128 }, //具備 x 和 y 屬性的點對象
sprite //須要檢測的精靈
)
複製代碼
若是點對象與精靈碰撞,hitTestPoint 方法返回 true,不然返回 false。
上面示例中的精靈被看成是矩形的,但 hitTestPoint 方法一樣適用於圓形精靈。若是精靈具備 radius 屬性,則 hitTestPoint 方法假定精靈是圓形的而且對它應用圓形碰撞檢測算法。若是精靈沒有 radius 屬性,則該方法假定它是矩形。你能夠給任何精靈一個 radius 屬性。而一個更簡單的方法是給精靈一個 circular 屬性並將其設置爲 true 。
anySprite.circular = true;
複製代碼
這樣精靈就會應用圓形碰撞檢測算法,並具備一個 radius 屬性,該屬性的值等於精靈寬度的一半。
hitTestCircle 方法用來檢測兩個圓形精靈之間的碰撞。
b.hitTestCircle(sprite1,sprite2)
複製代碼
做爲參數傳入 hitTestCircle 方法的精靈須要有 radius 屬性,若是精靈碰撞則返回 true,所以你能夠將其與 if 語句一塊兒使用來檢測碰撞,以下所示:
if(b.hitTestCircle(sprite1,sprite2)){
message.text = "碰撞到了!";
//碰撞到後,將 vx 設置爲0,中止移動
sprite1.vx=0;
}
複製代碼
當移動的圓形精靈碰到沒有移動的圓形精靈時,你可使用 circleCollision 方法建立碰撞反應。
參數:
名稱 | 默認值 | 描述 |
---|---|---|
circle1 | 移動的圓形精靈 | |
circle2 | 沒有移動的圓形精靈 | |
bounce | false | 用於肯定第一個精靈碰撞到第二個精靈時是否應該反彈 |
global | false | 是否使用精靈的全局座標。若是要檢測具備不一樣父容器的精靈之間的碰撞 ,這頗有用 |
注意: 若是你但願參數中第一個精靈碰撞到第二個精靈時反彈,那第一個精靈必須有速度屬性,也就是 vx 和 vy 屬性。
movingCircleCollision 方法可讓兩個移動的圓形精靈在碰撞時彈開,它們會以一種很是逼真的方式將速度傳遞給對方,從而使它們彈開。
參數:
名稱 | 默認值 | 描述 |
---|---|---|
circle1 | 移動的圓形精靈 | |
circle2 | 移動的圓形精靈 | |
global | false | 是否使用精靈的全局座標。若是要檢測具備不一樣父容器的精靈之間的碰撞 , |
b.movingCircleCollision(circle1, circle2)
複製代碼
若是圓形精靈具備 mass 屬性,則該值將用於幫助肯定圓形精靈應該相互反彈的力。
若是你有一堆移動的圓形精靈,你但願這些精靈都在碰撞後進行反彈,這個時候你須要把這些精靈進行兩兩檢查,判斷它們是否碰撞,這須要把這些精靈放在一個數組中,使用兩層 for 循環,而且內層 for 循環的計數器比外層的 for 循環大1,這樣就能夠檢測全部圓形精靈的碰撞狀況。
for (let i = 0; i < container.children.length; i++) {
//碰撞檢查中使用的第一個圓形精靈
var c1 = container.children[i];
for (let j = i + 1; j < container.children.length; j++) {
//碰撞檢查中使用的第二個圓形精靈
let c2 = container.children[j];
//檢查碰撞狀況,若是精靈發生碰撞,將精靈彈開
b.movingCircleCollision(c1, c2);
}
}
複製代碼
你能夠看到內層 for 循環的計數器開始就是一個大於外層 for 循環的數字:
let j = i + 1
複製代碼
這能夠防止對任何一對精靈進行屢次碰撞檢測。
Bump 庫還有一個方便的方法 multipleCircleCollision,使用這個方法能夠替代 for 循環的方式。這個方法會對每對精靈自動調用 movingCircleCollision,使它們互相反彈。 你能夠在遊戲循環中使用它來檢查數組中的全部精靈,可是要注意數組中的精靈是不能重複的。
示例:
b.multipleCircleCollision(container.children);
複製代碼
要肯定兩個矩形精靈是否碰撞,請使用 hitTestRectangle 方法:
b.hitTestRectangle(rectangle1, rectangle2)
複製代碼
若是矩形精靈碰撞,hitTestRectangletrue 方法返回 true,沒有碰撞則返回 false。
示例:
if(b.hitTestRectangle(sprite1,sprite2)){
message.text = "碰撞到了!";
}else{
message.text = "沒有碰到";
}
複製代碼
rectangleCollision 方法使矩形精靈表現得好像它們有質量。它能夠防止參數中的兩個矩形精靈重疊。
參數:
名稱 | 默認值 | 描述 |
---|---|---|
rectangle1 | 矩形精靈 | |
rectangle2 | 矩形精靈 | |
bounce | false | 用於肯定第一個精靈是否應該從第二個精靈反彈 |
global | true | 是否使用精靈的全局座標 |
返回值:
若是精靈碰撞到了,rectangleCollision 方法返回一個字符串值,告訴你第一個矩形精靈的哪一側碰到了第二個矩形精靈。其值多是 left
,right
,top
或 bottom
。若是沒有碰撞到返回值就是 undefined
。
示例:
let collision = b.rectangleCollision(sprite2, sprite1);
//碰撞發生在矩形1(第一個參數)的哪一側
switch (collision) {
case "left":
message.text = "參數中的第一個精靈的 左側 發生碰撞";
break;
case "right":
message.text = "參數中的第一個精靈的 右側 發生碰撞";
break;
case "top":
message.text = "參數中的第一個精靈的 上方 發生碰撞";
break;
case "bottom":
message.text = "參數中的第一個精靈的 下方 發生碰撞";
break;
default:
message.text = "沒有發生碰撞";
}
複製代碼
此示例代碼將阻止矩形重疊,並在名爲 message 的文本精靈中顯示碰撞側。
rectangleCollision 方法具備很是有用的反作用。參數中的第二個精靈可以將第一個精靈推走。若是你須要相似於推箱子游戲中的那種功能,這會頗有用。
hitTestCircleRectangle 方法能夠檢查圓形和矩形精靈之間的碰撞。
參數:
名稱 | 默認值 | 描述 |
---|---|---|
circle | 圓形精靈 | |
rectangle | 矩形精靈 | |
global | false | 是否使用精靈的全局座標 |
返回值:
若是精靈碰撞到了,hitTestCircleRectangle 方法一樣返回一個字符串值,告訴你圓形精靈在哪裏碰到了矩形精靈。其值多是 topLeft
,topMiddle
,topRight
,leftMiddle
,rightMiddle
,bottomLeft
,bottomMiddle
或 bottomRight
。若是沒有碰撞到返回值就是 undefined
。
示例:
let collision = b.hitTestCircleRectangle(circle, rectangle);
if (collision) {
message.text = "圓形精靈的 " + collision + " 側,發生碰撞";
} else {
message.text = "沒有發生碰撞";
}
複製代碼
使用 circleRectangleCollision 方法讓一個圓形精靈從矩形精靈的側面或角反彈。
參數:
名稱 | 默認值 | 描述 |
---|---|---|
circle | 圓形精靈 | |
rectangle | 矩形精靈 | |
bounce | false | 是否使使精靈反彈 |
global | false | 是否使用精靈的全局座標 |
示例:
b.circleRectangleCollision(circle, rectangle, true);
複製代碼
contain 方法能夠將精靈限制在必定矩形區域內。
參數:
名稱 | 默認值 | 描述 |
---|---|---|
sprite | 精靈 | |
container | 容器,這是一個對象,具備 x、y、width 和 height 屬性,表示一個矩形區域。 | |
bounce | false | 肯定精靈在碰到容器邊界時是否應該反彈。 |
callbackFunction | 回調函數,當精靈碰撞到容器邊界時會調用它,而且會將 contain 方法的返回值做爲參數傳入這個回調函數。 |
返回值:
若是精靈碰撞到容器邊界,contain 方法將返回一個 Set 對象,告訴你精靈撞到了哪一側,它的值可能有 left
,right
,top
或 bottom
,若是精靈沒有碰撞到容器邊界, 返回值就是 undefined
。
示例:
let collision = b.contain(sprite, { x: 0, y: 0, width: 512, height: 512 }, true, callbackFunction);
//發生碰撞時的回調函數
function callbackFunction(collision) {
console.log("collision", collision);
}
//若是發生碰撞,顯示哪邊的邊界發生碰撞
if (collision) {
if (collision.has("left")) {
message.text = "邊界 左側 發生碰撞";
};
if (collision.has("right")) {
message.text = "邊界 右側 發生碰撞";
};
if (collision.has("top")) {
message.text = "邊界 上方 發生碰撞";
};
if (collision.has("bottom")) {
message.text = "邊界 下方 發生碰撞";
};
}
複製代碼
上面的代碼會將精靈限制在對象定義的512 x 512像素區域內。若是精靈碰撞到容器的邊界,它將會反彈, 而且顯示碰到了哪邊的邊界,callbackFunction(第四個參數)也將運行。
contain 方法的另外一個特色是,若是精靈具備 mass 屬性,該值將用於以很是天然的方式抑制精靈的反彈。
注意:
使用 Bump 庫時,最好給精靈設置上速度屬性(vx,vy),由於 Bump 庫中許多方法實現效果時,都須要用到這個兩個屬性。