Win32 message loop and game loop

Started by
8 comments, last by theNestruo 21 years ago
Hi... I'm doing an OpenGL game, but I think my main loop is very very confusing (altough it works). It's something like this:
    
int WINAPI WinMain (BLAH blah, BLAH blah, BLAH blah, BLAH blah) {

  // Register a class, create a window


  // Create a rendering context into the window


  // Initialize the game logic


  // Main loop

  for (;;) {

    // If the application is active, then ...

    if (isAppActive) {
      // If there're any message, then ...

      if (PeekMessage (&msg, hWnd, 0, 0, PM_REMOVE)) {
        if (msg.message==WM_QUIT)
          break;
        TranslateMessage (&msg);
        DispatchMessage  (&msg);
      }
      // Update the game

      UpdateGame ();
      RenderScene ();

    // If the application isn't active, then ...

    } else {
      // Wait for a message

      switch (GetMessage (&msg, hWnd, 0, 0)) {
        // WM_QUIT received

        case 0:
          goto out;
        // GetMessage failed

        case -1:
          // Show an error message

          return 1;
      }
      TranslateMessage (&msg);
      DispatchMessage  (&msg);
    }
  }

out:

  // Terminate the game


  // Destroy the rendering context


  return (msg.wParam);
}
    
Can someone show me a better way to do it, please? Thanks in advance. theNestruo Syntax error in 2410 Ok [edited by - theNestruo on April 20, 2003 1:02:38 PM]
theNestruoSyntax error in 2410Ok
Advertisement
Your basic structure is OK. The only reservation I have is the fact that you are using gotos. You should minimise your jumps for efficiency.
Why are you using a for(; loop instead of a while(1) loop?

Also as the previous poster said, you don''t really want to use GOTOs - a simple boolean flag (like ''while(!bDone)'') would work fine here.

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

quote:Original post by superpig
Why are you using a for(; loop instead of a while(1) loop?

Just to avoid one (useless) comparision each time the loop iterares. Anyway, I've changed it to "while (!done)", so that "optimization" is gone away.

EDIT: I've found a much better way to do it:

  int WINAPI WinMain (...) {  // Create a window, init. the game, OpenGL, etc...  // ...  // Main loop  for (;;) {    // Prevent CPU usage:    if (!isAppActive) WaitMessage ();    // Message loop:    if (PeekMessage (&mensaje, hVentana, 0, 0, PM_REMOVE)) {      if (mensaje.message==WM_QUIT)        break;      TranslateMessage (&mensaje);      DispatchMessage  (&mensaje);    }    // Game Loop:    if (isAppActive) {      UpdateGame ();      RenderScene ();    }  }  // ...  // Terminate game, OpenGL, etc...  return (mensaje.wParam);}  

theNestruo

Syntax error in 2410
Ok

[edited by - theNestruo on April 20, 2003 7:56:35 PM]
theNestruoSyntax error in 2410Ok
Here''s the code of how MS handles it from their DX SDK:


  PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );    while( WM_QUIT != msg.message  )    {        // Use PeekMessage() if the app is active, so we can use idle time to        // render the scene. Else, use GetMessage() to avoid eating CPU time.        if( m_bActive )            bGotMsg = ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) != 0 );        else            bGotMsg = ( GetMessage( &msg, NULL, 0U, 0U ) != 0 );        if( bGotMsg )        {            // Translate and dispatch the message            if( hAccel == NULL || m_hWnd == NULL ||                 0 == TranslateAccelerator( m_hWnd, hAccel, &msg ) )            {                TranslateMessage( &msg );                DispatchMessage( &msg );            }        }        else        {            if( m_bDeviceLost )            {                // Yield some CPU time to other processes                Sleep( 100 ); // 100 milliseconds            }            // Render a frame during idle time (no messages are waiting)            if( m_bActive )            {                if( FAILED( Render3DEnvironment() ) )                    SendMessage( m_hWnd, WM_CLOSE, 0, 0 );            }        }    }  


It can be modified to change into OpenGL standards. Then again, it is MS code, so not sure you would want to
Hi (again)!
Thank you, Nytegard; that code (with some modifications) works perfect!

Anyway, I have another problem... When I was trying to use the code of my last post, after closing the window, the application remained active, and using 99% of the CPU. I tried to change the main loop to the minimum (see the next code block), but it had no effect.

  while (GetMessage (blah blah blah)) {  TranslateMessage (&mensaje);  DispatchMessage (&mensaje);}  

It closes perfectly when I call PostQuitMessage when processing the WM_CLOSE message... But when I do it "as in book is" (WM_CLOSE calls DestroyWindow, WM_DESTROY calls PostQuitMessage) the application never closes and I need to kill the task with the "taskmgr".
I''m very confused with this... Can anyone explain me what I''m doing wrong?
Thank you in advance!

theNestruo

Syntax error in 2410
Ok
theNestruoSyntax error in 2410Ok
quote:Original post by theNestruo
Original post by superpig
Why are you using a for(; loop instead of a while(1) loop?

Just to avoid one (useless) comparision each time the loop iterares. Anyway, I''ve changed it to "while (!done)", so that "optimization" is gone away.



Does for(; compile to better machine code than while(1)?
quote:Original post by theNestruo
for (;; )
Original post by superpig
Why are you using a for(;; ) loop instead of a while(1) loop?
Original post by theNestruo
Just to avoid one (useless) comparision each time the loop iterares.
Original post by rypyr
Does for(;; ) compile to better machine code than while(1)?

The dissasembly button told me so...
4:        for (;; ) {5:            if (i==1) break;0040B46F   cmp         dword ptr [ebp-4],10040B473   jne         main+27h (0040b477)0040B475   jmp         main+29h (0040b479)6:        }0040B477   jmp         main+1Fh (0040b46f)7:8:        while (1) {0040B479   mov         eax,10040B47E   test        eax,eax0040B480   je          main+3Ch (0040b48c)9:            if (i==1) break;0040B482   cmp         dword ptr [ebp-4],10040B486   jne         main+3Ah (0040b48a)0040B488   jmp         main+3Ch (0040b48c)10:       }0040B48A   jmp         main+29h (0040b479)   


theNestruo

Syntax error in 2410
Ok

[Edit: I replaced some for(; with for(;; )]

[edited by - theNestruo on April 21, 2003 7:34:37 PM]
theNestruoSyntax error in 2410Ok
Ok, it''s solved now. Halcyon and BlueDev helped me a lot. The second parameter of the GetMessage and the PeekMessage calls should be NULL instead of hWnd.

theNestruo

Syntax error in 2410
Ok
theNestruoSyntax error in 2410Ok
What compiler is that? That''s horrible
Is that perchance a debug build?

This topic is closed to new replies.

Advertisement