Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (542)
Games in Android Showcase (133)
games submitted by our members
Games in WIP (606)
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  
  Box2D World Inconsistent Movement Speeds  (Read 1375 times)
0 Members and 1 Guest are viewing this topic.
Offline Rayexar
« Posted 2013-10-24 06:48:04 »

I currently have a game using Box2D, and the movement seems to be inconsistent. For example, when i move the player character across the map (it's a platformer), sometimes it moves at 'normal' speed, and sometimes slower. It also happens with the effect of gravity, sometimes the player falls 'normally' and sometimes slowly.

The problem seems to be random, because it doesn't happen every time.

The player character is about 1 m wide by 2 m tall, and all the platforms are about 0.5 m thick and range from 2-10 m long, except for the ground, which is about 60 m long. All objects except for the player are static bodies, and created using the Box2DMapObjectParser.

Any ideas on what might be causing the problem?
Offline Grunnt

JGO Kernel


Medals: 95
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #1 - Posted 2013-10-24 07:46:46 »

This may be a timing issue, i.e. at some times you are updating the world with large time intervals, at some other time with short intervals, making it appear as if the character moves faster or slower, while in fact the entire physics world is updated at a faster or slower pace. Does the World.step(timestep, velocityIterations, positionIterations) function get called at a consistent rate with a consistent interval? (for example 30 times per second with a timestep of 1/30)

Otherwise I would have no idea what this could be.

Offline Rayexar
« Reply #2 - Posted 2013-10-24 09:44:47 »

I'm pretty sure it's being called at a constant rate, because it's only called in the render method of the libgdx screen.

1  
2  
3  
4  
5  
6  
@Override
public void render(float delta) {
        ...
   world.step(1/60f, 8, 3);
        ...
}


Unless I'm meant to use the delta time as well? world.step is not being called anywhere else.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline opiop65

JGO Kernel


Medals: 161
Projects: 7
Exp: 4 years


JumpButton Studios


« Reply #3 - Posted 2013-10-24 09:51:16 »

Yes, you should multiply all your movement code by delta. This will smooth the movement out between frames, so it should fix some issues.

Offline Rayexar
« Reply #4 - Posted 2013-10-24 10:20:57 »

So instead of doing playerBody.setLinearVelocity(v), I should use playerBody.setLinearVelocity(v*delta)? I thought Box2D took care of the delta timesteps.
Offline opiop65

JGO Kernel


Medals: 161
Projects: 7
Exp: 4 years


JumpButton Studios


« Reply #5 - Posted 2013-10-24 10:23:50 »

I have no idea what Box2D does and doesn't do, you should check into it. But yes, for all movement you should be multiplying by the delta.

Offline xsvenson
« Reply #6 - Posted 2013-10-24 10:47:43 »

Although the box2d manual specifies that the world should step with a constant step time, You might want to experiment with
1  
2  
3  
4  
5  
6  
@Override
public void render(float delta) {
        ...
   world.step(delta, 8, 3);
        ...
}

“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
Offline Grunnt

JGO Kernel


Medals: 95
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #7 - Posted 2013-10-24 11:11:11 »

I'm pretty sure it's being called at a constant rate, because it's only called in the render method of the libgdx screen.

1  
2  
3  
4  
5  
6  
@Override
public void render(float delta) {
        ...
   world.step(1/60f, 8, 3);
        ...
}


Unless I'm meant to use the delta time as well? world.step is not being called anywhere else.

Your code should work fine if you are 100% sure that the render(float delta) method is called 60 times per second. I'm not 100% sure but I think that LibGDX will try to call this method as fast as possible, which in some cases lead to a lot of world.step calls (i.e. when little has to be drawn on screen and FPS is high) and in other cases to fewer world.step calls (i.e. when FPS is low), slowing the physics down.

Theres some a nice article on time step on http://gafferongames.com/game-physics/fix-your-timestep/. Here's what I do, it's not perfect but it avoids your problem (if that is the problem):
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  
public abstract class AbstractGame implements ApplicationListener {

   public static final long ONE_SECOND_NS = 1000000000;
   public static final int MAX_FPS = 60;

   private int maxUpdates = 10;

   private long lastTime = System.nanoTime();

   @Override
   public void render() {
      long time = System.nanoTime();
      long timeDelta = time - lastTime;
      float timeDeltaSeconds = timeDelta / (float) ONE_SECOND_NS;
      lastTime = time;

      // Update the game state in capped time steps (in case we're running too slow)
      int updateCount = 0;
      while (timeDelta > 0 && (maxUpdates <= 0 || updateCount < maxUpdates) && !paused) {
         // Update using a time step in seconds
         long updateTimeStep = Math.min(timeDelta, ONE_SECOND_NS / MAX_FPS);
         float updateTimeStepSeconds = updateTimeStep / (float) ONE_SECOND_NS;

         // Update here (also call world.step here)

         timeDelta -= updateTimeStep;
         updateCount++;
      }
     
      // Do rendering here
     
      // Limit the maximum FPS if this is not a loading screen
      long sleepTime = Math.round((ONE_SECOND_NS / MAX_FPS) - (System.nanoTime() - lastTime));
      if (sleepTime <= 0)
         return;
      long prevTime = System.nanoTime();
      while (System.nanoTime() - prevTime <= sleepTime) {
         Thread.sleep(1);
      }
   }
}


Edit: I'd recommend against using a varying time step in Box2D, as this may lead to other difficulties (according to the manual).

Offline Grunnt

JGO Kernel


Medals: 95
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #8 - Posted 2013-10-24 11:24:20 »

So instead of doing playerBody.setLinearVelocity(v), I should use playerBody.setLinearVelocity(v*delta)? I thought Box2D took care of the delta timesteps.

Box2D indeed takes care of delta timesteps and you should never do setLinearVelocity(v*delta), unlike opiop65 suggests. However, by setting velocity of objects directly you are interfering with the physics simulation. Maybe you are better off using impulses, as described here.

Offline Rayexar
« Reply #9 - Posted 2013-10-24 11:26:45 »

@xsvenson: putting delta in the timestep definitely made the physics run much more smoothly and consistently, but the frame rate seemed to keep changing between 30 and 60. With a constant timestep (1/60f), the FPS is about 60.

@Grunnt: I'll try out your method tomorrow once I get some sleep, because I'm really tired at the moment. That's quite an interesting idea though, because I never would have thought of manually controlling the game/render loop and Thread. I thought libgdx took care of that stuff.

Anyways, thanks everyone for all the quick replies! Good night

EDIT: Just saw your latest reply as I posted my reply. I initially used impulses, but that made the controls feel "slow", because it took time for the player to accelerate. Player movement feels a lot more snappy by directly setting the velocity. Thanks for the tip though, I'll try playing around with impulses again. Anyways, really appreciate the help, thank you very much.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Grunnt

JGO Kernel


Medals: 95
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #10 - Posted 2013-10-24 11:27:43 »

Sleep well Grin

Offline xsvenson
« Reply #11 - Posted 2013-10-24 11:51:01 »

@xsvenson: putting delta in the timestep definitely made the physics run much more smoothly and consistently, but the frame rate seemed to keep changing between 30 and 60. With a constant timestep (1/60f), the FPS is about 60.
...

As Grunnt explained, with very high FPS and with very low fps, the world step still calculates the physical world with 1/60 timestep. This means with 60 fps You get a resolution of 1, with 600fps You get a resolution of 10 (10 times faster). If the FPS is capped at 60, this is not much of a problem, but if the FPS gets lower than 60, it, once again, gets to be a problem.

On desktop, the default cap is at 60fps, on adroid, the cap can be device dependent (60fps, 80fps, 30fps), this means, on those device, Your game will run differently.

You reporting a FPS drop might be caused by Your box world just taking lots of time for calculations.

With libgdx You should have no reason to roll Your own rendering loop, with years of human hours spent on the engine and running well on more restricted environment (android) , one can assume that the rendering loop is quite well optimized.


“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
Offline Grunnt

JGO Kernel


Medals: 95
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #12 - Posted 2013-10-24 12:27:54 »

EDIT: Just saw your latest reply as I posted my reply. I initially used impulses, but that made the controls feel "slow", because it took time for the player to accelerate. Player movement feels a lot more snappy by directly setting the velocity. Thanks for the tip though, I'll try playing around with impulses again. Anyways, really appreciate the help, thank you very much.

Happy to help! Be sure to look into the differences between applying impulse and applying force, as applying impulse should help you get instantaneous effect, as opposed to applying force.

Offline Grunnt

JGO Kernel


Medals: 95
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #13 - Posted 2013-10-24 12:45:33 »

On desktop, the default cap is at 60fps, on adroid, the cap can be device dependent (60fps, 80fps, 30fps), this means, on those device, Your game will run differently.

Whether a LibGDX game has a framerate cap at 60FPS is entirely up to the developer as far as I know. You can make a game run at 6000FPS or at 6FPS, it just depends on how you code it, and things like whether v-sync is turned on or off.

With libgdx You should have no reason to roll Your own rendering loop, with years of human hours spent on the engine and running well on more restricted environment (android) , one can assume that the rendering loop is quite well optimized.

One can assume that this loop is quite well optimized, but this is quite different from one having a loop with a fixed time step. Grin In order to decouple world updates from rendering (which is really neccessary in physics-based games precisely to avoid the problems the OP has) you need to develop a custom game loop that seperates updates from rendering, so update speed no longer depends on FPS. LibGDX out of the box does not do this (which is not a shortcoming of LibGDX, it's just something you have to do yourself). Again, take a look at http://gafferongames.com/game-physics/fix-your-timestep/ which explains this a lot better than I ever could.

Offline xsvenson
« Reply #14 - Posted 2013-10-24 14:38:24 »

Yes, as I said, the default is 60fps. However, on android devices this has been capped for You.

While a fixed step update gives more predictability and stability for physics simulation, it is not directly necessary. For using physics with delta You just need to be aware of the shortcomings.
I would like to point out that all libgdx box demos run with the regular libgdx rendering loop. With the default fps of 60 (which is even achievable with most android devices and in browser), the max delta is theoretically capped, giving You a nearly "fixed step" simulation. Of course, the fps could get lower, in which case, indeed, the simulation can take a hit or experience some artifacts.

The question here is rather do You care or does it matter ? I just know I am using the regular libgdx and box and for me it's good enough.

“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
Offline Grunnt

JGO Kernel


Medals: 95
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #15 - Posted 2013-10-24 14:57:01 »

The question here is rather do You care or does it matter ? I just know I am using the regular libgdx and box and for me it's good enough.

That is a very good point Grin

Offline pitbuller
« Reply #16 - Posted 2013-10-24 21:37:56 »

If for some reason you don't want to run fixed time step simulation you should still always cap your delta time to some sane value. Usually good value is inverse of target fps halved. So target fps is 60, target delta time is then 16.6ms so cap would be (1/30) ms ~ 33.33ms. When fps for some reason drops significantly you want to avoid tunneling artefacts or explosions at physic simulation. In these cases you can just choose to game either lag a bit behind or run multiple steps to get simulation to catch real time.
Offline Rayexar
« Reply #17 - Posted 2013-10-25 11:42:30 »

@Grunnt: Your update loop did the trick! In fact, it made all the physics a lot smoother and faster as well as more consistent. I highly recommend anyone who's using Box2D with libgdx to use this as well
Offline Grunnt

JGO Kernel


Medals: 95
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #18 - Posted 2013-10-25 12:21:16 »

@Grunnt: Your update loop did the trick! In fact, it made all the physics a lot smoother and faster as well as more consistent. I highly recommend anyone who's using Box2D with libgdx to use this as well

Great! Glad to hear it.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Elsealabs (20 views)
2014-12-28 10:39:27

CopyableCougar4 (21 views)
2014-12-28 02:10:29

BurntPizza (25 views)
2014-12-27 22:38:51

Mr.CodeIt (15 views)
2014-12-27 04:03:04

TheDudeFromCI (20 views)
2014-12-27 02:14:49

Mr.CodeIt (26 views)
2014-12-23 03:34:11

rwatson462 (60 views)
2014-12-15 09:26:44

Mr.CodeIt (48 views)
2014-12-14 19:50:38

BurntPizza (98 views)
2014-12-09 22:41:13

BurntPizza (117 views)
2014-12-08 04:46:31
How do I start Java Game Development?
by gouessej
2014-12-27 19:41:21

Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50
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!