2011-11-05 161 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; 
}