斜壁与球之间的弹性碰撞

时间:2008-12-27 23:40:19

标签: actionscript-3 collision-detection

我无法计算撞击斜墙的球的反射角度。我正在使用从此tutorial解除的算法。看起来像这样(在Actionscript 3中),p1是当前的速度向量,p2是墙的法线:

private function getReflect2(p1 : Point, p2 : Point) : Point
{

    var wallvec : Point = getNorm(p2);
    var wallnorm  : Point = p2;

    var t : Number = dotProduct(wallvec, p1);
    var n : Number = dotProduct(wallnorm, p1);
    var vt : Point = new Point(wallvec.x * t, wallvec.y * t);
    var vn : Point = new Point(wallnorm.x * -n, wallnorm.y * -n);

    var vx : Number = dotProduct(new Point(1,0), vn) + dotProduct(new Point(1,0), vt);
    var vy : Number = dotProduct(new Point(0,1), vn) + dotProduct(new Point(0,1), vt);
    return new Point(vx, vy);
}

该函数返回新的速度矢量,并且对于垂直墙壁的碰撞而不是倾斜的碰撞是正确的。球可以从两个“侧面”撞击墙壁(即,法线可能在另一个方向突出)。

有人可以发现我的错误吗?或者建议一个更好的算法?

5 个答案:

答案 0 :(得分:1)

矢量wallvec和wallnorm必须具有1的大小才能使函数起作用。我怀疑函数getNorm()为你处理wallvec的工作,但是wallnorm似乎有任意的大小。

此外,您的实现与页面上链接的算法不完全匹配。特别是,页面使用P2作为墙本身的方向。然后它对矢量进行归一化(将幅度减小到1而不改变方向)并将其复制到wallvec中。 Wallnorm接受了墙的正常(已经是1级)。

我的C实现看起来像这样。请注意,即使wnx和wny与p2c和p2y的方向相同,我仍然需要除以幅度。

void solve (double p1x, double p1y, double p2x, double p2y, double *p3x, double *p3y)
{
double wvx = -p2y / sqrt(p2x*p2x+p2y*p2y);
double wvy = p2x / sqrt(p2x*p2x+p2y*p2y);
double wnx= p2x/ sqrt(p2x*p2x+p2y*p2y);
double wny=  p2y/ sqrt(p2x*p2x+p2y*p2y);

double t = wvx*p1x+wvy*p1y;
double n = wnx*p1x+wny*p1y;

double vtx = wvx*t;
double vty = wvy*t;
double vnx = wnx*-n;
double vny = wny*-n;

*p3x=vnx+vtx;
*p3y=vny+vty;

}

答案 1 :(得分:0)

如果它适用于垂直,可能wallvec不正确。您打印出wallvec和其他值吗?

修改:当P1(1, 0)P2(0, 1)时,您能否提供所有向量值?

答案 2 :(得分:0)

我认为答案可能是关于“(即正常可能在另一个方向突出)的部分。”如果法线指向“墙壁”,则反射将通过墙壁穿过,而不是朝向您期望的方向。

答案 3 :(得分:0)

这不是你问的答案,但最后几行不必要地复杂化。由于(1,0)代表 x -axis,

dotProduct(new Point(1,0), vn)

可以替换为vn.x.因此,通过简单地引用vn和vt的适当成员,可以使函数的最后三行更加清晰:

return new Point(vn.x + vt.x, vn.y + vt.y);

我对ActionScript不太熟悉,知道是否有更方便的方法来表达矢量加法,但最好直接表达矢量加法。

答案 4 :(得分:0)

它未经测试,但这应该反映你的速度

private function reflectVectors(p1 : Point, p2 : Point) : Point
{
    // get the normalized normal
    var wallNorm:Point = p2.clone();
    wallNorm.normalize(1);

    // v1 = v - 2 * (v.n).n
    var dot:Number = p1.x * wallNorm.x + p1.y * wallNorm.y;
    var diff:Point = wallNorm.clone();
    diff.normalize(dot * -2);
    return p1.add(diff);
}