Linear Motion

In order to program something interesting with 2-d motion, I figured that I should start with the absolute basics… linear motion. I typed up this program today to try it out, and it doesn’t completely work. All the calculations it performs at run time turn out slightly differently from what it should be. I noticed that this error margin decreases when I up the fps, but it only does that, decreases it. Does anyone know what I should change to make the game displacement equal to the one it gets from the equation: x=x0 + v0t + (1/2)at^2?
my source code:


  import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   import javax.swing.event.*;
   import java.util.*;
   import java.applet.*;


    public class LinearMotion extends Applet implements MouseMotionListener 
   { 
      Graphics g; 
      Image offscreen; 
      Dimension dim; 
      int mouseX, mouseY; 
      int mouseDX, mouseDY;
   	
      double initialVelocity=45;// m/s
      double velocity=initialVelocity;
      double acceleration=-6;// m/s^2
		double startingPosition=20.0;
      double position =startingPosition;// m
      int meterLength=5;// m/10*pixel
		
      boolean backwards=true;//can velocity become negative? false if friction, etc
      boolean finished=false;//if backwards = true, and velocity becomes negative
   	
      int fps=100;
      int frames = 0;//incremented every screen
      ArrayList<Double> oldPositions = new ArrayList<Double>();
   	
      Thread t = new Thread();
       public void init()  
      { 
         dim = getSize(); 
         addMouseMotionListener(this); 
         setBackground(Color.black); 
         offscreen = createImage(dim.width,dim.height); 
         g = offscreen.getGraphics(); 
         t.start();
      } 
   
       public void paint(Graphics z)  
      { 
         try{ t.sleep(1000/fps); } 
             catch(Exception e){};
         g.clearRect(0,0,dim.width,dim.width); 
      	
      	/*Physics Calculations*/
         position+=(velocity/(double)fps);
         velocity+=(acceleration/(double)fps);
         System.out.println(acceleration/fps);
         System.out.println(position);
         System.out.println(velocity);
         if(backwards==false && velocity<0){
            velocity=0;
            finished=true;
         }
      	
         frames++;
      	/*Mark previous displacement positions*/
         if(frames%fps==0 && !finished)
            oldPositions.add(new Double(position));
      		      
      	
      	/*Draw Grid*/
         g.setColor(Color.white);
         g.drawLine(0,70,dim.width,70);
         for(int x=0;x<dim. width/10;x++){
            g.setColor(Color.white);
            g.drawLine(x*10,65,x*10,70);
            if(x%5==0){
               g.drawString(x*meterLength+"",x*10,80);
               g.setColor(Color.red);
               g.drawLine(x*10,65,x*10,70-1);
            }
         }
      	      	/*Draw moving dot and variables*/
         g.setColor(Color.cyan);
         int xLoc = (int)(position*10.0/meterLength);
         g.drawRect(xLoc,50,1,1);
         g.drawLine(xLoc,75,xLoc,65);
         g.drawLine(xLoc+1,75,xLoc+1,65);
      				
         g.setColor(Color.yellow);
         g.drawString("Velocity: "+round(velocity,2)+" m/s",40,100);
         g.drawString("Acceleration: "+round(acceleration,2)+" m/s^2",40,120);
         g.drawString("Current Position: "+round(position,2)+" m",40,140);
      	
      	
      
      	/*Draw previous positions on the grid*/
         g.setColor(Color.yellow);
         g.drawString("Demo Position",10,170);
         g.drawString("Actual Position",130,170);
         g.drawString("Difference",250,170);
         for(int x=0;x<oldPositions.size();x++){
            Double d = oldPositions.get(x);
         	
         	
         //draws a box on the grid where the point moves
            int drawY=50-1;
            g.setColor(Color.yellow);         	
            g.drawRect((int)(d*10.0/meterLength)-1,drawY,2,2);//rect
            g.setColor(Color.white);
            g.drawString(x+"",(int)(d*10.0/meterLength-3),drawY-10);//#
         	
				double demo = round(d,2);
            g.drawString("["+x+"]: "+demo,20,200+x*15);//Demo position
				
            int time =x+1;
				double actual = (startingPosition+initialVelocity*time+0.5*acceleration*time*time);
            g.drawString(""+actual,150,200+x*15);//Actual Position
				
				g.drawString(""+(round(actual-demo,5)),270,200+x*15);//Difference
         }
      	
         z.drawImage(offscreen,0,0,this);     	
         repaint();
      } 
   
       public void update(Graphics g) 
      { 
         paint(g); 
      } 
   
       public void mouseMoved(MouseEvent evt)  
      { 
         mouseX = evt.getX(); 
         mouseY = evt.getY(); 
         repaint(); 
      } 
   
       public void mouseDragged(MouseEvent e)  
      {
         mouseDX=e.getX();
         mouseDY=e.getY();
         repaint();
      }
       double round(double d, int decimalPlace){
         int rounder=1;
         for(int x=0;x<decimalPlace;x++)
            rounder*=10;
         return (double)((int)(d*rounder))/(double)rounder;
      }
   } 
 

Since you’re using euler integration your results will always be an approximation. Plus you’ll have the usual floating-point inaccuracies and cumulative rounding error.

What problem is this causing exactly? Usually the small differences aren’t big enough to matter for games. As you’ve found you can increase your simulation steps to get better accuracy, or you can switch to another integration method.

Thanks. I just thought it was some error in my code, due to the fact that an increase in fps somehow made the results more accurate, and because of the fact that it was constantly off by approximately the same ammount.

This hasn’t caused me any trouble, but I just wanted to make sure that the method itself wasn’t flawed. The longer the program runs, the more the number goes off, so for implementation it might be better to just update the displacement to the correct value every second.