2011-07-22 41 views
1

我已经用Java创建了一个带有用户界面的弹丸运动模拟。 该程序允许用户输入初始值来计算物体的抛射物。我目前没有任何东西可以将弹丸吸引到屏幕上。弹丸运动的实现

我有一个单独的弹簧工作线程在后台处理模拟代码。

我还添加了碰撞检测功能,以便当物体碰到地面时它会弹起并继续这样做,直到环路退出。

我所在的方程式对于我所要达到的目标并不正确。

用下面的初始条件,这里是输出的数据率的情节是什么:

Initial Conditions: 
Angle: 30 degrees; 
Initial Speed 8.66 m/s; 
Height: 50 m; 
Elasticity of object: .5 coefficient of restitution in the y direction; 
Acceleration: -9.8 m/s^2; 
No acceleration in the x direction 

enter image description here

看来,一旦模拟开始,Y只是变得越来越大,因此,循环将永远不会退出。

下面是代码:

//This class will handle all time consuming activities 
class Simulation extends SwingWorker<Void, Void> 
{ 
    //Execute time consuming task 
    protected Void doInBackground() throws Exception 
    { 
     FileWriter fstream = new FileWriter("output.txt"); 

     BufferedWriter out = new BufferedWriter(fstream); 

     double angle = Double.valueOf(angleText.getText()); 
     double radians = angle * (Math.PI/180); 
     double vel = Double.valueOf(speedText.getText()); 
     double mass = Double.valueOf(massText.getText()); 
     double y = Double.valueOf(heightText.getText()); 
     double x = 0; 
     double epX = Double.valueOf(epxText.getText()); 
     double epY = Double.valueOf(epyText.getText()); 
     double ax = Double.valueOf(accxText.getText()); 
     double ay = Double.valueOf(accyText.getText()); 

     int numBounces = 0; 
     double deltaTime = .00000001; 
     double total_velocity = 0.0; 
     double time = 0.0; 

     String fs; 

     angle = angle * Math.PI/180; 

     while(numBounces < 10) 
     { 
      //Increment Time 
      time = time + deltaTime; 

      //Calculate new values for velocity[x] and velocity[y] 
      double vx = (vel*Math.cos(angle)) + ax*time;; 
      double vy = (vel*Math.sin(angle)) + ay*time; 

      //Calculate new values for x and y 
      x = x + vx*time; 
      y = y + vy*time + .5*ay*(time*time); 

      System.out.format("%.3f\n", y); 

      fs = String.format("%f\t %f\t %f\t %f\t %f\t %f\t %f\t\n", ax, ay, x, y, vx, vy, time); 

      out.write(fs); 

      //If ball hits ground: y < 0 
      if(y < 0) 
      { 
       numBounces++; 

       System.out.println("Number of Bounces: " + numBounces); 

       //Why is this statement needed if the velocity in the y direction is already being reversed? 
       vy = -vy - ay*time; // vy = -vy - ay*time; 

       //Calculate angle 
       angle = Math.atan(vy/vx); 

       angle = angle * Math.PI/180; 

       //Calculate total velocity 
       total_velocity = Math.sqrt((vy*vy) + (vx*vx)); 

       //Velocity with elasticity factored in 
       total_velocity = Math.sqrt((epY) * total_velocity); 

       //New velocities for when ball makes next trip 
       vy = total_velocity*Math.sin(angle); 
       vx = total_velocity*Math.cos(angle); 

       out.write(fs); 

      } 

      //Draw projectile 

       //Thread.sleep(.00001); //Sleep for deltaTime - 10 nanoseconds or draw after n number of points 
     } 

     out.close(); 

     return null; 
    } 

    //SwingWorker lets you execute code on the event dispatching thread. Also allows you to update the GUI 
    public void done() 
    { 
     try 
     {    
      /* 
      rangeText.setText(" " + x); 
      heightTText.setText(" " + y); 
      timeText.setText(" " + time); 
      */ 
     } 

     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

可能是什么可能出现的问题? 我的猜测是它可能与角度有关。在之前版本的代码中,我没有考虑角度,它运行良好。另外,我不确定是否必须设置GUI界限,以便y不会永远持续下去。

我也有一个NullPointerException。

+0

NullPointerException提取不是堆栈跟踪,这可能很有用 - 相反,它显示的是NullPointerException类的字节码 - 它永远不会改变,因此不会提供对问题的深入了解。把你的后台任务包装在try/catch块中,该块捕获Throwable并执行printStackTrace。 –

回答

2

我看到的第一个问题是在这里:

//Calculate angle 
angle = Math.atan(vy/vx); 
angle = angle * Math.PI/180; 

Math.atan返回弧度已经值:

返回一个值的反正切;返回的角度在-pi/2到pi/2的范围内。

所以* Math.PI/180是不会对你有任何好处的。

第二个问题是在这里:

//Calculate new values for velocity[x] and velocity[y] 
double vx = (vel*Math.cos(angle)) + ax*time;; 
double vy = (vel*Math.sin(angle)) + ay*time; 

每次通过循环,这些值重新初始化。因为angle,ax,aytime在循环过程中不能更改,这意味着您总是以相同的vx和(正数)vy结束。 vy应该每个环通变得越来越小,更多的东西一样:

//Calculate initial values for velocity[x] and velocity[y] 
double vx = (vel*Math.cos(angle)) + ax*time; 
double vy = (vel*Math.sin(angle)) + ay*time; 

while(numBounces < 10) { 
    //Increment Time 
    time = time + deltaTime; 

    //Calculate new values for x and y 
    x = x + vx*time; 
    y = y + vy*time + .5*ay*(time*time); 

    //Calculate new values for velocity[x] and velocity[y] 
    vx += ax * time; 
    vy += ay * time; 
+0

因此,用户输入的初始角度被转换为弧度,但Math.atan计算的新角度是度数?我应该保留这条线'angle = angle * Math.PI/180''避免任何不一致? – kachilous

+0

用户输入的初始角度被转换为弧度(虽然由于某种原因,您有一个弧度变量,在本例中从未使用过)。 然后Math.atan给你一个弧度的角度,你立即乘以Math.PI并除以180;所有这些都是以弧度为单位的角度并将其大致分为57.如果在“Math.atan”行后面删除“angle = angle * Math.PI/180”,则情况只会改善。 –

+0

是的,因为我意识到Math.cos/Math.sin只能使用弧度,所以必须在该语句中添加,以便可以转换用户的角度。 – kachilous

-1

你需要学习使用调试器 - 在Eclipse中,例如。然后,你可以停下你想要的地方,然后检查变量,直到你找出错误的转向(或者在这种情况下没有采取正确的转向)。你可以在一分钟左右的时间内弄清楚这一点。

如果这不是一个选项,请开始放入关键数据的控制台printlns。

代码总是有错误,而且通常只是通过查看它们而无法弄清楚 - 无论多么困难和多长时间。

+0

那么我把打印语句,并使用调试器来确定y值增加,永远不会减少。这似乎是主要问题 – kachilous

+0

继续前进!所以y不对 - 什么影响y的价值?他们哪个是错的?看看它的输入 - 是_they_对吗?如果不是,继续......如果它们是正确的,放大第一个不合格值出现的计算。 –

+0

它看起来像vx和vy计算后,他们继续保持不变,而y变得越来越大 – kachilous