Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (799)
Games in Android Showcase (237)
games submitted by our members
Games in WIP (865)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Using delta time messes up movement  (Read 9243 times)
0 Members and 1 Guest are viewing this topic.
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Posted 2015-04-19 09:15:21 »

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?

Offline rwatson462
« Reply #1 - Posted 2015-04-19 10:28:17 »

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:

1  
2  
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 Smiley
Offline trollwarrior1
« Reply #2 - Posted 2015-04-19 16:56:13 »

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:
1  
2  
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:
1  
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.
1  
object.position += speed * deltaTime;


This way the object will move the same amount of distance regardless of the frame rate.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Reply #3 - Posted 2015-04-19 23:30:31 »

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:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
    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:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
    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? Smiley

Offline trollwarrior1
« Reply #4 - Posted 2015-04-20 05:31:05 »

It should like something like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
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;
    }
}
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Reply #5 - Posted 2015-04-20 14:03:39 »

Thank you! It works perfectly now! Thank you very much!  Grin Grin

Online jonjava
« Reply #6 - Posted 2015-04-26 07:59:17 »

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

Offline Roquen

JGO Kernel


Medals: 518



« Reply #7 - Posted 2015-05-01 14:54:10 »

Fixed time steps for the win.
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Reply #8 - Posted 2015-05-05 13:57:25 »

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

Offline Springrbua
« Reply #9 - Posted 2015-05-05 14:44:29 »

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...
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online jonjava
« Reply #10 - Posted 2015-05-06 08:44:53 »

What @Springrbua is describing is a simple time accumulator.

In code it could look like this (javascript):

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
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:
https://www.youtube.com/watch?v=avwDj3KRuLc&t=21m0s

Offline Riven
Administrator

« JGO Overlord »


Medals: 1370
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #11 - Posted 2015-05-08 08:01:06 »

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

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings!
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Reply #12 - Posted 2015-05-10 12:41:55 »

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.

Pages: [1]
  ignore  |  Print  
 
 

 
Riven (198 views)
2019-09-04 15:33:17

hadezbladez (4909 views)
2018-11-16 13:46:03

hadezbladez (1810 views)
2018-11-16 13:41:33

hadezbladez (5183 views)
2018-11-16 13:35:35

hadezbladez (1023 views)
2018-11-16 13:32:03

EgonOlsen (4387 views)
2018-06-10 19:43:48

EgonOlsen (5228 views)
2018-06-10 19:43:44

EgonOlsen (2971 views)
2018-06-10 19:43:20

DesertCoockie (3874 views)
2018-05-13 18:23:11

nelsongames (4305 views)
2018-04-24 18:15:36
Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08

Deployment and Packaging
by gouessej
2018-08-22 08:03:45
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!