How to use time delta to make movement independent from how fast game runs?

Viewed 87

I want to make the movement to be independent from speed of game. I mean if my game UPS is 60 or 30 speed of game object will be the same. If UPS is 60, then for one second player moves 60 ticks * (speed / 60) pixels per tick. Or if UPS is 30, then for one second player moves 30 ticks * (speed / 30) pixels per tick. Distances are the same. I use this approach in my game.

public class Bullet extends GameObject {

    private double vx, vy, g;

    public Bullet(double x, double y, double vx, double vy) {
        this.vx = vx;
        this.vy = vy;
        setX(x);
        setY(y);
        g = 8.0 / GameContainer.getUPS();
    }

    public void tick() {
        setX(getX() + vx);
        setY(getY() + vy);
        vy += g;
    }

    public void render(Graphics2D g) {
        g.setColor(new Color(255, 128, 0));
        g.fillOval((int) getX(), (int) getY(), 4, 4);
    }

}

Player's movement is fine. But when I change my UPS game ball's speed changes.
https://imgur.com/a/UePTqv3

2 Answers

that's probably because of how you have written your game loop. if you call tick() in only a while loop, the game will run faster or slower on different computers. to prevent that from happening, you can use a game loop more like this:

public void run()
{
    long lastTime = System.nanoTime();
    double delta = 0.0;
    double amountOfTicks = 60.0;
    double ns = 1000000000 / amountOfTicks;
    while(running)
    {
        long now = System.nanoTime();
        delta += (now - lastTime) / ns;
        while(delta > 1)
        {
            delta--;
            tick();
        }
        render();
    }
}

The reason why this works, is because it doesn't depend on the tick speed of your computer, but on actual time. Hope I could help.

pseudo code ...

void GameLoop()
{ 
    while( notAborting ) 
    {
    
        static float deltaTime = 0.0f;
        //Get current Time T1
        
        //pass this deltaTime as argument to update function, 
        //and multiply every thing that updates its location 
        //by deltaTime, this way you will have frame rate independent 
        //movememnt and update.
        Update(deltaTime);
        
        //render as usual
        Render();
        
        //update deltatime, time of 1 frame drawn
        deltaTime = /*Get current Time*/ T2 - T1; (in seconds)
    }
}
Related