Basic GameLoop Issues using Windows Messaging ...

Started by
10 comments, last by Oluseyi 19 years, 2 months ago
I have never created an actual game loop using a window that I have created myself and implimenting messages and whatnot ... but what I thought would simply work doesnt work. Could someone help me out a bit? This is the main hassle bit:
	do
	{
	    while(GetMessage(&msg, hWnd, 0, 0)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
	    }
		XPos = 5.0;
		//Frame?
	} while (GameRuns == 1);
The XPos = 5.0 bit is never reached :-( Why is this? If you want a look at ALL of the code then here it is:
#include <windows.h>			/* must include this before GL/gl.h */
#include <GL/gl.h>			/* OpenGL header file */
#include <GL/glu.h>			/* OpenGL utilities header file */
//#include <stdio.h>

int GameRuns = 1;

GLfloat XPos = 0.0;

//int FORM_WIDTH, FORM_HEIGHT;

void display()
{

	// MODELVIEW TRANSFORMATION
	//glMatrixMode(GL_MODELVIEW);
	//clearing the background with the color specified
	glClearColor(0.0f,1.0f,0.0f,1.0f);
	//glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	//glMatrixMode(GL_PROJECTION);
	//glLoadIdentity();
	//gluPerspective(50.0, 1.0, 3.0, 7.0);
	//glMatrixMode(GL_MODELVIEW);
	//glLoadIdentity();
	//glTranslatef(-0.5f,0.0f,-0.0f);
	// Finished Drawing The Triangle
	//gluPerspective(50.0, 1.0, 1.0, 100.0);
	//gluLookAt(-1.0, 0.0, 1.5, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	/* PUSHING THE MATRIX STACK */
	//glPushMatrix();
	/*glLoadIdentity();
	glTranslatef(0.0, 0.0, -0.56);
	glBegin(GL_TRIANGLES);						// Drawing Using Triangles
		glColor3f(0.0f, 0.0f, 1.0f);			// Blue Colour
		glVertex3f( 0.0f, 1.0f, -1.0f);			// Top
		glVertex3f(-1.0f,-1.0f, -1.0f);			// Bottom Left
		glVertex3f( 1.0f,-1.0f, -1.0f);			// Bottom Right
	glEnd();*/
	//glPopMatrix();

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
        gluPerspective(50.0, 1.0, 1.0, 100.0);
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
    gluLookAt(-0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
	
	/*glBegin(GL_TRIANGLES);						// Drawing Using Triangles
		glColor3f(0.0f, 0.0f, 1.0f);
		glVertex3f( 0.0f, 1.0f, -1.0f);				// Top
		glVertex3f(-1.0f,-1.0f, -1.0f);				// Bottom Left
		glVertex3f( 1.0f,-1.0f, -1.0f);				// Bottom Right
		glColor3f(1.0f, 0.0f, 0.0f);
		glVertex3f( 0.0f, 1.0f, -2.0f);				// Top
		glVertex3f(-1.0f,-1.0f, -2.0f);				// Bottom Left
		glVertex3f( 1.0f,-1.0f, -2.0f);				// Bottom Right
	glEnd();							// Finished Drawing The Triangle*/
glBegin(GL_TRIANGLES); // Drawing Using Triangles glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( -9.5f + XPos, 1.0f, -2.0f); // Top glVertex3f(-10.0f + XPos,-1.0f, -2.0f); // Bottom Left glVertex3f( -9.0f + XPos,-1.0f, -2.0f); // Bottom Right glEnd(); // Finished Drawing The Triangle glFlush(); } LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static PAINTSTRUCT ps; switch(uMsg) { case WM_PAINT: display(); BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); return 0; case WM_SIZE: /*FORM_WIDTH = LOWORD(lParam); FORM_HEIGHT = HIWORD(lParam);*/ glViewport(0, 0, LOWORD(lParam), HIWORD(lParam)); // PROJECTION TRANSFORMATION //glMatrixMode(GL_PROJECTION); //glLoadIdentity(); //glFrustum(10, 10, 10, 10, 1, 20); PostMessage(hWnd, WM_PAINT, 0, 0); return 0; case WM_CHAR: /* WHEN EXCAPE KEY IS PRESSED */ switch (wParam) { case 27: /* ESC key */ GameRuns = 0; PostQuitMessage(0); break; } return 0; case WM_CLOSE: /* WHEN THE WINDOW IS CLOSED BY PRESSING X BUTTON */ GameRuns = 0; PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } HWND CreateOpenGLWindow(char* title, int x, int y, int width, int height, BYTE type, DWORD flags) { int pf; HDC hDC; HWND hWnd; WNDCLASS wc; PIXELFORMATDESCRIPTOR pfd; static HINSTANCE hInstance = 0; /* only register the window class once - use hInstance as a flag. */ if (!hInstance) { hInstance = GetModuleHandle(NULL); wc.style = CS_OWNDC; wc.lpfnWndProc = (WNDPROC)WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "OpenGL"; if (!RegisterClass(&wc)) { MessageBox(NULL, "RegisterClass() failed: Cannot register window class.", "Error", MB_OK); return NULL; } } hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, x, y, width, height, NULL, NULL, hInstance, NULL); if (hWnd == NULL) { MessageBox(NULL, "CreateWindow() failed: Cannot create a window.", "Error", MB_OK); return NULL; } hDC = GetDC(hWnd); /* there is no guarantee that the contents of the stack that become the pfd are zeroed, therefore _make sure_ to clear these bits. */ memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | flags; pfd.iPixelType = type; pfd.cColorBits = 32; pf = ChoosePixelFormat(hDC, &pfd); if (pf == 0) { MessageBox(NULL, "ChoosePixelFormat() failed: Cannot find a suitable pixel format.", "Error", MB_OK); return 0; } if (SetPixelFormat(hDC, pf, &pfd) == FALSE) { MessageBox(NULL, "SetPixelFormat() failed: Cannot set format specified.", "Error", MB_OK); return 0; } DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); ReleaseDC(hWnd, hDC); return hWnd; } int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR lpszCmdLine, int nCmdShow) { HDC hDC; /* device context */ HGLRC hRC; /* opengl context */ HWND hWnd; /* window */ MSG msg; /* message */ hWnd = CreateOpenGLWindow("XyuRi", 100, 100, 640, 480, PFD_TYPE_RGBA, 0); if (hWnd == NULL) {exit(1);} hDC = GetDC(hWnd); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); ShowWindow(hWnd, nCmdShow); /* ENABLE DEPTH BUFFERING! */ glEnable(GL_DEPTH_TEST); do { while(GetMessage(&msg, hWnd, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } XPos = 5.0; //Frame? } while (GameRuns == 1); wglMakeCurrent(NULL, NULL); ReleaseDC(hWnd, hDC); wglDeleteContext(hRC); DestroyWindow(hWnd); return msg.wParam; } Any help with this is greatly appreciated as per usual :-) Thanks.
__________Michael Dawson"IRC is just multiplayer notepad." - Reverend
Advertisement
It never gets to the XPos = 5.0 as GetMessage is a blocking function, that is it does not return until after it has handled a message, which means that the loop condition is never false.

instead use PeekMessage this will allow your program to continue.
Quote:Original post by Dragoncar
It never gets to the XPos = 5.0 as GetMessage is a blocking function, that is it does not return until after it has handled a message, which means that the loop condition is never false.

instead use PeekMessage this will allow your program to continue.

Thank you very much Dragoncar :-)

This document looks useful.
__________Michael Dawson"IRC is just multiplayer notepad." - Reverend
I still cant get it working :-( Anyone know of or got a very basic example?
__________Michael Dawson"IRC is just multiplayer notepad." - Reverend
this

Are you sure its not being reached. Also if its a float it should be 5.0f

You should really use PeekMessage.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                          
Looking for video game music? Check out some of my samples at http://www.youtube.c...ser/cminortunes            
                                                          
I'm currently looking to create music for a project, if you are interested e-mail me at cminortunes@gmail.com    
                                                          
Please only message me for hobby projects, I am not looking to create music for anything serious.
Quote:Original post by Dragoncar
It never gets to the XPos = 5.0 as GetMessage is a blocking function, that is it does not return until after it has handled a message, which means that the loop condition is never false.

instead use PeekMessage this will allow your program to continue.

PeekMessage() is the right thing to use, but it is not entirely true that the loop condition is never false -- GetMessage() returns false when the quit message is posted. Thus, used correctly GetMessage() ensures that your program stays in the message loop as long as the main program is running. Then, when you exit, it exits the loop to allow any clean up code after the loop to run.
Then what do I do with the ...
wc.lpfnWndProc   = (WNDPROC)WindowProc;

... part of my app?
__________Michael Dawson"IRC is just multiplayer notepad." - Reverend
Quote:Original post by xyuri
Then what do I do with the ...
wc.lpfnWndProc   = (WNDPROC)WindowProc;

... part of my app?


The same as what you were doing before when you had the GetMessage function.

ie. This method still handles the messages recieved by your program.
hehe, I sorta got it working ......

Because my app only draws to the screen with the PAIN message, I just told it to paint every time, therefore processing it and passing that loop ....

	do	{	    //while(GetMessage(&msg, hWnd, 0, 0)) 		XPos += 0.001;		PostMessage(hWnd, WM_PAINT, 0, 0);		while(PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)) 		{			TranslateMessage(&msg);			DispatchMessage(&msg);	    }		//Frame?	} while (GameRuns == 1);

Dunno if it is the correct way to go about this, but it works ... Now for double buffering to get rid of the clicker :( ....
__________Michael Dawson"IRC is just multiplayer notepad." - Reverend
Well, my current game loop looks like this...

while(1){		if(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))	{				if(msg.message == WM_QUIT) break;				TranslateMessage(&msg);		DispatchMessage(&msg);			}	else	{				Update();			}	}

..and it works very well. No-one uses WM_PAINT for an app that continuously draws to it's window, such as a game. I just call ValidateRect(hWnd, NULL) in the WindowProc when a WM_PAINT message arrives, so that Windows doesn't send any more WM_PAINT messages. All my game code, including the rendering code, is called in the Update function. It's the best way to do it...

PS. You could replace the 1 in the while loop with your GameRuns variable for another way to end the program. I just use 1 and call PostQuitMessage when I want to quit the program.
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]

This topic is closed to new replies.

Advertisement