TeN*_*NoX 7 java 2d collision-detection
我只是想编写一个漂亮的物理游戏.
球碰撞看起来不错,但如果球碰撞得太慢,它们会互相"粘".我不知道他们为什么这么做.
这是我的碰撞功能:
private void checkForCollision(ArrayList<Ball> balls) {
for (int i = 0; i < balls.size(); i++) {
Ball ball = balls.get(i);
if (ball != this && ball.intersects(this)) {
this.collide(ball, false);
}
}
}
public boolean intersects(Ball b) {
double dx = Math.abs(b.posX - posX);
double dy = Math.abs(b.posY - posY);
double d = Math.sqrt(dx * dx + dy * dy);
return d <= (radius + b.radius);
}
private void collide(Ball ball, boolean b) {
double m1 = this.radius;
double m2 = ball.radius;
double v1 = this.motionX;
double v2 = ball.motionX;
double vx = (m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);
v1 = this.motionY;
v2 = ball.motionY;
double vy = (m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);
if (!b)
ball.collide(this, true);
System.out.println(vx + " " + vy);
motionX = vx * BOUNCEOBJECT;
motionY = vy * BOUNCEOBJECT;
}
Run Code Online (Sandbox Code Playgroud)
但是当它们以低速碰撞时会发生这种情况:

你有什么想法吗?
编辑:
Alnitak的更新非常好......但是仍有一个问题......如果我像这样添加引力:
public void physic() {
motionY += GRAVITY; // <= this part (GRAVITY is set to 0.3D)
checkForCollision(screen.balls);
keyMove();
bounceWalls();
posX += motionX;
posY += motionY;
}
Run Code Online (Sandbox Code Playgroud)
他们仍然相互移动.我认为这是增加引力的错误方法,或者不是吗?
而且我认为碰撞公式我做错了,因为它们不合适:
!
然后他们慢慢沉入地下.
编辑: 找到一个令人惊叹的教程:http : //www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BouncingBalls.html
这是一个常见的问题,因为有时弹跳球的delta-v不足以将其从碰撞区带回.
因此,碰撞程序再次反转方向,将其带回到另一个球内,无限制.
您应该在球的位置添加足够的偏移(在碰撞力的方向上),以确保新计算的位置不再发生碰撞.
或者,在添加新值后检查球是否会发生碰撞motion:
public boolean intersects(Ball b) {
double dx = b.posX - (posX + motionX); // no need for Math.abs()
double dy = b.posY - (posY - motionY);
double d = dx * dx + dy * dy; // no need for Math.sqrt()
return d < (radius + b.radius) * (radius + b.radius);
}
Run Code Online (Sandbox Code Playgroud)
但你也应该ball.intersects(this)改为intersects(ball).
它们可能看起来有点过早碰撞,但在快速移动的球上它可能不会被看到.
(m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);
Run Code Online (Sandbox Code Playgroud)
它的整数值为 2。请将其设置为 2.0f 或 2.0d,然后检查。这一定是小速度的问题。因为整数常量会自动转换乘法双精度数。
如果这不起作用,那么Alnitak的答案将会有所帮助。
如果您需要真正好的物理效果,您应该使用力,然后将其转换为速度,然后将其转换为位移。查看Runge Kutta和Euler Integration等积分器技术
Force-->acceleration-->velocity-->displacement
Run Code Online (Sandbox Code Playgroud)
如果发生碰撞,只需更新力即可,其余部分将流动。
----> http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ <-----
http://www.forums.evilmana.com/game-programming-theory/euler-vs-verlet-vs-rk4-physicals/
http://www.newagepublishers.com/samplechapter/001579.pdf
http://cwx.prenhall.com/bookbind/pubbooks/walker2/
Verlet 积分是Runge-Kutta-4和Euler 积分之间的一个点,适用于分子动力学(如果省略电场和键,则这是弹跳球的一个很好的例子)