Sam Brotherton Sam Brotherton - 9 months ago 24
Java Question

Why do I get inaccuracies when working with large scale/speed projectiles, is it due to Eulerian Integration?

So I am trying to make a Physics Simulation, which aims to simulate a missile going off a long distance away, (for my example I have used 1.6km) and I have a AA weapon at this 1.6km distance; when the missile is launched, due to maths I have worked out when I need to release the AA weapon to hit the missile. So cool the maths all checks out, and I am 99% certain mathematically this should work; but the error seems to occur in the animation stage, and I feel this is something to do with how I am handling gravity.

The issue is instead of the flight path of the missile following a lovely parabola, it is instead taking a path consisting of many different linear functions (hence the Eulerian integration speculation(Source: http://natureofcode.com/book/chapter-5-physics-libraries/)); and I believe the reason for this is to do with my scale. I am using a scale of 1 pixel = 1 meter. The image updates every 60 seconds, so I am saying every cycle, take the vertical velocity - (9.81 / 60) and then update the position by (Vertical velocity / 60). The problem is, it only wants to round to the nearest pixel, so in the first 2 seconds or so, it only wants to have the vertical position change at 4 pixels per cycle, and then it goes to 5, then 6... This causes the flight path (when the missile was launched at 200m/s at 50 degrees and the AA launched at 70degrees with the same speed) to look like: Simulation Test

If anyone knows how I can fix this issue to turn the inaccurate linear representation into a nice parabolic one that was still accurate to the time, (the time after launch is about 3 seconds for this). If anyone has any suggestions and/or solutions, or if you are able to explain why this is happening and don't mind spending a little time explaining it to me to get a better understanding of the problem, that would be greatly appreciated! If you require any more information to help you help me, then just leave a comment and I will provide you with any info. The relevant pieces of code are:

public void gravity(){
for (int i = 0; i < rockets.size(); i++){

if(timeToStart <= milliSecondTimer){
rockets.get(1).fired = true;
//Trail of other rocket
if (milliSecondTimer > 0.1 * count){
rockets.add(new Ball(rockets.get(1).x - 20 ,rockets.get(1).y - HEIGHT + 100,5,0,0,false));
}

}

if(rockets.get(i).fired){
rockets.get(i).vSpeed -= 9.81 / 60;
rockets.get(i).move(0, (int) (rockets.get(i).vSpeed / 60));
rockets.get(i).move(1, (int) (rockets.get(i).hSpeed / 60));
} else if (timeToStart==1110){
//function to work out the time displacment
derr(1);
}

//For the trail
if (milliSecondTimer > 0.1 * count){
rockets.add(new Ball(rockets.get(0).x - 20 ,rockets.get(0).y - HEIGHT + 100,5,0,0,false));
count++;
}

}
}
public static void main(String[] args) throws InterruptedException{
JFrame frame = new JFrame("App Name");
Rockets app = new Rockets();
frame.setSize((int)(WIDTH * SCALER),(int)(HEIGHT * SCALER));
frame.add(app);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.requestFocus();
long lastLoopTime = System.nanoTime();
int fps = 0, lastFpsTime = 0, count = 1;
final int TARGET_FPS = 60;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
//Game Loop
while(true){
long now = System.nanoTime();
long updateLength = now - lastLoopTime;
lastLoopTime = now;
delta = updateLength / ((double)OPTIMAL_TIME);
lastFpsTime += updateLength;
fps++;
if (lastFpsTime > 100000000 * count){
milliSecondTimer += 0.1;
count++;
}
if (lastFpsTime >= 1000000000){
System.out.println("(FPS: "+fps+")");
lastFpsTime = 0;
fps = 0;
count = 1;
}
loopsGone++;
app.repaint();
Thread.sleep( (lastLoopTime-System.nanoTime() + OPTIMAL_TIME)/1000000 );
}
}


Thank you,

Sam

Answer Source

Perhaps you can change your x and y rocket coordinates to a float (I'm assuming they are int right now). And then when you are drawing, that is when you add the (int) cast. For instance,

rockets.get(i).move(0, (int) (rockets.get(i).vSpeed / 60));

Should not have an int cast.

Also, you're going to want to change

(rockets.get(i).vSpeed / 60));

to

(rockets.get(i).vSpeed / 60.0)); 

You want your position to retain precision, which it's not doing currently with the int cast. This is what using a float would achieve.

It doesn't look like scale is the issue. It would be an issue if you are trying to draw a parabola on an image that is, say, 10 x 10 pixels.

Could you post your rocket class? I'd like to run this, looks interesting.