使用JavaScript检查画布上的两个项目是否重叠

4

我有一个画布,正在使用地理定位、谷歌地图和openweathermap 来获取用户所在地的天气。获取到的天气将被应用到我正在制作的游戏中...

如何检测两个生成在画布上的正方形是否重叠?这是下雨代码,它目前看起来与下雨无关...

function rectangle(x, y, w, h) {
    var randomx = Math.floor(Math.random() * canvas.width - 50);
    this.x = randomx || x || 0;
    this.y = y || 0;
    this.w = w || 0;
    this.h = h || 0;
    this.expired = false;

    this.draw = function() {
        cx.fillStyle = "blue";
        cx.fillRect(this.x, this.y, this.w, this.h);
    };

    this.update = function() {
        this.y++;
            if (y > canvas.height) {
                this.expired = true;
            }
    };
}

var rectangles = new Array();
function newRect() {
    rectangles.push(new rectangle(window.randomx, window.y, 10, 10));
}
var timing = 0;

function loop() {
    cx.clearRect(0, 0, canvas.width, canvas.height);
    if (timing % 10 === 0) {
        newRect();
    }

    for (var i = 0, l = rectangles.length; i < l; i++) {
        rectangles[i].update();
        rectangles[i].draw();
        if (rectangles[i].expired) {
            rectangles.splice(i, 1);
            i--;
        }
    }
    timing++;
    requestAnimFrame(loop);
}
loop();

我的假设是,我需要执行一个“命中测试”来查看数组中的两个矩形是否在同一周长内... 我猜想,在这个.draw和.update函数所在的位置,我应该做些什么...

this.hitTest = function () {
    //Maths to check here
};

然后在for循环中做...
rectangles[i].hitTest();

但是我不确定数学部分或接下来该怎么做...

任何帮助将不胜感激,谢谢!


我上周参加了一个黑客马拉松比赛,并第一次使用画布元素。我发现这个是一种有效的管理画布框架的方式,很好地实现了事件驱动。同时,我还发现这篇教程非常有帮助。 - Lawrence Jones
@LawrenceJones,非常感谢您提供的这两个方案,看起来都非常有趣。但是我忘了提到我不能使用任何框架或外部库。必须在没有它们的情况下完成。 - user3045449
丹,这些解决方案都没有使用任何外部库。虽然第一个链接可能被Angular包围,但它并不依赖于它。最终只是纯JavaScript。 - Lawrence Jones
1个回答

8
您可以像这样扩展您的rectangle对象:
function rectangle(x, y, w, h) {

    ... existing code here ...

}

rectangle.prototype.intersects = function(rect) {
    return !( rect.x           > (this.x + this.w) || 
             (rect.x + rect.w) <  this.x           || 
              rect.y           > (this.y + this.h) ||
             (rect.y + rect.h) <  this.y);
}

基于Daniel Vassallo的这段代码,为您的对象进行了调整。

现在只需在要比较的矩形上调用该函数:

 if ( rectangles[x].intersects(rectangles[y]) ) {
     ... they intersect ...
 }

要检查新矩形是否与现有矩形相交,您可以执行以下操作:

function isOverlapping(myNewRect, rectangles) {

    for(var i = 0, r; r = rectangles[i]; i++) {
        if (myNewRect.intersect(r)) return true;
    }
    return false;
}

我理解这背后的逻辑,也明白为什么它应该可以工作,但是为什么它们仍然重叠呢?我还尝试在if语句内部放置console.log();,但控制台中没有显示任何内容。 - user3045449
@Dan,我可能误解了你的问题... 我理解为你想检测两个矩形是否重叠(或相交)?如果你还需要防止这种情况发生(如果它们确实重叠),你可以简单地移除重叠的矩形或不绘制它。 - user1693593
我想检查两个矩形是否相互重叠,即使它们只有1像素的角落重叠。我知道我应该删除它,但我不知道如何检查矩形是否尝试生成已被占用的位置。 - user3045449
@Dan 对不起,昨天有1k个中断,很忙。我已经更新了答案。不过,答案的主要重点是如何检测交集。如果你认为这回答了问题,请考虑接受/点赞。 - user1693593
没问题!但是我刚刚看了你更新的答案,现在已经搞定了!非常感谢你的帮助。 - user3045449
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接