有没有更好的方法来创建这个游戏循环?(C++/Windows)

4

我正在开发一个Windows游戏,遇到了这个问题:

bool game_cont;

LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_QUIT: case WM_CLOSE: case WM_DESTROY: game_cont = false; break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

int WINAPI WinMain(/*lots of parameters*/)
{
    //tedious initialization

    //game loop
    while(game_cont)
    {
        //give message to WinProc
        if(!GameRun()) game_cont = false;
    }
    return 0;
}

我在想是否有比将game_cont设为全局变量更好的方法来实现这个功能(暂不考虑计时器等问题)。简而言之,我需要能够从WinProc退出WinMain中的while循环,以便如果用户以游戏菜单之外的方式关闭游戏,则程序不会继续在内存中运行。(当我在没有WinProc中的game_cont..语句测试时,它确实会这样做)。
此外,GameRun基本上是一个布尔值,当游戏结束时返回false,否则返回true。

你应该只在接收到 WM_QUIT 时退出,并通过调用 PostQuitMessage 处理 WM_DESTROY - Ben Voigt
4个回答

11

是的,使用PeekMessage,在游戏开发中这是标准做法。

我认为这是最好的方法:

int Run()
{
    MSG msg;
    while(true)
    {
        if(::PeekMessage(&msg,0,0,0 PM_REMOVE))
        {
            if(msg.message == WM_QUIT || 
                       msg.message == WM_CLOSE || 
                       msg.message == WM_DESTROY)
                break;

            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);           
        }
        else
        {
            //Run game code
                    if(!GameRun())
                         break;
        }
    }
} 

另外,看看这个(尤其是第一个答案)


我可能会通过传递一个“游戏结束”值到GameRun代码中,以便在您选择退出应用程序时进行清理,而不仅仅使用“break”。但是一般的结构完全正确。 - Kylotan
谢谢评论。是的,我认为那样会更好。 - Daniel Rodriguez
2
PeekMessage是在没有消息时执行后台工作的正确方法,但是WM_CLOSEWM_DESTROY不应该在主消息循环中处理。现在,每当任何子控件或不可见的消息助手窗口被销毁时,您都将中止整个程序! - Ben Voigt

1

你可以使用exit。 使用atexit确保在退出时WM_CLOSE到达消息队列。

我不知道这里的最终设计是什么,但这是一个想法。


0
你可以将 game_cont 声明为 static,放在包含 WinMain/WinProc 的主文件中,但我不知道是否有更好的结构。

0

不,不要那样做。

WM_QUIT 是你的标志。当遇到 WM_QUIT 时,GetMessage 的返回值会指示它。

你的主窗口永远不会收到 WM_QUIT,因为它不会被发送到一个窗口。默认情况下,WM_CLOSE 会调用 DestroyWindow,所以你不需要任何特殊处理。通过调用 PostQuitMessage 处理 WM_DESTROY,这将导致在你的线程上出现 WM_QUIT,从 GetMessage 返回的特殊值,并停止你的消息分派循环。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接