[摘抄]游戏主循环逻辑

1. 最简单的情况

1 bool game_is_running = true;
2 while(game_is_running)
3 {
4   update_game();    // 逻辑帧
5   display_game();   // 渲染帧
6 }

带来的问题:小霸王机器会跑的很慢,牛逼机器上跑得飞快,cpu达到100%。显然不是一个合适的算法。

2. 恒定帧率和恒定游戏速度

 1 const int FRAMES_PER_SECOND = 25;
 2 const int SKIP_TICKS = 1000 / FRAMES_PER_SECOND;
 3  
 4 // GetTickCount() returns the current number of milliseconds
 5 DWORD next_game_tick = GetTickCount();
 6  
 7 int sleep_time = 0;
 8 bool game_is_running = true;
 9 while(game_is_running)
10 {
11     update_game();
12     display_game();
13     next_game_tick += SKIP_TICKS;
14     sleep_time = next_game_tick - GetTickCount();
15     if(sleep_time >= 0)
16     {
17       Sleep(sleep_time);
18     }
19     else
20     {
21       // Shit, we are running behind!
22     }
23 }

在这种方案下,游戏的帧率恒定设置为25帧。如果达不到游戏内设定的恒定帧率,例如小霸王的机器,会非常的卡;牛逼的机器顶多也就是25帧,一定程度上有点浪费,但是对于手机游戏来说,能省点电,也许是个好事情。

3. 恒定的游戏速度和独立的帧率

 1 const int TICKS_PER_SECOND = 25;
 2 const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
 3 const int MAX_FRAMESKIP = 5;
 4 DWORD next_game_tick = GetTickCount();
 5 int loops;
 6 float interpolation;
 7 bool game_is_running = true;
 8 while(game_is_running)
 9 {
10     loops = 0;
11     while(GetTickCount() > next_game_tick && loops < MAX_FRAMESKIP)
12     {
13         update_game();
14         next_game_tick += SKIP_TICKS;   // 保证25帧
15         loops++;
16     }
17  
18     // interpolation代表插值
19     interpolation = float(GetTickCount() + SKIP_TICKS - next_game_tick) / float(SKIP_TICKS);
20     display_game(interpolation);
21 }

如果是牛逼的机器,在保持逻辑帧率25帧的情况下,会尽可能的提高渲染帧率,当然前提是需要计算需要渲染的插值。
如果是小霸王的机器,渲染帧率不足以达到25帧时,会在渲染一帧的同时跑多次逻辑帧,来尽量保证逻辑帧率一致,如果渲染帧率下降到TICKS_PER_SECOND/MAX_FRAMESKIP时,逻辑帧率也会随之降低。

4. 渲染帧率是否真的需要尽可能的高?
如果没有限制的话,那跑渲染的那个cpu肯定到100%了,这个应该在大部分的情况下是不能接受的。而且在视觉效果表现上来看,一定有个阈值的渲染帧率,超过了这个数值,再高的帧率的意义对画面的提升也有限,显得意义不大。如果是手机游戏的话,考虑到电池电量的因素,更应该控制一下帧率。

参考文档
http://www.koonsolo.com/news/dewitters-gameloop/

posted @ 2014-03-26 12:38  H.Q.Cai  阅读(405)  评论(0)    收藏  举报