在Stack Overflow社区的帮助下,我编写了一个非常基本但有趣的物理模拟器。
单击并拖动鼠标以启动球。它会反弹并最终停在“地板”上。
我要添加的下一个重要功能是球与球之间的碰撞。球的运动分为轴速度和y速度向量。我有重力(每个步骤y向量的小减小),我有摩擦力(每个与壁碰撞的两个向量的小减小)。球以令人惊讶的现实方式诚实地移动。
我想我的问题分为两个部分:
- 检测球与球碰撞的最佳方法是什么?
我是否只有O(n ^ 2)循环遍历每个球并检查其他每个球以查看其半径是否重叠? - 我使用什么方程式来处理球与球之间的碰撞?物理101
如何影响两个球的x / y向量速度?两个球朝哪个方向前进?如何将此应用于每个球?
处理“墙”的碰撞检测和所产生的矢量变化很容易,但我发现球与球之间的碰撞会更加复杂。对于墙,我只需要取适当的x或y向量的负值,然后沿正确的方向走即可。对于球,我认为不是那样。
一些快速的澄清:为简单起见,我现在可以进行完全弹性的碰撞,而且我的所有球现在都具有相同的质量,但将来可能会改变。
编辑:我发现有用的资源
带矢量的2d球物理:没有Trigonometry.pdf的
二维碰撞。pdf2d球碰撞检测示例:添加碰撞检测
成功!
我的球碰撞检测和响应效果很好!
相关代码:
碰撞检测:
for (int i = 0; i < ballCount; i++)
{
for (int j = i + 1; j < ballCount; j++)
{
if (balls[i].colliding(balls[j]))
{
balls[i].resolveCollision(balls[j]);
}
}
}
这将检查每个球之间的碰撞,但跳过多余的检查(如果您必须检查第1球是否与第2球碰撞,则无需检查第2球是否与第1球碰撞。而且,它也跳过对自身的碰撞的检查。 )。
然后,在我的ball类中,我有colliding()和resolveCollision()方法:
public boolean colliding(Ball ball)
{
float xd = position.getX() - ball.position.getX();
float yd = position.getY() - ball.position.getY();
float sumRadius = getRadius() + ball.getRadius();
float sqrRadius = sumRadius * sumRadius;
float distSqr = (xd * xd) + (yd * yd);
if (distSqr <= sqrRadius)
{
return true;
}
return false;
}
public void resolveCollision(Ball ball)
{
// get the mtd
Vector2d delta = (position.subtract(ball.position));
float d = delta.getLength();
// minimum translation distance to push balls apart after intersecting
Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / ball.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2d v = (this.velocity.subtract(ball.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse
float i = (-(1.0f + Constants.restitution) * vn) / (im1 + im2);
Vector2d impulse = mtd.normalize().multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
ball.velocity = ball.velocity.subtract(impulse.multiply(im2));
}
如果有人对如何改进此基本物理模拟器有任何建议,请告诉我!我要补充的一件事是角动量,这样球将更真实地滚动。还有其他建议吗?发表评论!
Vector2d impulse = mtd.multiply(i);
应为i *归一化的mtd向量。像这样的东西:Vector2d impulse = mtd.normalize().multiply(i);