Time based movement / deltaTime / Event Timing ?

Hi,

I’m really confused. The app is faster or slower on some devices. I had some small problems with libgdx. BUT this is the biggest problem that I’ve had.

First I thought I understood deltaTime. But that is not so.

Why is that so hard. I made a small program, where is a 3d cube is moving from left to right.
And then the 3d cube is moving backwards.

I’ve tried so many things. NOTHING WORKS.
I also added the deltaTime (test += steps*deltaTime) to the movement. Nothing helps. On my smaller smartphone the movement is faster.

I don’t know what to do. On my bigger smartphone is it slower.

I have read all of this. (some things I did not understand):

http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=1845&p=10046&hilit=step+deltatime#p10046

http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=4185&p=20139&hilit=deltaTime#p20139

Has somebody not a great solution for this. How can I do it, that the render() renders at the same speed on all devices?

I read about accumulate or something like that. Is this the answer?

Info: I’m not using box2d.

Has anybody solved this problem. It would be great, when somebody can post a working example code.

My program looks a little bit like this:



public class ObjectScreen implements Screen {
	Game game;


	public ObjectScreen (Game game) {
		this.game = game;
		
		cam = new PerspectiveCamera(45, VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
		...
	}
...

@Override
public void render (float delta) {
	update(delta);
	draw(delta);
}

public void update (float deltaTime) {
	// ...
}

public void draw (float deltaTime) {		

	GL10 gl = Gdx.graphics.getGL10();

	gl.glClearColor(0.0f, 0.0f, 0.0f, 1);

	gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
	...
	
	// 3d Object moving
	...
}
}

Thank You!

I can’t really say anything unless you provide us with more of your code, specifically whats inside the update() function.

How are you calculating deltaTime?

I’m not calculating deltaTime. I generated a standard LibGDX Project. I get it from LibDX.

When I output deltatime on my bigger smartphone I get this:
0.016456…, or 0.152546… etc.

On my smaller smartphone I get this:
0.011254…, or 0.102546… etc.

Not all phones are equal, I don’t think its really worth even trying to make every phone render at the same time.

Your “bigger smart phone” may have more background app’s running then your “smaller smart phone”, this would alter the speed as your phone would be running some background tasks, try closing everything but your game on both devices.

The hardware in the “smaller phone” could be better then in your “bigger phone” or your smaller phone just requires less processing time for its general things, (maybe less things need updating in the smaller phone).

Conclusion: If you try testing the delta time on different computers, you will also notice that every computer will give a different number, Delta is there to help fix the speed of the game for slower computers, the faster your computer is going, the less the delta value will be, meaning if you had a free loop, the delta value SHOULD make the movement of objects stay constant or pretty close between devices, despite the value of delta being greater or lower on one computer.

EDIT: Maybe your screen is a different resolution, your “bigger smart phone” probably has a higher resolution then your smaller phone.

Meaning the cube in the “smaller smart phone” has less distance to travel to the other side of the screen.

Here is an example.

In my app, there is a red box. It’s moving from left to right. The app starts, when you touch the screen.
Now, I installed this on my big and small smartphone. I touch the both devices at the same time.
And now I see, that the red box on my smaller smartphone touches the right side of the screen first.

In my app, there is a ease function from Robert Penner and I added Aspect ratio.

So, first the images:
(This is my libgdx.png file)

http://img213.imageshack.us/img213/5928/libgdx.png

(this is, where the red box starts)

http://img826.imageshack.us/img826/646/boxleft.png

(and this is, where the red box touches the right side)

http://img33.imageshack.us/img33/9328/boxright.png

And this is the code:

package com.me.mygdxgame;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;

public class MyGdxGame implements ApplicationListener {
	
    private static final int VIRTUAL_WIDTH = 800;
    private static final int VIRTUAL_HEIGHT = 480;
    private static final float ASPECT_RATIO = (float)VIRTUAL_WIDTH/(float)VIRTUAL_HEIGHT;
	
    private Rectangle viewport;
	
	private OrthographicCamera camera;
	private SpriteBatch batch;
	private Texture texture;
	private Sprite sprite;
	
	private float x = 0f;
	private float y = 0f;	
	
	private boolean start = false;
	
    private float diff = 200f;

    private float minTime = 0;
    private float maxTime = 770f;
    
    private float iEaseOut = 0;
    private float zTime = 0;
    	
	@Override
	public void create() {		

		camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
		batch = new SpriteBatch();
		
		texture = new Texture(Gdx.files.internal("data/libgdx.png"));
		texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
		
		TextureRegion region = new TextureRegion(texture, 2, 2, 32, 32);
		
		sprite = new Sprite(region);
	}

	@Override
	public void dispose() {
		batch.dispose();
		texture.dispose();
	}

	@Override
	public void render() {		
		
		float deltaTime = Gdx.graphics.getDeltaTime();
		
		if (Gdx.input.isTouched()) {
			start = true;
		}		
		
		if (start) {

			if (iEaseOut < diff) {
				zTime = expoEaseOut(iEaseOut, minTime, maxTime, diff);

				float deltaAdd = zTime*deltaTime;				
				zTime += deltaAdd;					
				
				x = zTime;			

				iEaseOut++;		
			} else {
				start = false;
			}
			
		}
		
		System.out.println(Gdx.graphics.getDeltaTime());
		
		
		Gdx.gl.glClearColor(1, 1, 1, 1);
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		
		camera.update();
		
        Gdx.gl.glViewport((int) viewport.x, (int) viewport.y, (int) viewport.width, (int) viewport.height);	
		
		batch.setProjectionMatrix(camera.combined);
		batch.begin();
		sprite.setPosition(x-VIRTUAL_WIDTH/2, y);
		sprite.draw(batch);
		batch.end();
	}
		
	public static float expoEaseOut(float t,float b , float c, float d) {
		return (t==d) ? b+c : c * (-(float)Math.pow(2, -10 * t/d) + 1) + b;	
	}

	@Override
	public void resize(int width, int height) {
    	// calculate new viewport
        float aspectRatio = (float)width/(float)height;
        float scale = 1f;
        Vector2 crop = new Vector2(0f, 0f);
        
        if(aspectRatio > ASPECT_RATIO)
        {
            scale = (float)height/(float)VIRTUAL_HEIGHT;
            crop.x = (width - VIRTUAL_WIDTH*scale)/2f;
        }
        else if(aspectRatio < ASPECT_RATIO)
        {
            scale = (float)width/(float)VIRTUAL_WIDTH;
            crop.y = (height - VIRTUAL_HEIGHT*scale)/2f;
        }
        else
        {
            scale = (float)width/(float)VIRTUAL_WIDTH;
        }

        float w = (float)VIRTUAL_WIDTH*scale;
        float h = (float)VIRTUAL_HEIGHT*scale;
        viewport = new Rectangle(crop.x, crop.y, w, h);
	}

	@Override
	public void pause() {
	}

	@Override
	public void resume() {
	}
}

Have you tried something simple like make small program that when you touch the screen it starts counting the number of seconds?
This way you could better isolate if the issue is with your time step or with the render/easing function.

I solved it now. Thanks to everybody.

This two lines solved my problem:

		float addDelta = 100*Gdx.graphics.getDeltaTime();
		speed = addDelta;

I tried that before. But without success.

Now it’s working. It’s unbelievable. :slight_smile: