2

我无法计算球撞击斜墙的反射角。我正在使用从本教程中提取的算法。它看起来像这样(在 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);
}

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

谁能发现我的错误?或者建议更好的算法?

4

5 回答 5

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;

}
于 2008-12-28T00:37:31.410 回答
0

这不是您所问问题的完全答案,但最后几行不必要地复杂。由于 (1, 0) 代表x轴,

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

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

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

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

于 2009-01-03T03:36:54.437 回答
0

it's untested, but this should reflect your velocity

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);
}
于 2009-02-06T22:52:53.737 回答
0

如果它适用于垂直,也许 wallvec是不正确的。你有没有打印出wallvec 其他值?

编辑P1:你能在is(1, 0)P2is时提供所有的向量值(0, 1)吗?

于 2008-12-27T23:51:31.847 回答
0

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

于 2008-12-28T00:00:30.547 回答