计算 ball/point 的弹跳角度

Calculate the bouncing angle for a ball/point

我正在构建自己的小型游戏引擎以供学习。所以基本纯Java。我有由起点和终点(x 和 y 坐标)定义的线

现在我有了一个带有速度矢量的球。我想 "bounce" 离墙,它可以放置在任何可能的角度。碰撞发生后如何找出新的速度矢量?我知道点 S、P1 和 P2(见图)

我考虑过计算角度,并更改 x 和 y 分量。但我无法找到一种方法如何针对所有可能的角度执行此操作。

对于平行于 canvas 边界的墙,我可以找到很多解决方案,但没有通用的解决方案。 "big" 游戏引擎如何处理这个常见问题?

编辑

我更新的 Vector class 方法:

public static Vector bounce(Vector normal, Vector velocity) {
    Vector tmp = Vector.multiplication(2*Vector.dot(normal,velocity), normal);
    return Vector.addition(tmp, velocity);
}

public static Vector multiplication(double multi, Vector n) {
    Vector new_vector = new Vector(n.x * multi, n.y * multi);
    return new_vector;
}

public static double dot(Vector a, Vector b) {
    return a.x*b.x + a.y*b.y; // + a.z*b.z if you're in 3D
}

我的测试函数:

@Test
   public void testBounce() {
        Vector normal_vector_corrected = new Vector(0, 1);
        Vector start_velocity = new Vector(3, -3);
        Vector bounced_vector = Vector.bounce(normal_vector_corrected, start_velocity);
        System.out.println("normal vector: "+normal_vector_corrected);
        System.out.println("start_velocity: "+start_velocity);
        System.out.println("bounced_vector "+bounced_vector);
    }

输出是这样的:

normal vector: <Vector x=0,00, y=1,00>
start_velocity: <Vector x=3,00, y=-3,00>
bounced_vector <Vector x=3,00, y=-9,00>

根据我的计算,bounced_vector应该是x=3,y=3。我的错误在哪里? (我的例子如图:)

编辑2: 我发现它必须是return Vec.add(tmp, v);。此外,我必须反转速度矢量。

"bounced velocity vector"v'由原始速度v表面法线单位向量n得到[= =15=] 其中 . 代表 向量点积 。这通常称为反射;速度矢量反映在表面法线上。

如果您不熟悉这些术语,表面法线是垂直于表面(成 90 度角)的矢量。单位向量是长度为 1 的向量。

我假设您已经有一个 class 来表示向量,称为 Vec,具有将向量与标量相乘以及将两个向量相加的方法。您可以将反弹操作写为:

static Vec bounce(Vec n, Vec v) {
    Vec tmp = Vec.scalarMultiply(-2*Vec.dot(n,v), n);
    return Vec.add(tmp, v);
}

static double dot(Vec a, Vec b) {
    return a.x*b.x + a.y*b.y; // + a.z*b.z if you're in 3D
}

至于如何让表面法线,那要看你是2D还是3D了。假设二维,很简单:如果 (x,y) 是从 P1 到 P2 的向量,那么 (-y,x) 垂直于它,并且 one 单位法线将是:

n = (-y/sqrt(x*x+y*y), x/sqrt(x*x+y*y))

另一个可能的正常单位是-n。您将使用一个或另一个取决于您在表面的哪一侧。

您应该将法向量与场景的几何形状一起存储,这样您就不必每次都计算它。