henryprescott
henryprescott

Reputation: 483

Windows Application (Game) using a lot of resources

I'm currently working on a game that creates a window using WindowsAPI. However, at the moment the process is taking up 50% of my CPU. All I am doing is creating the window and looping using the code found below:

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);
}

Where 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;
}

So even when I am not drawing anything when the window has focus it still takes up 50%. I don't understand how this is taking up so much system resources.

Am I doing something wrong?

Any help would be much appreciated, thank you!

Upvotes: 0

Views: 208

Answers (3)

Chris Becke
Chris Becke

Reputation: 36026

To add to the other answers...

You need to throttle your game loop in some way. PeekMessage returns immediately if there are no messages so you are just looping as fast as possible, consuming 100% of one of your CPU cores. Presumably you see 50% as you have a dual core PC.

Instead of doing a Sleep() to avoid consuming 100% of the CPU cycles, call MsgWaitForMultipleObjects at the start of each loop, passing in zero handles, passing in a small timeout being your minimal interval between frames. Each time it returns, its because the timeout elapsed, OR because there are messages to process. If there are messages, process them (all) and then, either way, then process a game OnNextFrame / Repaint cycle. Use UpdateWindow instead of waiting for a WM_PAINT to be posted.

Upvotes: 1

detunized
detunized

Reputation: 15289

Your application is running in a tight loop and burning CPU by not doing anything useful. You have to add something like Sleep(1) into the loop.

This example you provided is a degenerate case and it doesn't really have to be fixed. If you going to make a game out of this, then you are going to put the frame update and render functionality into the loop and it will be doing some useful "stuff". In this case you wouldn't want to "sleep" any cycles.

If I were you I wouldn't start making a game from scratch and would look for some game engine. There's a lot of high quality open and closed source free game engines available on the market. Or at least look for some simple game skeletons that provide basic things like a message loop and double buffered window drawing setup.

Upvotes: 1

Hans Passant
Hans Passant

Reputation: 941635

hasfocus falls out of the sky. You'll burn 100% core when it is true, there's nothing inside the if() statement that will make your program wait for anything. Sleep(1) would fix that but it isn't otherwise obvious what you intend to do.

Upvotes: 3

Related Questions