2011-01-29 70 views
0

我目前正在使用WindowsAPI创建窗口的游戏。但是,目前这个过程占用了我CPU的50%。所有我做的是创建窗口,并使用下面发现​​的代码循环:使用大量资源的Windows应用程序(游戏)

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 
{ 
    MSG message = {0}; 
    WNDCLASSEX wcl = {0}; 

    wcl.cbSize = sizeof(wcl); 
    wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 
    wcl.lpfnWndProc = WindowProc; 
    wcl.cbClsExtra = 0; 
    wcl.cbWndExtra = 0; 
    wcl.hInstance = hInstance = hInstance; 
    wcl.hIcon = LoadIcon(0, IDI_APPLICATION); 
    wcl.hCursor = LoadCursor(0, IDC_ARROW); 
    wcl.hbrBackground = 0; 
    wcl.lpszMenuName = 0; 
    wcl.lpszClassName = "GL2WindowClass"; 
    wcl.hIconSm = 0; 

    if (!RegisterClassEx(&wcl)) 
     return 0; 

    hWnd = CreateAppWindow(wcl, "Application"); 

    if (hWnd) 
    { 
     if (Init()) 
     { 
      ShowWindow(hWnd, nShowCmd); 
      UpdateWindow(hWnd);   

      while (true) 
      { 
       while (PeekMessage(&message, 0, 0, 0, PM_REMOVE)) 
       { 
        if (message.message == WM_QUIT) 
         break; 

        TranslateMessage(&message); 
        DispatchMessage(&message); 
       } 

       if (message.message == WM_QUIT) 
        break; 

       if (hasFocus) 
      { 
       elapsedTime = GetElapsedTimeInSeconds(); 
       lastEarth += elapsedTime; 
       lastUpdate += elapsedTime; 
       lastFrame += elapsedTime; 
       lastParticle += elapsedTime; 

       if(lastUpdate >= (1.0f/100.0f)) 
       { 
        Update(lastUpdate);   
        lastUpdate = 0; 
       } 
       if(lastFrame >= (1.0f/60.0f)) 
       { 
        UpdateFrameRate(lastFrame); 
        lastFrame = 0; 
        Render(); 
        SwapBuffers(hDC); 
       } 
       if(lastEarth >= (1.0f/10.0f)) 
       { 
        UpdateEarthAnimation(); 
        lastEarth = 0; 
       } 
       if(lastParticle >= (1.0f/30.0f)) 
       { 
        particleManager->rightBooster->Update(); 
        particleManager->rightBoosterSmoke->Update(); 
        particleManager->leftBooster->Update(); 
        particleManager->leftBoosterSmoke->Update(); 

        particleManager->breakUp->Update(); 
        lastParticle = 0; 
       } 
      } 
      else 
      { 
       WaitMessage(); 
      } 
      } 
     } 

     Cleanup(); 
     UnregisterClass(wcl.lpszClassName, hInstance); 
    } 

    return static_cast<int>(message.wParam); 
} 

其中GetElapsedTimeInSeconds:

float GetElapsedTimeInSeconds() 
{ 
    static const int MAX_SAMPLE_COUNT = 50; 

    static float frameTimes[MAX_SAMPLE_COUNT]; 
    static float timeScale = 0.0f; 
    static float actualElapsedTimeSec = 0.0f; 
    static INT64 freq = 0; 
    static INT64 lastTime = 0; 
    static int sampleCount = 0; 
    static bool initialized = false; 

    INT64 time = 0; 
    float elapsedTimeSec = 0.0f; 

    if (!initialized) 
    { 
     initialized = true; 
     QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&freq)); 
     QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&lastTime)); 
     timeScale = 1.0f/freq; 
    } 

    QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&time)); 
    elapsedTimeSec = (time - lastTime) * timeScale; 
    lastTime = time; 

    if (fabsf(elapsedTimeSec - actualElapsedTimeSec) < 1.0f) 
    { 
     memmove(&frameTimes[1], frameTimes, sizeof(frameTimes) - sizeof(frameTimes[0])); 
     frameTimes[0] = elapsedTimeSec; 

     if (sampleCount < MAX_SAMPLE_COUNT) 
      ++sampleCount; 
    } 

    actualElapsedTimeSec = 0.0f; 

    for (int i = 0; i < sampleCount; ++i) 
     actualElapsedTimeSec += frameTimes[i]; 

    if (sampleCount > 0) 
     actualElapsedTimeSec /= sampleCount; 

    return actualElapsedTimeSec; 
} 

所以,即使我不画任何东西,当窗口具有焦点仍然占用50%。我不明白这是如何占用这么多系统资源。

我做错了什么?

任何帮助将不胜感激,谢谢!

回答

1

要添加到其他答案...

您需要以某种方式节制您的游戏循环。如果没有消息,PeekMessage会立即返回,因此您只需尽快循环,消耗100%的一个CPU内核。假设你有双核心PC,你大概会看到50%。

为了避免消耗100%的CPU周期,请在每个循环的开始时调用MsgWaitForMultipleObjects,而不是执行Sleep(),传递零句柄,传递一个小暂停,这是您的最小帧间隔。每次它返回时,由于超时已过,或者因为有消息要处理。如果有消息,则处理它们(全部),然后以任一方式处理游戏OnNextFrame /重新绘制周期。使用UpdateWindow而不是等待发布WM_PAINT。

3

hasfocus从天上掉下来。如果它是真的,你就会烧掉100%的核心,if()语句里面没有任何东西可以让你的程序等待任何东西。睡眠(1)可以解决这个问题,但是你打算做什么并不明显。

+0

目前它似乎总是使用100%的核心(50%),但是当我开始做其他事情时,它会超过50%。它如何传播到像这样的2个内核? – henryprescott 2011-01-29 21:12:13

+0

我认为它会减少等待消息的时间,(50%) - (游戏引擎使用率) – henryprescott 2011-01-29 21:21:22

1

您的应用程序运行在一个紧密的循环中,并且没有做任何有用的事情来刻录CPU。您必须在循环中添加诸如Sleep(1)之类的内容。

您提供的这个例子是一个退化的案例,它并不一定要修复。如果你打算制作一款游戏,那么你将把帧更新和渲染功能放到循环中,并且它会做一些有用的“东西”。在这种情况下,你不会想要“休眠”任何周期。

如果我是你,我不会从头开始制作游戏,并会寻找一些游戏引擎。市场上有很多高质量的开源和免费游戏引擎。或者至少寻找一些简单的游戏框架,提供诸如消息循环和双缓冲窗口绘制设置等基本功能。