JAVA移动和非移动圆的弹性碰撞

时间:2014-04-20 09:16:28

标签: java math physics collision geometry

我正在尝试编写一个Java移动应用程序(J2ME),我遇到了一个问题:在我的项目中有移动的圆圈称为镜头,而非移动的圆圈称为orbs。当射击击中球体时,它应该通过经典的物理定律反弹。但是我找不到这种算法。

镜头的移动由轴x和y上的速度(像素/更新)描述。所有关于圆圈的信息都是已知的:它们的位置,半径和镜头的速度(在轴x和y上)。

注意:碰撞后球体不会开始移动,它会停留在原位。碰撞是两者之间的弹性碰撞,而球体保持静止

这是Shot类中的碰撞解决方法:

public void collision(Orb o)
{
    //the orb's center point
    Point oc=new Point(o.getTopLeft().x+o.getWidth()/2,o.getTopLeft().y+o.getWidth()/2);
    //the shot's center point
    Point sc=new Point(topLeft.x+width/2,topLeft.y+width/2);

    //variables vx and vy are the shot's velocity on axis x and y
    if(oc.x==sc.x)
    {
        vy=-vy;
        return ;
    }

    if(oc.y==sc.y)
    {
        vx=-vx;
        return ;
    }

    // o.getWidth() returns the orb's width, width is the shot's width

    double angle=0;  //here should be some sort of calculation of the shot's angle
    setAngle(angle);
}

public void setAngle(double angle)
{
    double v=Math.sqrt(vx*vx+vy*vy);
    vx=Math.cos(Math.toRadians(angle))*v;
    vy=-Math.sin(Math.toRadians(angle))*v;
}

提前感谢所有帮助者

2 个答案:

答案 0 :(得分:1)

在碰撞点,动量,角动量和能量得以保留。设m1,m2为磁盘质量,p1 =(p1x,p1y),p2 =(p2x,p2y)磁盘中心在碰撞时的位置,u1,u2为速度前的速度,v1,v2为速度后的速度碰撞。然后保护法要求

0 = m1*(u1-v1)+m2*(u2-v2)
0 = m1*cross(p1,u1-v1)+m2*cross(p2,u2-v2)
0 = m1*dot(u1-v1,u1+v1)+m2*dot(u2-v2,u2+v2)

使用第一个等式消除u2-v2

0 = m1*cross(p1-p2,u1-v1)
0 = m1*dot(u1-v1,u1+v1-u2-v2)

第一个告诉我们(u1-v1)因而(u2-v2)是(p1-p2)的倍数,脉冲交换是在正常或径向方向,没有切向相互作用。脉冲和能量的守恒现在导致相互作用常数a,因此

u1-v1 = m2*a*(p1-p2)
u2-v2 = m1*a*(p2-p1)
0 = dot(m2*a*(p1-p2), 2*u1-m2*a*(p1-p2)-2*u2+m1*a*(p2-p1))

导致非零交互项a

的条件
2 * dot(p1-p2, u1-u2) = (m1+m2) * dot(p1-p2,p1-p2) * a

现在可以使用分数

来解决
b = dot(p1-p2, u1-u2) / dot(p1-p2, p1-p2)

作为

a = 2/(m1+m2) * b

v1 = u1 - 2 * m2/(m1+m2) * b * (p1-p2)
v2 = u2 - 2 * m1/(m1+m2) * b * (p2-p1)

要使第二个磁盘静止,设置u2 = 0且其质量m2非常大或无穷大,则第二个公式表示v2 = u2 = 0且第一个


  

v1 = u1 - 2 * dot(p1-p2,u1)/ dot(p1-p2,p1-p2)*(p1-p2)


也就是说,v1是在平面上具有(p1-p2)的u1的反射。请注意,碰撞点的特征是norm(p1-p2)=r1+r2

dot(p1-p2, p1-p2) = (r1+r2)^2

以便从碰撞检测中得知分母。


根据您的代码,oc{x,y}包含固定磁盘或orb的中心,sc{x,y}中心和{vx,vy}移动磁盘的速度。

  1. 计算dc={sc.x-oc.x, sc.y-oc.y}dist2=dc.x*dc.x+dc.y*dc.y

    1.a检查sqrt(dist2)是否足够接近sc.radius+oc.radius。常见的传说说,比较正方形更有效。如果dist2太小,则微调交点的位置。

  2. 计算dot = dc.x*vx+dcy*vydot = dot/dist2

  3. 更新vx = vx - 2*dot*dc.xvy = vy - 2*dot*dc.y

  4. 特殊情况包含在这些公式中,例如dc.y==0,即oc.y==sc.y得到dot=vx/dc.x,以便vx=-vxvy=vy结果

答案 1 :(得分:0)

考虑到一个圆是静态的,我会说包括能量和动量是多余的。只要移动球在碰撞前后具有相同的速度,系统的动量就会被保留。因此,你唯一需要改变的是球移动的角度。

如果你能用矢量数学解决问题,我知道有很多反对使用三角函数的意见。但是,一旦你知道了两个圆圈之间的接触点,处理这个问题的三角学方法就是这么简单:

dx = -dx; //Reverse direction
dy = -dy;
double speed = Math.sqrt(dx*dx + dy*dy);
double currentAngle = Math.atan2(dy, dx);

//The angle between the ball's center and the orbs center
double reflectionAngle = Math.atan2(oc.y - sc.y, oc.x - sc.x);
//The outcome of this "static" collision is just a angular reflection with preserved speed
double newAngle = 2*reflectionAngle - currentAngle;

dx = speed * Math.cos(newAngle); //Setting new velocity
dy = speed * Math.sin(newAngle);

在计算中使用orb的坐标是一种近似值,在执行此方法时,您的镜头越接近实际影响点,精度越高。因此,您可能希望执行以下操作之一:

  1. 用实际撞击点替换orb的坐标(稍微准确一点)
  2. 将影片的坐标替换为影响将/确实发生的位置。这是关于结果角度的最佳情景,但与完全真实的情景相比可能导致轻微的位置偏移。