How to get a constant speed on both new and old iPhone?

I am going to create a 2D game in OpenGL ES for iPhone. I call my game loop using NSTimer with an interval of 0.002 (60 frames per second) with the repeats set to "NO" (I start NSTimer from the function again, as recommended):

-(void)gameLoop:(id)sender { double currTime=(double)CACurrentMediaTime(); m_FPS_framesThisSecond++; float timeThisSecond=currTime-m_FPS_lastSecondStart; if (timeThisSecond>1.0f) { m_FPS=m_FPS_framesThisSecond; m_FPS_framesThisSecond=0; m_FPS_lastSecondStart=currTime; } [game update]; [game render]; //Continue the loop [NSTimer scheduledTimerWithTimeInterval:0.002 target:self selector:@selector(gameLoop:) userInfo:nil repeats:NO]; } 

This works smoothly on my 3GS, however, when I test it on 2G, the game runs much slower, and sometimes I get random empty frames. When I lower the interval to 0.033 (30 frames per second). This is too slow for 3G.

I know there must be some way to achieve consistent playback on both devices. Doodle Jump seems to work smoothly and at the same frame rate on both phones.

+4
source share
2 answers

A significant problem is as follows:

Your game should be updated depending on the amount of time that has passed since the last rendering, and not how many times it is displayed. Suppose you calculate the position of a sprite based on some speed. The new position should be calculated based on the time between the renders, and not with the assumption that has passed since the last render of 0.002 seconds. This is called independent FPS animation.

So here is a simple example:

 // FPS dependent animation int x = sprite.x + sprite.velocity.x 

The right way to do this is to use the time since the last render and update proportionally. The following code assumes 0.002 is a temporary base.

 // FPS independent animation int x = sprite.x + sprite.velocity.x * time_since_last_render/0.002 

On a device where rendering takes twice as long, the next update will move the object twice as long, so it will be in the same place as on a faster device.

A side issue, you should not always display the next frame at 0.002 seconds in the future. You should see how long the current frame took for rendering, subtract from 0.002 and use it to plan the next rendering. Naturally, this number will have a minimum value of zero, so on slow devices that you will not begin to plan in the past. For example, if your render function takes exactly 0.002 seconds to render, this will halve the frame rate unnecessarily.

+2
source

There are actually two types of frame rates:

  • Display frame rate: at which the screen is redrawn.
  • Logical frame rate: game logic refresh rate (game speed)

I think that you are looking for a constant logical frame rate, which is separated from the display frame rate, which is tuned to the phone's hardware capabilities. Compare with the game loop, which should fill one display frame for each logical frame.

Check out the “Constant Game Speed ​​with Maximum FPS” algorithm described in deWiTTERS Game Loop. The game logic seems to work at the same speed on both 3G and 2GS, but the display frame rate will be adjusted by a slower 2G CPU. Although this is not covered in the article above, you can also limit the display frame rate to save battery.

+2
source

Source: https://habr.com/ru/post/1315283/


All Articles