2
\$\begingroup\$

I'm running a simple Libgdx game using Box2D physic and i get different speed on different Android devices.

I believe that this is because timestep.

If I use 1 and 2 example i get different speed on different devices and the 3 example it works nice but on old devices (on my old smartphone Galaxy Wonder) lose fps and is unplayable

1)

world.step(1f/60f, 6, 2); 

2)

static final float STEP_TIME = 1f/60f;
float accumulator = 0;

private void stepWorld() {
    float delta = Gdx.graphics.getDeltaTime();

    accumulator += Math.min(delta, 0.25f);

    if (accumulator >= STEP_TIME) {
        accumulator -= STEP_TIME;

        world.step(STEP_TIME, 6, 2);
    }
}

3)

world.step(Gdx.graphics.getDeltaTime(), 6, 2);

There is an other way how to get the same speed?

\$\endgroup\$
  • \$\begingroup\$ The code should be while (accumulator >= STEP_TIME), not if. Try changing that and report back. \$\endgroup\$ – Charanor Jul 15 '17 at 19:48
  • \$\begingroup\$ I tried it, but it work as example 3 \$\endgroup\$ – WaltherEvans95 Jul 15 '17 at 20:07
  • \$\begingroup\$ What do you mean by "lose fps and is unplayable" exactly? Does the game experience FPS drops or does your physics slow down? \$\endgroup\$ – Charanor Jul 16 '17 at 12:22
  • \$\begingroup\$ Does the game experience FPS \$\endgroup\$ – WaltherEvans95 Jul 16 '17 at 12:59
  • \$\begingroup\$ Then try changing the step time to be something higher like 1/45 (recommended) or 1/30. \$\endgroup\$ – Charanor Jul 16 '17 at 13:02
0
\$\begingroup\$

So let's take a look at what each of those code examples are doing:

world.step(1f/60f, 6, 2);

Example #1 tells the physics engine that 1/60th of a second has passed every time you call it. If your game loop is being called more than 60 times a second it will go fast; less than 60 times a second and it'll be slow. The number of times it gets called per second will depend on the speed of the underlying hardware, so this method will end up in different behavior on different devices.

static final float STEP_TIME = 1f/60f;
float accumulator = 0;

private void stepWorld() {
    float delta = Gdx.graphics.getDeltaTime();

    accumulator += Math.min(delta, 0.25f);

    if (accumulator >= STEP_TIME) {
        accumulator -= STEP_TIME;

        world.step(STEP_TIME, 6, 2);
    }
}

Example #2 uses a cooldown pattern- this is the right way to do it. Like @Charanor said, you'll want to use a while loop instead of an if statement (it'll be slightly more accurate), but otherwise it is correct. If it is too slow for your phone, you might consider changing the step from 1/60f to 1/45f.

world.step(Gdx.graphics.getDeltaTime(), 6, 2);

Example #3 has you calling the engine every frame, which means that your results will be very accurate, but it also means that you'll be calling the engine way more often than you need to (you don't need to update the position of your objects faster than you can display the changes).

\$\endgroup\$
1
\$\begingroup\$

According to the LibGDX Box2D Wiki it is recommended to use a fixed time step with a step time of 1/45 or 1/300; i.e. your Example #2 but with STEP_TIME as 1/45 or 1/300.

You should also change your if (accumulator >= STEP_TIME) to while (accumulator >= STEP_TIME) so it can properly step multiple times per frame if needed.

If you find that you still have lag on slow devices you could try to play with the 0.25 value of this line: accumulator += Math.min(delta, 0.25f). I found that a lower value generates better performance but sacrifices more accuracy in the simulation.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.