计算与作为2D线段的倾斜或倾斜壁碰撞后移动球的角度

Ben*_* Mc 1 android game-physics

如果在2D多边形内部有一个"球",由4个线段组成,可以作为边界墙,那么在与不规则倾斜的墙壁碰撞后,如何计算球的角度?

如果墙壁是水平的,垂直的或者是45度角,我知道如何使球反弹.我也有我的代码设置来检测与墙壁的碰撞.

我已经阅读了关于点积和法线的内容,但我无法弄清楚如何在Java/Android中实现它们.我完全感到难过,觉得我现在已经10次在Google中查找了10页.我已经烧坏了试图解决这个问题,我希望有人可以提供帮助.

Tom*_*mmy 8

提前道歉:我不知道正确的Android类型.我假设你有一个属性为'x'和'y'的矢量类型.

如果墙是水平的并且当前速度是"矢量"那么它就像下面那样容易:

vector.y = -vector.y;
Run Code Online (Sandbox Code Playgroud)

而你只留下x组件.所以你需要做一些类似的事情,但更一般.

您可以通过替换线法线(垂直于线的矢量)的概念来对y轴(垂直于水平线)进行硬编码.

由于法线与线正交,因此可以通过将线旋转90度来找到.在2d中,通过将矢量(a,b)转换为(-b,a),可以将矢量(a,b)旋转90度.因此,如果你有一条从(x1,y1)到(x2,y2)的线,你可以得到正常的:

vectorAlongLine.x = x2 - x1;
vectorAlongLine.y = y2 - y1;

normal.x = -vectorAlongLine.y;
normal.y = vectorAlongLine.x;
Run Code Online (Sandbox Code Playgroud)

实际上你并不关心原始行的长度(并且当你不希望它时它会影响计算),所以你想使长度为1的法线无论其当前长度如何.您可以通过将其除以当前长度来实现.所以,例如

lengthOfNormal = Math.sqrt(normal.x*normal.x + normal.y*normal.y);
normal.x /= lengthOfNormal;
normal.y /= lengthOfNormal;
Run Code Online (Sandbox Code Playgroud)

使用毕达哥拉斯定理得到长度.

对于水平线,在y轴上的翻转与(i)计算向量的范围沿y轴延伸的内容相同; (ii)减去该数量两次 - 一次使速度在该方向上为0,再次使其成为原始的负版本.也就是说,它与:

distanceAlongNormal = vector.y;
vector.y -= 2.0 * distanceAlongNormal;
Run Code Online (Sandbox Code Playgroud)

在一般情况下使用的点积是用于向量沿法线延伸多远.因此它与采用vector.y对水平线的作用相同.这是你可能需要一点点信仰的地方.它是点积的属性,您可以通过检查直角三角形来说服自己.但是现在,如果你有一条水平线,你最终会得到正常值(0,1).由于点积将是:

vector.x * normal.x + vector.y * normal.y
Run Code Online (Sandbox Code Playgroud)

你计算:

distanceAlongNormal = vector.x * 0.0 + vector.y * 1.0;
Run Code Online (Sandbox Code Playgroud)

这显然与仅采用y组件相同.

在计算出法线距离之后,你实际上想要减去那个数量乘以正常时间2.这里唯一的额外步骤是乘以法线得到2d数量减去.那是因为你想要按正常顺序减去.所以完整的代码,基于之前计算的法线,是:

distanceAlongNormal = vector.x * normal.x + vector.y * normal.y;
vector.x -= 2.0 * distanceAlongNormal * normal.x;
vector.y -= 2.0 * distanceAlongNormal * normal.y;
Run Code Online (Sandbox Code Playgroud)

如果你没有使长度为1的法线,那么你需要除以这里的长度,因为点积会将distanceAlongNormal值缩放该量.