How to change from 60FPS to 30FPS while keeping things smooth?

Here is my current game loop:

final int ticksPerSecond = 60;
final int skipTicks = (1000 / ticksPerSecond);
float dt = 1f/ticksPerSecond;

while(System.currentTimeMillis() > nextGameTick && loops < maxFrameskip){
updateLogic();
nextGameTick+=skipTicks;
timeCorrection += (1000d/ticksPerSecond) % 1;
nextGameTick+=timeCorrection;
timeCorrection %=1;
loops++;


On most devices I've tested my game on (this is an Android game BTW) it runs quite nice.

As you can see, I'm using a fixed time-step (defined as my ticks per second).

If I reduce my Ticks Per Second to 30, everything runs at the same speed but is nowhere near as smooth. I keep hearing people say that 30fps should be OK for mobile games and everything should run great at 30 fps, but that's just not my experience.

Would be grateful if someone could give me some pointers on how to achieve this.

• Smooth is quite relative I'd say. 30 FPS might be smooth for a strategy game, but not for a fighting game fo example. – János Turánszki Jul 1 '14 at 21:55
• Thanks @JánosTuránszki, I've struggled with this problem for well over a year now. I'm trying to figure out if successful games (the Angry Birds and Flappy Birds of the world) are running at 60fps, on running at 30fps and doing something I'm not aware of to keep things running super-smooth. – BungleBonce Jul 1 '14 at 23:10

If you have seen a game running at 60fps, then reverting to 30fps will always be noticeably less smooth - it's a perception thing.

Get someone who has never played your game before to play it at 30fps and they'll probably think it's just fine.

Most games target 60fps these days as games running at 60fps have a much better feel. Most recent (high end?) mobile devices have their framerates throttled to 60fps. Older/low end devices may be forced to run at a lower frame rate, but more and more will be targeting 60fps. If games looked just as good at 30fps as they do at 60fps, then devices would just throttle to 30fps.

The bottom line is - don't worry about it. You'll never get a game looking as smooth at 30fps as it looks at 60fps.

• Thanks @WillCalderwood. I tried my app on a low-end tablet which does indeed have it's VSync capped at 30. The thing I can't get my head around is that Angry Birds look really smooth on this device compared to my app. I just don't get how they achieve this! Thanks for the answer though I guess I'll have to live with it for the time being. As you say, most devices will be capped at 60FPS these days anyway. – BungleBonce Jul 2 '14 at 12:54
• @user22241 Does your framerate remain very consistent? This helps massively with how smooth a game feels. – Will Calderwood Jul 2 '14 at 12:59
• Yeah the framerate is pretty much between 30 and 31 FPS on this tablet. The sprite's movement is constant (doesn't speed up / slow down), it's just very choppy. – BungleBonce Jul 2 '14 at 19:00

One thing stands out to me that could likely explain the difference in how smooth it looks: I don't see any indication that your updateLogic() method is using the actual delta time between frames. If I'm correct in assuming that dt is your delta time variable, it should not be constant.

This probably won't be cut and paste usable, but it should be something more like:

float skipTime = 1000 / 60.0f;
float lastUpdate = System.currentTimeMillis();
float dt;

while(true){
dt = System.currentTimeMillis() - lastUpdate;
if(dt >= skipTime){
updateLogic(dt);
lastUpdate = System.currentTimeMillis()
}
}

void updateLogic(float dt){
// modify any time-influenced calculations by the delta time, ex:
player.position += player.velocity * dt
}


The difference between that, and what I think is probably going on in your game, is that in this case, if the update happens to occur at 18, 19, or even 100 milliseconds, the update will account for the actual difference in time between frames and the position of a moving object will update by the correct amount. If dt is always 16.666667, but the actual time between frames is not that amount, then the object will not move the correct amount of space for the amount of time that has passed. What should be a constant velocity, or a smoothly changing velocity as it is affected by acceleration, is not so smooth, and not so constant. At 60 FPS this is likely to be less perceptible, but I'd wager the effect is still there, mitigated by the smaller dt constant.

• Hi @LLL79 Many thanks for this, I am using my dt value. I'm not 'passing' it into the logic routine, but the class that contains the updateLogic(); routine does have access to it. I am using it to move my objects. However, it is a fixed amount. Are you talking about using a variable time-step? I've very specifically tried to stick to using a fixed (or semi-fixed) Interestingly through, I have attempted to use a variable time-step but it caused inconsistent sprite movement - I've also read that using a variable amount can cause problems with physics? Thanks for your help!! – BungleBonce Jul 2 '14 at 19:03
• That's probably it then. It's all but guaranteed that the exact time between frames will vary from frame to frame, your delta time should reflect this, rather than being constant. I don't know how you were using the variable time step previously, but it should have the effect of smoothing things out, rather than making them more inconsistent. Edit: I'm actually not 100% certain I'm talking about a variable time-step, that term is not familiar to me. Despite sounding self explanatory, it could be slightly different than what I think it means. Will need to spend a little time reading up on it. – LLL79 Jul 2 '14 at 19:05
• Interesting, are you saying that it's not possible to use a fixed time-step? If not, how can one use a fixed value when, as you say, you can't guarantee the time beween frames? I really would prefer to use a fixed time-step (if possible) rather than a variable one. – BungleBonce Jul 2 '14 at 19:09
• gafferongames.com/game-physics/fix-your-timestep seems to resemble the approach you're following, and I don't see an issue with anything described within, but honestly I haven't tried it and thus have not profiled it in any way. My best estimate remains that if your updates are not smooth, there is some kind of issue with the way you're handling the discrepancy between update time step and actual time step. – LLL79 Jul 2 '14 at 19:34