猜想它有多是在主循环里使用了 Sleep(0), 一搜,果真定位到具体代码,它位于 cocos2dx\platform\win32\CCApplication.cpp,大体长像以下:函数
1 |
while ( 1 ) { |
2 |
if ( 有消息 ) { |
3 |
if ( 时间到 ) 更新计时, call 主循环函数; |
4 |
else Sleep(0); |
5 |
} |
6 |
// 其余跳出循环判断代码 |
7 |
} |
也就是说,该循环除了执行 mainLoop 之外,花了大量时间在 检查消息和 Sleep(0) 上面。oop
而且,我还发现一个奇怪的现象(暂时还不清楚是为何),即:测试
HelloCPP 项目的 AppDelegate.cpp 文件中有一行代码:this
// set FPS. the default value is 1.0/60 if you don't call this |
pDirector->setAnimationInterval(1.0 / 60); |
上面的 60 ,若是改大,不起任何做用,帧速始终是 60 不会变。但若是改到小于60,是能够起做用的。.net
因而,解决 CPU 占用的思路,始于 “是否能够下降循环精度” 的念头。code
已知正常状况下,执行 Sleep(1) ,会睡大概 1/50 秒,这个时间并不精确也不许确,看上去没法知足 60 fps 这个流畅度需求。不过,若是游戏运行帧速不须要这么高,好比 30 fps ?? 则该方案大为可行。orm
经实际测试,将 Sleep(0) 改为 Sleep(1), 再将上面代码中的 60 改为 25, 效果很是显著。但另外一个问题来了:若是每游戏循环作的事有点多,时间有点长,那么游戏将被拖慢。游戏
原engine中,同步时间的代码以下:get
QueryPerformanceCounter(&nNow); |
if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart) { |
nLast.QuadPart = nNow.QuadPart; |
由于每次在 nLast 中记录 nNow 时间,并用时间差与设定间隔做比较,时间差每每会比设定间隔要大,若是是在不精确的 Sleep(1) 以及每循环负担比较大的状况下,将致使每帧实际所花的时间,会超出设定间隔很多,从而拖慢游戏速度(若是游戏按帧步进计时的话)。同步
为解决这个问题,我用的是时间对齐的方式。其实就是改了一下更新 nLast 的表达式:
nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart %m_nAnimationInterval.QuadPart); |
这样每帧的总消耗时间就至关的恒定了。
上面的问题解决并不算太完美。如何保持 60 fps 也能 cpu 0% 占用呢? 我考虑的方案是修改 Sleep(1) 的精度。
找了一下资料,发现 Winmm.lib 库中有 timeBeginPeriod(1); timeEndPeriod(1); 函数能够用于该目的,令 Sleep(1) 的精度提高到1毫秒级别,遂动手改之:
1. 添加 Winmm.lib 库的引用。我在这里采起了在 CCApplication.cpp 头部添加 #pragma comment(lib, "Winmm.lib") 语句的方式。
2. 在 while(1) 代码段的先后,分别放上 timeBeginPeriod(1); timeEndPeriod(1); 语句
这样就算完工了。
经测试,帧速设定在 59 fps 之内, cpu 均可以实现 0 占用 (i7 2600k)。设成 60 的话, cpu 占用会周期性的古怪浮动,暂时不明就里中。而设成 60+, cpu 将 100%。
不过该问题就算暂时告一段落,先将程序限定到 50 fps 好了,流畅,无问题,感受上也方便计算...