2011-11-05 127 views
6

我正在用Javascript創建一個遊戲,使用需要碰撞檢測的畫布,在這種情況下,如果玩家精靈碰到一個盒子,玩家不能通過盒子。Javascript畫布碰撞檢測

我有一個名爲blockList的全局數組,其中包含所有正在繪製到畫布的框。它看起來像這樣:

var blockList = [[50, 400, 100, 100]]; 

而且他們被吸引到畫布像這樣:

c.fillRect(blockList[0][0], blockList[0][1], blockList[0][2], blockList[0][3]); 

我也有一個玩家對象,它有一個更新的方法和draw方法。更新根據鍵盤輸入等設置播放器的位置,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.xposplayer.yposplayer.widthplayer.height。塊的屬性相同。因此,我擁有所需的一切來實現碰撞檢測,但我不知道如何去做。我試過這樣的事情:

if(player.x > blockList[0][0] && player.y > blockList[0][1]) 

但它遠非完美或可播放。

有誰知道一個簡單的方法或函數能夠返回true或false的基礎上,如果兩個對象相撞?

回答

8

我使用碰撞檢測兩個矩形之間的下面的函數:

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*size12*size2分別是重疊的。應該很容易改變left1,right1等的定義來處理一般的矩形而不是僅僅處理正方形並使用不同的數據格式。

具體地說,left1是所述第一方,right1右側等的左側需要注意的是,在我的座標系中,Y軸反轉(top1 < bottom1)。

2

你只是想知道兩個矩形是否重疊?

這是給你一個防彈功能:

// 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; 
} 

它做的是什麼找到兩個矩形的右側和底部的位置,然後看看第二個是從第一個矩形的外側開始,還是第一個從第二個矩形的外側開始。

如果任一矩形在另一個矩形結束後開始,則不會發生碰撞。否則一定會有碰撞。

0

在我看來,我不喜歡需要很多參數的函數。

這是我會怎麼做:

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; 
}