algorithm - 二维圆矩形碰撞和反射不起作用

标签 algorithm math reflection 2d collision

我有一个由矩形构建的 map 游戏,较暗的矩形(名为“封闭”)表示球应该能够移动的位置,球应该从较亮的矩形(名为“开放”)边界反射。将来我会添加更多的球,它们会相互反射。

问题出在碰撞后的新 Vector 上。

我强制函数 circleRectGetCollisionNormal() 返回 vector(-1,0) 我认为在这种情况下它是正常的(球向正确的方向移动)。 球从度数开始并将其简单地更改为矢量,这种反射适用于 45 度,但是当我将角度更改为 10 度时,球移动到更亮的矩形(名为“开放”)。

Here is how it looks like (Picture)

我是这样做的:

1-检查球是否与较亮的矩形碰撞, 2-如果它发生碰撞,我想改变方向所以我返回向量,例如球的右侧与矩形碰撞返回 [-1,0](我认为它是垂直线的法线,它指向左方向)。

3-从这个等式计算新的球移动向量:newMoveVector = oldMoveVector − (2 * dotProduct(oldMoveVector, normalVector) * normalVector)

这是每个步骤的代码:

1.

   circleRect(circlePos, circleSize, rectPos, rectSize) { 
//its rectRect collision but it doesnt matter because reflection surface is always horizontal or vertical
        let r1 = {
            left: circlePos.x - circleSize.x/2,
            right: circlePos.x + circleSize.x/2,
            top: circlePos.y - circleSize.y/2,
            bottom: circlePos.y + circleSize.y/2
        };
        let r2 = {
            left: rectPos.x,
            right: rectPos.x + rectSize.x,
            top: rectPos.y,
            bottom: rectPos.y + rectSize.y
        };  
    return !(r2.left > r1.right || 
        r2.right < r1.left || 
        r2.top > r1.bottom ||
        r2.bottom < r1.top);
    }

    isOnOpenTile(pos: Vector, size: Vector) {
        let openTiles = this.getTiles('open');
        let result = false;
        openTiles.forEach(element => {
            if( this.circleRect(pos,size,element.pos,element.size) ){
                 result = element;
                return;
            }
        });
        return result;
    }

2.

    circleRectGetCollisionNormal(c, r) {
        if(c.pos.y <= r.pos.y - (r.size.y/2)) return new Vector(0,-1);
        //Hit was from below the brick
        if(c.pos.y >= r.pos.y + (r.size.y/2)) return new Vector(0,1);
        //Hit was from above the brick
        if(c.pos.x < r.pos.x) return new Vector(1,0);
        //Hit was on left
        if(c.pos.x > r.pos.x) return new Vector(-1,0);
        //Hit was on right
        return false;
    }

3.

    getNewMoveVector(moveVector, normalVector) {
        normalVector = this.normalize(normalVector);
        let dot = (moveVector.x * moveVector.y) + (normalVector.x * normalVector.y);
        let dotProduct = new Vector(dot, dot);
        return moveVector.sub(dotProduct.mult(normalVector).mult(new Vector(2,2)));
    }

    normalize(v) {
        let length = Math.sqrt((v.x*v.x) + (v.y*v.y));
        return new Vector(v.x/length,v.y/length);
    }

这是主要功能

        getMoveVectorOnCollision(circle) {
        let coll = this.isOnOpenTile( circle.pos, circle.size );
        if( coll != false) {
            let vector = this.circleRectGetCollisionNormal(circle, coll);
            return this.getNewMoveVector(circle.moveVector, vector);
        } else return false;
    }

对象向量始终包含 2 个值,所有函数(mult、sub、div、add)都像这里一样工作。

sub(vector: Vector) {
    return new Vector(this.x - vector.x, this.y - vector.y);
}

请给我建议、实际解决方案或告诉我进行此反射(reflection)的不同方法。我浪费了 3 天多的时间试图解决这个问题,我必须继续前进。

最佳答案

您的点积计算有误。更改这些行:

let dot = (moveVector.x * moveVector.y) + (normalVector.x * normalVector.y);
let dotProduct = new Vector(dot, dot);

通过这一行:

let dotProduct = (moveVector.x * normalVector.x  + moveVector.y * normalVector.y);

请注意,dotProduct标量值,而不是矢量,因此您必须将减法矢量制作为

subvec.x = 2 * dotProduct * normalVector.x
subvec.y = 2 * dotProduct * normalVector.y

return moveVector.sub(subvec);

关于algorithm - 二维圆矩形碰撞和反射不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50543270/

相关文章:

c++ - 我想优化这个短循环

c++ - 在不违反约束的情况下生成整数数组

javascript - 以编程方式减去 SVG 路径

java - android getSystemService(String s) - 反射?

algorithm - 是否有一种算法可以寻找 3 个变量之间的数学联系?

algorithm - 如何处理机器人来计算浏览量

python - 无法理解余弦相似度的python函数

algorithm - : T(n) = 2T(n-1) + 3T(n-2)+ 1 的运行时间是多少

c# - 在 C# 中编写自定义联合(多个对象之间的连接)

java - 对象反射的安全风险是什么?