Приложение Windows (игра), использующее много ресурсов - PullRequest
0 голосов
/ 29 января 2011

В настоящее время я работаю над игрой, которая создает окно с использованием WindowsAPI. Тем не менее, на данный момент процесс занимает 50% моего процессора. Все, что я делаю, это создаю окно и зацикливаюсь, используя код, найденный ниже:

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%. Я не понимаю, как это занимает столько системных ресурсов.

Я что-то не так делаю?

Любая помощь будет высоко ценится, спасибо!

Ответы [ 3 ]

3 голосов
/ 29 января 2011

hasfocus падает с неба.Вы сожжете ядро ​​на 100%, когда это правда, в операторе if () нет ничего, что заставило бы вашу программу ждать чего-либо.Sleep (1) исправит это, но в остальном не очевидно, что вы собираетесь делать.

1 голос
/ 29 января 2011

Чтобы добавить к другим ответам ...

Вам нужно каким-то образом ограничить свой игровой цикл.PeekMessage немедленно возвращается, если сообщений нет, поэтому вы просто зацикливаетесь настолько быстро, насколько это возможно, потребляя 100% одного из ваших ядер ЦП.Предположительно, вы видите 50%, поскольку у вас есть двухъядерный ПК.

Вместо того чтобы выполнять Sleep (), чтобы избежать использования 100% циклов ЦП, вызовите MsgWaitForMultipleObjects в начале каждого цикла, передавая нулевые метки, передавая маленький тайм-аут, являющийся вашим минимальным интервалом между кадрами.Каждый раз, когда он возвращается, его, потому что истекло время ожидания, ИЛИ, потому что есть сообщения для обработки.Если есть сообщения, обработайте их (все), а затем, в любом случае, обработайте игровой цикл OnNextFrame / Repaint.Используйте UpdateWindow вместо ожидания публикации WM_PAINT.

1 голос
/ 29 января 2011

Ваше приложение работает в узком цикле и сжигает процессор, не делая ничего полезного. Вы должны добавить что-то вроде Sleep(1) в цикл.

Этот пример, который вы предоставили, является вырожденным случаем, и его не нужно исправлять. Если вы собираетесь сделать из этого игру, то поместите обновление цикла и функциональность рендеринга в цикл, и он будет делать некоторые полезные «вещи». В этом случае вы не захотите «спать» никакими циклами.

На вашем месте я бы не стал делать игру с нуля и искал бы какой-нибудь игровой движок. На рынке доступно множество высококачественных бесплатных игровых движков с открытым и закрытым исходным кодом. Или, по крайней мере, поищите несколько простых игровых каркасов, которые обеспечивают базовые функции, такие как цикл сообщений и настройка рисования окна с двойной буферизацией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...