[英]Javascript canvas collision detection
我正在使用需要碰撞檢測的畫布在 Javascript 中構建游戲,在這種情況下,如果玩家精靈擊中一個盒子,則不允許玩家通過盒子。
我有一個名為blockList
的全局數組,用於保存所有繪制到畫布上的框。 它看起來像這樣:
var blockList = [[50, 400, 100, 100]];
他們像這樣被吸引到畫布上:
c.fillRect(blockList[0][0], blockList[0][1], blockList[0][2], blockList[0][3]);
我還有一個播放器對象,它有一個更新方法和一個繪制方法。 更新根據鍵盤輸入等設置玩家的位置,主游戲循環使用 draw 將玩家繪制到畫布上。 玩家被畫成這樣:
this.draw = function(timestamp) {
if(this.state == "idle") {
c.drawImage(this.idleSprite, this.idleSprite.frameWidth * this.idleSprite.frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, this.xpos, this.ypos, this.idleSprite.frameWidth, this.idleSprite.frameHeight);
if(timestamp - this.lastDraw > this.idleSprite.updateInterval) {
this.lastDraw = timestamp;
if(this.idleSprite.frameCount < this.idleSprite.frames - 1) { this.idleSprite.frameCount++; } else { this.idleSprite.frameCount = 0; }
}
} else if(this.state == "running") {
var height = 0;
if(this.facing == "left") { height = 37; }
c.drawImage(this.runningSprite, this.runningSprite.frameWidth * this.runningSprite.frameCount, height, this.runningSprite.frameWidth, this.runningSprite.frameHeight, this.xpos, this.ypos, this.runningSprite.frameWidth, this.runningSprite.frameHeight);
if(timestamp - this.lastDraw > this.runningSprite.updateInterval) {
this.lastDraw = timestamp;
if(this.runningSprite.frameCount < this.runningSprite.frames - 1) { this.runningSprite.frameCount++; } else { this.runningSprite.frameCount = 0; }
}
}
}
現在,播放器具有某些屬性: player.xpos
、 player.ypos
、 player.width
、 player.height
。 塊存在相同的屬性。 所以我擁有實現碰撞檢測所需的一切,我只是不知道該怎么做。 我試過做這樣的事情:
if(player.x > blockList[0][0] && player.y > blockList[0][1])
但它遠非完美或可玩。
有誰知道一個簡單的方法或函數能夠根據兩個對象是否發生碰撞來返回 true 或 false?
我使用以下函數來檢測兩個矩形之間的碰撞:
rect_collision = function(x1, y1, size1, x2, y2, size2) {
var bottom1, bottom2, left1, left2, right1, right2, top1, top2;
left1 = x1 - size1;
right1 = x1 + size1;
top1 = y1 - size1;
bottom1 = y1 + size1;
left2 = x2 - size2;
right2 = x2 + size2;
top2 = y2 - size2;
bottom2 = y2 + size2;
return !(left1 > right2 || left2 > right1 || top1 > bottom2 || top2 > bottom1);
};
這確定了兩個以(x1, y1)
和(x2, y2)
,邊長分別為2*size1
和2*size2
正方形是否重疊。 更改left1
、 right1
等的定義以處理一般矩形而不僅僅是正方形並使用不同的數據格式應該很容易。
具體來說, left1
是第一個正方形的左側, right1
是右側,等等。請注意,在我的坐標系中,y 軸是倒置的( top1
< bottom1
)。
您只想知道兩個矩形是否重疊?
這是為您提供的防彈功能:
// returns true if there is any overlap
// params: x,y,w,h of two rectangles
function intersects(x1, y1, w1, h1, x2, y2, w2, h2) {
if (w2 !== Infinity && w1 !== Infinity) {
w2 += x2;
w1 += x1;
if (isNaN(w1) || isNaN(w2) || x2 > w1 || x1 > w2) return false;
}
if (y2 !== Infinity && h1 !== Infinity) {
h2 += y2;
h1 += y1;
if (isNaN(h1) || isNaN(y2) || y2 > h1 || y1 > h2) return false;
}
return true;
}
如果您的程序可以確定數字總是有限的,您可以使用更簡單的版本:
// returns true if there is any overlap
// params: x,y,w,h of two rectangles
function intersects(x1, y1, w1, h1, x2, y2, w2, h2) {
w2 += x2;
w1 += x1;
if (x2 > w1 || x1 > w2) return false;
h2 += y2;
h1 += y1;
if (y2 > h1 || y1 > h2) return false;
return true;
}
它的作用是找到兩個矩形的右側和底邊在哪里,然后查看第二個矩形是否從第一個矩形開始,或者第一個矩形是否從第二個矩形開始。
如果其中一個矩形在另一個矩形結束后開始,則不會發生碰撞。 否則一定會發生碰撞。
在我看來,我不喜歡需要很多參數的函數。
這是我將如何做到的:
function collisionCheckRectRect(rectOne, rectTwo){
var x1=rectOne.x, y1 = rectOne.y, height1 = rectOne.height, width1 = rectOne.width;
var x2=rectTwo.x, y2 = rectTwo.y, height2 = rectTwo.height, width2 = rectTwo.width;
return x1 < x2+width2 && x2 < x1+width1 && y1 < y2+height2 && y2 < y1+height1;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.