繁体   English   中英

Javascript画布碰撞检测

[英]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.xposplayer.yposplayer.widthplayer.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*size12*size2正方形是否重叠。 更改left1right1等的定义以处理一般矩形而不仅仅是正方形并使用不同的数据格式应该很容易。

具体来说, 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM