具有旋转形状的分离轴定理

问题描述

我正在学习 SAT(分离轴定理)算法和碰撞响应,在我应用旋转之前它似乎工作正常。 如果两个碰撞形状都在旋转,它们会粘在一起并且无法解决碰撞,我猜这是由于形状旋转回对撞机。

我在碰撞检查之前一次旋转所有形状(发生在 render 方法中),但我尝试在渲染后旋转以及在渲染循环本身中旋转,这两种方法都不起作用.

sprites[0].rotate(1);
sprites[2].rotate(2);
sprites[3].rotate(5);
for (let sprite of sprites) {
    // render loop
    sprite.render(ctx);
}

没有响应,实际检测工作正常(尝试用 if (this.colliding_SAT(sprite)) { 替换第 59 行),所以我怀疑这是检测的问题,而是响应的问题。

我将如何解决这个问题,以便正确解决碰撞问题,或者 SAT 仅适用于静态形状?

// SAT colliding algorithm with response
let sprite1 = this;
let sprite2 = cand;

let overlap; // min dist to resolve collision

for (let sprite = 0; sprite < 2; sprite++) {
    if (sprite == 1) {
        // flip to avoid repetitive code
        sprite1 = cand;
        sprite2 = this;
    }

    for (let a = 0; a < sprite1.vertices.length; a++) {
        const b = (a + 1) % sprite1.vertices.length;
        // normal to sprite edge (axis projection)
        const ap = new Vector(-(sprite1.vertices[b].y - sprite1.vertices[a].y),sprite1.vertices[b].x - sprite1.vertices[a].x);

        //stablize slightly
        ap.norm();

        // find min max for both sprites
        let min1,max1,min2,max2;

        for (let p of sprite1.vertices) {
            let q = ap.dot(p);
            min1 = Math.min(min1 ?? q,q);
            max1 = Math.max(max1 ?? q,q);
        }
        for (let p of sprite2.vertices) {
            let q = ap.dot(p);
            min2 = Math.min(min2 ?? q,q);
            max2 = Math.max(max2 ?? q,q);
        }

        let op = Math.min(max1,max2) - Math.max(min1,min2);

        overlap = Math.min(op,overlap ?? op);

        if (!(max2 >= min1 && max1 >= min2))
            return false;
    }
}

// sprites are colliding
const d = new Vector(sprite2.pos.x - sprite1.pos.x,sprite2.pos.y - sprite1.pos.y);
d.norm();
sprite1.translate(overlap * d.x,overlap * d.y);

return false;

见附件 jsfiddlehttps://jsfiddle.net/sbnjxag8/

解决方法

原来我需要将位置(pos 属性)应用到每个精灵,并且由于以下行,不能将其保留为默认 0,0:const d = new Vector(sprite2.pos.x - sprite1.pos.x,sprite2.pos.y - sprite1.pos.y);

sprites.push(new Sprite({
    vertices: [
        new Vector(300,250),new Vector(320,270),new Vector(300,270)
    ],pos: new Vector(310,260)
}));