2011-01-29 41 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)之類的內容。

您提供的這個例子是一個退化的案例,它並不一定要修復。如果你打算製作一款遊戲,那麼你將把幀更新和渲染功能放到循環中,並且它會做一些有用的「東西」。在這種情況下,你不會想要「休眠」任何週期。

如果我是你,我不會從頭開始製作遊戲,並會尋找一些遊戲引擎。市場上有很多高質量的開源和免費遊戲引擎。或者至少尋找一些簡單的遊戲框架,提供諸如消息循環和雙緩衝窗口繪製設置等基本功能。