想要让一个物体在圆圈内反弹,最终使物体沿着圆圈移动

这是有问题的代码:

public void calculate() { // Center of circle is at (250, 250). //THIS ALGORITHM IS NOW PROVEN TO BE WORSE THAN I FEARED... /* What it does: * Moves object around in a circle. * Does not move the object towards the center. * Object always stays on the rim of the circle. * * Algorithm I used. (DOES NOT WORK): * N is normalized vector. * R = -2*(V dot N)*N + V */ vx += Accelero.X * 0.1; vy += Accelero.Y * 0.1; double nx = x - 250; double ny = y - 250; double nd = Math.hypot(nx, ny); if (nd == 0) nd = 1; nx /= nd; ny /= nd; double dotProduct = vx * nx + vy * ny; vx += (float) (-2 * dotProduct * nx); vy += (float) (-2 * dotProduct * ny); x -= vx * 2; y -= vy * 2; vx *= 0.99; vy *= 0.99; } 

这就是发生的事情。

图片。

你看到的黑线是紫色物体(盒子)移动的地方。 它恰好恰好在我用Canvas.drawCircle()绘制的圆圈线上。

我不明白为什么反思不起作用。 如果一个物体要撞到一个圆形墙壁,它不应该反映物体的速度方向,这就是算法的意图吗? 或者我使用了错误的算法?

任何帮助表示赞赏。 提前致谢。

你可以从任意角度的直墙上弹跳吗? 这应该是第一步。 (您可能会发现速度矢量的极坐标表示更容易使用。)

一旦你有了这个工作,它应该是相当简单的:从圆圈反弹就像从接触点接触它的那个圆的切线反弹。

您可以通过观察它垂直于接触点中的半径向量(即从对象到圆心的位置指向的向量)来计算此切线。

是否存在基于矢量的实现,而不依赖于角度?

是的,请参阅此KineticModel所示的没有三角函数的二维弹性碰撞 。 您的实现似乎缺少切向组件。 有关详细信息,请参阅Ensemble#collideAtoms()

这就是我所拥有的,我将把你的发现分享给大家。

 public void calculate() { // Center of circle is at (250, 250). Radius is 40. //THIS ALGORITHM IS PROVEN TO BE BETTER THAN I FEARED... /* What it does: * Moves object around in a circle, if object is * inside of circle. * Does not move the object towards the center, * nor outwards. This is crucial. * Object always stays on the rim of the circle, * if the collision detection allows it to. * * Algorithm I used. (DOES WORK, NOT EXPECTING THIS THOUGH.): * N is normalized vector. * R = -2*(V dot N)*N + V */ double nx = x - 250; double ny = y - 250; double nd = Math.hypot(nx, ny); if (nd < 40){ vx += Accelero.X * 0.1; vy += Accelero.Y * 0.1; x -= vx; y -= vy; vx *= 0.9; vy *= 0.9; return; } vx += Accelero.X * 0.1; vy += Accelero.Y * 0.1; if (nd == 0) nd = 1; nx /= nd; ny /= nd; double dotProduct = vx * nx + vy * ny; vx += (float) (-2 * dotProduct * nx); vy += (float) (-2 * dotProduct * ny); x -= vx * 2; y -= vy * 2; vx *= 0.99; vy *= 0.99; } 

我在我的函数中嵌入了一个碰撞检测,基本上使这个函数不尽可能高效。 忽略这一点,因为它不是主要焦点。

圆的半径为40,(x,y)位置为(250,250)。

只有当物体在圆上或远离圆心时,我们才能计算出碰撞响应,这是由算法R = -2 *(V点N)* N + V给出的,其中法向量N已经标准化。

算法确实是正确的,它是我的碰撞检测的布尔条件,是导致物体停留在圆圈边缘并绕过它的原因。

我没有说@trashgod提供的其他算法是错误的。 这是因为一些奇怪的问题导致对象exception移动。 我猜这是我使用的API的错误,它不允许双打,但我可能是不正确的。 我只是找不到问题的根源。 我也很高兴不再深入研究它了。

碰撞检测布尔条件本身可以改变一切,如果它稍有改变。 如果不是@nm指向我似乎忘了一个减号(在这种情况下,一个NOT符号),我可能永远不会意识到它会是多么微不足道。