Using delta time messes up movement

Using delta time with my speed variables actually don’t make it so nice, after all. The movement is smooth, but still the speed is different on all computers.

I want to have some kind of a constant speed, but also a smooth movement, on all computers. My girlfriend has an older laptop and when she runs my game Sokobanski, the character really moves slowly, while on my computer it’s like the normal speed. And when my brother runs my game on his new powerful PC, the character there moves too quickly.

So, my question is, how do I create a smooth constant movement? How to make the movement same on all computers?

Do you know what sort of numbers you are getting with your delta time? i.e, on your computer is your delta time around 20 and on your girlfriend’s laptop is it around 100? That could be a problem if delta is the same on all machines when they’re actually running at different frame rates.

Also, you need to make sure you’re scaling the distance moved by delta so they move the same amount over a set period of time (i.e. 100 pixels per second) which when multiplied by delta gives you a movement value:


distance_per_second = 100; // pixels per second
distance = distance_per_second / (1000 / delta);

Usually this should result in moving barely a pixel or 2 per frame to create a smooth looking movement.

Difficult to tell really without seeing some code of yours :slight_smile:

You need to get delta time between frames. You can do that manually, or try to find some kind of function that is already made in the framework / engine you are using. If you are using Libgdx that would be:


float deltaTime = Gdx.graphics.getDeltaTime(); // interpolated delta time, seconds
float deltaTime = Gdx.graphics.getRawDeltaTime(); // raw delta time, seconds

Next, you need to make a speed variable. It would mean the distance the moving object covers in 1 second. For example:


float speed = 100.0f; // object will move 100 pixels per second

When updating the position of the object, you simply multiply speed by delta time and add it to the position of the object.


object.position += speed * deltaTime;

This way the object will move the same amount of distance regardless of the frame rate.

Thank you for replies, trollwarrior1 and rwatson462!

I figured out there is something else wrong with the movement of entity. So, here’s how the movement works. Once entity’s destination (variables newX and newY) are set, entity moves towards those coordinates first on x-axis, then on y-axis. But, there is a problem. This only works if speed is set to 16, otherwise either newX or newY will never be equal to entity’s x or y. Here’s the code:


    public void update(float delta){
        float x = sprite.getX();
        float y = sprite.getY();
        float speed = (float) Math.floor(950 * delta);
        if(speed < 16 || speed > 16)
            speed = 16;
        
        if(x != newX){
            if(x < newX){
                sprite.setX(x + speed);
            }else if(x > newX){
                sprite.setX(x - speed);
            }
            
            moving = true;
        }
        
        if(y != newY){
            if(y < newY){
                sprite.setY(y + speed);
            }else if(y > newY){
                sprite.setY(y - speed);
            }
            
            moving = true;
        }
        
        if(x == newX && y == newY){
            moving = false;
        }
    }
    

I tried working around this problem, but then the movement turned to tile-based on x-axis, and never finished on y-axis. Here’s the code:



    public void update(float delta){
        float x = sprite.getX();
        float y = sprite.getY();
        float speed = 64;
        
        if(x != newX){
            if(x > newX - 1){
                sprite.setX(newX);
                return;
            }else if(x < newX + 1){
                sprite.setX(newX);
                return;
            }else{
                if(x < newX){
                    sprite.setX(x + speed * delta);
                }else if(x > newX){
                    sprite.setX(x - speed * delta);
                }
                
                moving = true;
            }
        }
        
        if(y != newY){
            if(y - 1 > newY && y + 1 < newY){
                sprite.setY(newY);
            }else{
                if(y < newY){
                    sprite.setY(y + speed * delta);
                }else if(y > newY){
                    sprite.setY(y - speed * delta);
                }
                
                moving = true;
            }
        }


        if(x == newX && y == newY){
            moving = false;
        }
    }
    

I’m not sure if I’m becoming dumber because it seems like this problem has a very simple solution. Someone help me, please? :slight_smile:

It should like something like this:


if(x != newX){
    if(x > newX - 1 && x < newX + 1){
        sprite.setX(newX);
    }else{
        if(x < newX){
            sprite.setX(x + speed * delta);
        }else if(x > newX){
            sprite.setX(x - speed * delta);
        }
        
        moving = true;
    }
}

if(y != newY){
    if(y > newY - 1 && y < newY + 1){
        sprite.setY(newY);
    }else{
        if(y < newY){
            sprite.setY(y + speed * delta);
        }else if(y > newY){
            sprite.setY(y - speed * delta);
        }
        
        moving = true;
    }
}

Thank you! It works perfectly now! Thank you very much! ;D ;D

Or better yet use a fixed step game loop. A variable step loop is more often than not a mistake.

Fixed time steps for the win.

Currently I’m using LibGDX which means I’m stuck with variable step loop until I start developing my own library.

You are not really stuck with variable step loop.
You could do something like this.
So basicly you store a float, which stores the remaining frametime. The you cycle through a loop, as long as the remaining frametime is bigger then or equals your TIME_STEP.
You update the logic, using TIME_STEP as delta and decrease the remaining frametime by TIME_STEP.

Example:

TIME_STEP of 1/60 = 0,017sec

  1. 60FPS: frametime = TIME_STEP, logic update once
  2. 10FPS: frametime = TIME_STEP * 6, logic updated 6 times
  3. 120FPS: frametiem = TIME_STEP/2, logic updated every 2 Frame only.

The result is drawn once per frame, but the logic is calculated more accurate, with lower delta times.

You might limit the maximum frametime, as low frametimes mean many calculations, which may increase frametime, which means even more calculations…

What @Springrbua is describing is a simple time accumulator.

In code it could look like this (javascript):

module.exports = function(rate) {
	var accum = 0;
	return function(time, callback) {
		accum += time;
		while (accum >= rate) {
			accum -= rate;
			callback(rate);
		}
	};
};

source: https://github.com/ericlathrop/time-accumulator

Might also want to check out this:

except the ‘rate’ variable should be renamed to ‘interval’, or the logic should be changed.

Thank you guys for telling me this! I appreciate it!

I will finish the current game I’m developing using variable step loop because I’m almost finished with it and I’d have to change a lot of things. I certainly will try your ideas out on the game I’ll develop next.