FPS dependant movement

I am getting 450-500 FPS in my game engine using LWJGL. Aware of the problem that machines will get very different FPS I used my code that I used with my old game engine (using fullscreen exclusive mode) to adjust the speed my vehicles/players can make every frame. Basically this is what I do:

I get the Time Delta/frameTime

I multiply every speed constant with that time delta

result should be same speed on all systems because high fps would lead to low speed/frame and low fps would lead to high speed/frame.

Somehow though, this won´t work when I use LWJGL. I always get faster movement when higher FPS. I am aware that I might have some error in my code that can cause this but there might as well be some logic problem that I am not aware of or limitation in java?

Here is my code (Chrono is my FPS capturing class, captFPS captures the fps and getFrameTime() gets frame time delta)


/*
 * Vehicle.java
 *
 * All vehicles are to be handled by this class
 * Driver is Object Player player and null if vehicle is empty
 *
 * Created on den 26 mars 2003, 20:44
 */

/**
 *
 * @author  digizard
 */

public class Vehicle {
    
    private String Name = "Panzer";
    private org.lwjgl.opengl.GL gl;
    private float posX, posY, posZ;
    private Player player;
    private int texID, FPS;
    private Chrono chrono;
    private double currentSpeed, maxSpeed, slowdownForward, slowdownBackwards, accForward, accBackwards, angle, angleSpeed;
    
    public Vehicle(int texID) {
        
        this.gl = Schlug.gl;
        this.texID = texID;
        
        chrono = new Chrono();
        
        player = null;
        maxSpeed = 1;
        currentSpeed = 0;
        slowdownForward = 0.1;
        slowdownBackwards = 0.1;
        accForward = 0.01;
        accBackwards = 0.001;
        angle = 0;
        angleSpeed = 2;
    }
    
    public void draw() {
        
        posX += currentSpeed * java.lang.Math.cos(java.lang.Math.toRadians(angle));
        posY += currentSpeed * java.lang.Math.sin(java.lang.Math.toRadians(angle));
        
        if(player != null) player.setPos(posX, posY, posZ);
        
        if(currentSpeed > 0) currentSpeed -= java.lang.Math.abs(currentSpeed) * slowdownForward * chrono.getFrameTime();
        else if(currentSpeed < 0) currentSpeed += java.lang.Math.abs(currentSpeed) * slowdownBackwards * chrono.getFrameTime();
        
        gl.loadIdentity();

        if(player != null) gl.translatef(0.0f, 0.0f, posZ);
        else gl.translatef(posX, posY, posZ);
        
        gl.rotatef((float) angle, 0.0f, 0.0f, 1.0f);
        
        gl.bindTexture(org.lwjgl.opengl.GL.TEXTURE_2D, texID);
    
        gl.begin(org.lwjgl.opengl.GL.QUADS);
            gl.texCoord2f(0.0f, 1.0f);
            gl.vertex3f(-1.0f, -1.0f, 0.0f); 
            gl.texCoord2f(1.0f, 1.0f);
            gl.vertex3f(1.0f, -1.0f, 0.0f);
            gl.texCoord2f(1.0f, 0.0f);
            gl.vertex3f(1.0f, 1.0f, 0.0f);
            gl.texCoord2f(0.0f, 0.0f);
            gl.vertex3f(-1.0f, 1.0f, 0.0f);
        gl.end();
    }
    
    public void setPos(float posX, float posY, float posZ) {
        this.posX = posX;
        this.posY = posY;
        this.posZ = posZ;        
    }
    
    public void setAngle (double angle) { this.angle = angle%360; }
    
    public double getAngle() { return angle; }   
    
    public double getAngleSpeed() { return angleSpeed * chrono.getFrameTime(); }
    
    public void accelerate(boolean forward) {
        if(java.lang.Math.abs(currentSpeed) < maxSpeed) {
            if(forward) currentSpeed += accForward * chrono.getFrameTime();
            else currentSpeed -= accBackwards * chrono.getFrameTime();
        }
    }
    
    public void setPlayer(Player player) { this.player = player; }
    public float getX() { return posX; }   
    public float getY() { return posY; } 
}


Please suggest any changes if you see anything obvious.

An educated guess would be that you’re just using Sys.getTime(). But this is in ticks not seconds or milliseconds - you need to divide by Sys.getTimerResolution() to get a proper time delta.

Yes, I do not have that code here (sitting in school with laptop) but what I do to get the time delta is something like…

(Sys.getTime() - temp)/Sys.getTimerResolution();

Any other ideas?

Don’t know exactly what you are doing there with your speed, but this look wrong, bc. it does not depend on time:

   
posX += currentSpeed * java.lang.Math.cos(java.lang.Math.toRadians(angle)); 
posY += currentSpeed * java.lang.Math.sin(java.lang.Math.toRadians(angle)); 

Most simple motion is described by:

x' = x + v*dt

accForward, accBackwards, slowdownForward and
slowdownBackwards seem to take the role of accelerations correctly. For acceleration is constant during the time of one frame, you you even enhance your intergration of position to

x' = x + v*dt + 0.5*a*dt²

First I thaught you had solved my problem, but when I looked again I see that there is no reason why my method should not work? Ok here it is…

For accelerating, the method accelerate(boolean forward) is called. It is called every frame (actually every time the program detects that keyboard press) so it would be called 400 times a second if the fps is 400.

Therefore, the currentSpeed variable would be incremented every second * FPS. And each frame it would be currentSpeed += accForward * td.
Consequently, it would inrement the currentSpeed with the same amount /second in all FPS:es. The posX += cos/sin etc code is the code for moving the ship depending on the currentSpeed variable, and then currentSpeed is decremented with the slowdown* variables depending on the td also.

I see nothing wrong with this, or is there another way that I should handle this?

x' = x + v*dt
v' = v + a*dt