1

我正在使用 AS3 为 Flash 游戏编写一些碰撞检测程序,但在弄清楚如何将球从线上弹起时遇到了麻烦。我跟踪表示球的 2D 速度的向量,并试图将其反映在垂直于球碰撞线(也称为法线)的向量上。我的问题是我不知道如何找出新向量(这反映在法线上)。我认为您可以使用 Math.atan2 来查找法线向量和球向量之间的差异,但我不确定如何扩展它来解决我的问题。

4

3 回答 3

5

矢量代数 -你想要“反弹”矢量:
vec1 是球的运动矢量,vec2 是表面/线矢量:

// 1. Find the dot product of vec1 and vec2
// Note: dx and dy are vx and vy divided over the length of the vector (magnitude)
var dpA:Number = vec1.vx * vec2.dx + vec1.vy * vec2.dy;

// 2. Project vec1 over vec2
var prA_vx:Number = dpA * vec2.dx;
var prA_vy:Number = dpA * vec2.dy;

// 3. Find the dot product of vec1 and vec2's normal
// (left or right normal depending on line's direction, let's say left)
var dpB:Number = vec1.vx * vec2.leftNormal.dx + vec1.vy * vec2.leftNormal.dy;

// 4. Project vec1 over vec2's left normal
var prB_vx:Number = dpB * vec2.leftNormal.dx;
var prB_vy:Number = dpB * vec2.leftNormal.dy;

// 5. Add the first projection prA to the reverse of the second -prB
var new_vx:Number = prA_vx - prB_vx;
var new_vy:Number = prA_vy - prB_vy;

将这些速度分配给球的运动矢量并让它弹跳。

PS:
vec.leftNormal --> vx = vec.vy; vy = -vec.vx;
vec.rightNormal --> vx = -vec.vy; vy = vec.vx;

于 2013-02-14T23:45:05.787 回答
1

可以使用投影张量计算任何向量v从具有法线n在任何维度上的线/(超)曲面的镜面反射。vn上的平行投影为:v || = ( v . n ) n = vnn。这里nn是法线与自身的外(或张量)乘积。在笛卡尔坐标中,它是一个包含元素的矩阵:nn[i,j] = n[i]*n[j]。垂直投影只是原始向量与其平行投影之间的差异:v - v||。当矢量被反射时,它的平行投影被反转,而垂直投影被保留。所以反射向量为:

v ' = - v || + ( v - v ||) = v - 2 v || = v。( I - 2 nn ) = vR ( n ),其中
R ( n ) = I - 2 nn

I是单位张量,在笛卡尔坐标中只是对角单位矩阵diag(1)

R称为反射张量。在笛卡尔坐标系中,它是一个具有分量的实对称矩阵R[i,j] = delta[i,j] - 2*n[i]*n[j],其中delta[i,j] = 1ifi == j0else。它也是关于n对称的:

R ( - n ) = I - 2(- n )(- n ) = I - 2 nn = R ( n )

因此,使用向外或向内的法线n并不重要- 结果是相同的。

在二维和笛卡尔坐标中,RR的矩阵表示)变为:

    [ R00  R01 ]   [ 1.0-2.0*n.x*n.x     -2.0*n.x*n.y ]
R = [          ] = [                                  ]
    [ R10  R11 ]   [    -2.0*n.x*n.y  1.0-2.0*n.y*n.y ]

然后将反射向量的分量计算为行向量矩阵乘积:

v1.x = v.x*R00 + v.y*R10
v1.y = v.x*R01 + v.y*R11

或扩展后:

k = 2.0*(v.x*n.x + v.y*n.y)
v1.x = v.x - k*n.x
v1.y = v.y - k*n.y

在三个维度:

k = 2.0*(v.x*n.x + v.y*n.y + v.z*n.z)
v1.x = v.x - k*n.x
v1.y = v.y - k*n.y
v1.z = v.z - k*n.z

找到球击中线/墙的确切点更复杂 - 请参见此处

于 2013-02-15T10:40:24.673 回答
0

计算向量的两个分量。

一个组件将是您的矢量在反射表面上的投影,另一个组件将是在表面法线上的投影(您说您已经拥有)。使用点积来获得投影。通过对两个向量求和来将这两个分量相加。你会有你的答案。

您甚至可以将第二个分量 A2 计算为原始向量减去第一个分量,因此:A2 = A - A1。然后你想要的向量是 A1 加上反射的 A2 (这只是 -A2 因为它垂直于你的表面)或:

Ar = A1-A2

或者

Ar = 2A1 - A 与 Ar = -(2A2 - A) 相同

如果 [Ax,Bx] 是你的球速度并且 [Wx,Wy] 是代表墙壁的单位向量:

A1x = (Ax*Wx+Ay*Wy)*Wx;

A1y = (Ax*Wx+Ay*Wy)*Wy;

Arx = 2*A1x - Ax;

Ary = 2*A1y - Ay;

于 2013-02-14T23:25:21.510 回答