Game Engine

HandleEvent Method

Listing 2.5 The GameEngine::HandleEvent() Method Receives and Handles Messages that Are Normally Handled in WndProc()
LRESULT GameEngine::HandleEvent(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Route Windows messages to game engine member functions switch (msg)
{
case WM_CREATE:
// Set the game window and start the game
SetWindow(hWindow);
GameStart(hWindow);
return 0;
case WM_SETFOCUS:
// Activate the game and update the Sleep status
GameActivate(hWindow);
SetSleep(FALSE);
return 0;
case WM_KILLFOCUS:
// Deactivate the game and update the Sleep status
GameDeactivate(hWindow);
SetSleep(TRUE);
return 0;
case WM_PAINT:
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hWindow, &ps);
// Paint the game
GamePaint(hDC);
EndPaint(hWindow, &ps);
return 0;
case WM_DESTROY:
// End the game and exit the application
GameEnd();
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWindow, msg, wParam, lParam);
}
The HandleEvent() method contains a switch statement that picks out Windows messages and responds to them individually. The HandleEvent() method also makes calls to game engine functions whose implementations are specific to each different game. First, the WM_CREATE message is handled, which is sent whenever the main game window is first created. The handler code for this message sets the window handle in the game engine and then calls the GameStart() game event function to get the game initialized.

The WM_SETFOCUS and WM_KILLFOCUS messages inform the game whenever its window receives (activated) or loses (deactivated) the input focus, respectively. If the game window is being activated (gains focus), the GameActivate() function is called, and the game is awoken. Similarly, if the game window is being deactivated (loses focus), the GameDeactivate() function is called, and the game is put to sleep.

The remaining messages in the HandleEvent() method are pretty straightforward in that they primarily call game functions. The WM_PAINT message handler calls the standard Win32 BeginPaint() function followed by the GamePaint() function. The EndPaint() function is then called to finish up the painting process; you learn a great deal more about BeginPaint() and EndPaint() in the next chapter. Finally, the WM_DESTROY handler calls the GameEnd() function and then terminates the whole program.

To help put all this game engine code into perspective, check out Listings 2.6 and 2.7, which contain the complete GameEngine.h header and GameEngine.cpp source code files. Please note that you don't need to understand every little nuance of this code in order to build games based on it. It will make much more sense as you get comfortable using it to build games throughout the book.
Listing 2.6 The Complete GameEngine.h Header Code
#pragma once
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
// Include Files
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
#include

//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
// Windows Function Declarations
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
// Game Engine Function Declarations
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
BOOL GameInitialize(HINSTANCE hInstance);
void GameStart(HWND hWindow);
void GameEnd();
void GameActivate(HWND hWindow);
void GameDeactivate(HWND hWindow);
void GamePaint(HDC hDC);
void GameCycle();
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
// GameEngine Class
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
class GameEngine
{
protected:
// Member Variables
static GameEngine* m_pGameEngine;
HINSTANCE m_hInstance;
HWND m_hWindow;
TCHAR m_szWindowClass[32];
TCHAR m_szTitle[32];
WORD m_wIcon, m_wSmallIcon;
int m_iWidth, m_iHeight;
int m_iFrameDelay;
BOOL m_bSleep;
public:
// Constructor(s)/Destructor
GameEngine(HINSTANCE hInstance, LPTSTR szWindowClass, LPTSTR szTitle,
WORD wIcon, WORD wSmallIcon, int iWidth = 640, int iHeight = 480);
virtual ~GameEngine();
// General Methods
static GameEngine* GetEngine() { return m_pGameEngine; };
BOOL Initialize(int iCmdShow);
LRESULT HandleEvent(HWND hWindow, UINT msg, WPARAM wParam,
LPARAM lParam);
// Accessor Methods
HINSTANCE GetInstance() { return m_hInstance; };
HWND GetWindow() { return m_hWindow; };
void SetWindow(HWND hWindow) { m_hWindow = hWindow; };
LPTSTR GetTitle() { return m_szTitle; };
WORD GetIcon() { return m_wIcon; };
WORD GetSmallIcon() { return m_wSmallIcon; };
int GetWidth() { return m_iWidth; };
int GetHeight() { return m_iHeight; };
int GetFrameDelay() { return m_iFrameDelay; };
void SetFrameRate(int iFrameRate) { m_iFrameDelay = 1000 /
iFrameRate; };
BOOL GetSleep() { return m_bSleep; };
void SetSleep(BOOL bSleep) { m_bSleep = bSleep; };
};
Listing 2.7 The Complete GameEngine.cpp Source Code
#include "GameEngine.h"
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
// Static Variable Initialization
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
GameEngine *GameEngine::m_pGameEngine = NULL;
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
// Windows Functions
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg;
static int iTickTrigger = 0;
int iTickCount;
if (GameInitialize(hInstance))
{
// Initialize the game engine
if (!GameEngine::GetEngine()->Initialize(iCmdShow))
return FALSE;
// Enter the main message loop
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// Process the message
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// Make sure the game engine isn't sleeping
if (!GameEngine::GetEngine()->GetSleep())
{
// Check the tick count to see if a game cycle has elapsed
iTickCount = GetTickCount();
if (iTickCount > iTickTrigger)
{
iTickTrigger = iTickCount +
GameEngine::GetEngine()->GetFrameDelay();
GameCycle();
}
}
}
}
return (int)msg.wParam;
}
// End the game
GameEnd();
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Route all Windows messages to the game engine
return GameEngine::GetEngine()->HandleEvent(hWindow, msg, wParam, lParam);
}
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
// GameEngine Constructor(s)/Destructor
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
GameEngine::GameEngine(HINSTANCE hInstance, LPTSTR szWindowClass,
LPTSTR szTitle, WORD wIcon, WORD wSmallIcon, int iWidth, int iHeight)
{
// Set the member variables for the game engine
m_pGameEngine = this;
m_hInstance = hInstance;
m_hWindow = NULL;
if (lstrlen(szWindowClass) > 0)
lstrcpy(m_szWindowClass, szWindowClass);
if (lstrlen(szTitle) > 0)
lstrcpy(m_szTitle, szTitle);
m_wIcon = wIcon;
m_wSmallIcon = wSmallIcon;
m_iWidth = iWidth;
m_iHeight = iHeight;
m_iFrameDelay = 50; // 20 FPS default
m_bSleep = TRUE;
}
GameEngine::~GameEngine()
{
}
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
// Game Engine General Methods
//覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧-
BOOL GameEngine::Initialize(int iCmdShow)
{
WNDCLASSEX wndclass;
// Create the window class for the main window
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = m_hInstance;
wndclass.hIcon = LoadIcon(m_hInstance,
MAKEINTRESOURCE(GetIcon()));
wndclass.hIconSm = LoadIcon(m_hInstance,
MAKEINTRESOURCE(GetSmallIcon()));
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = m_szWindowClass;
// Register the window class
if (!RegisterClassEx(&wndclass))
return FALSE;
// Calculate the window size and position based upon the game size
int iWindowWidth = m_iWidth + GetSystemMetrics(SM_CXFIXEDFRAME) * 2,
iWindowHeight = m_iHeight + GetSystemMetrics(SM_CYFIXEDFRAME) * 2 +
GetSystemMetrics(SM_CYCAPTION);
if (wndclass.lpszMenuName != NULL)
iWindowHeight += GetSystemMetrics(SM_CYMENU);
int iXWindowPos = (GetSystemMetrics(SM_CXSCREEN) - iWindowWidth) / 2,
iYWindowPos = (GetSystemMetrics(SM_CYSCREEN) - iWindowHeight) / 2;
// Create the window
m_hWindow = CreateWindow(m_szWindowClass, m_szTitle, WS_POPUPWINDOW |
WS_CAPTION | WS_MINIMIZEBOX, iXWindowPos, iYWindowPos, iWindowWidth,
iWindowHeight, NULL, NULL, m_hInstance, NULL);
if (!m_hWindow)
return FALSE;
// Show and update the window
ShowWindow(m_hWindow, iCmdShow);
UpdateWindow(m_hWindow);
return TRUE;
}
LRESULT GameEngine::HandleEvent(HWND hWindow, UINT msg, WPARAM wParam,
_ LPARAM lParam)
{
// Route Windows messages to game engine member functions
switch (msg)
{
case WM_CREATE:
// Set the game window and start the game
SetWindow(hWindow);
GameStart(hWindow);
return 0;
case WM_SETFOCUS:
// Activate the game and update the Sleep status
GameActivate(hWindow);
SetSleep(FALSE);
return 0;
case WM_KILLFOCUS:
// Deactivate the game and update the Sleep status
GameDeactivate(hWindow);
SetSleep(TRUE);
return 0;
case WM_PAINT:
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hWindow, &ps);
// Paint the game
GamePaint(hDC);
EndPaint(hWindow, &ps);
return 0;
case WM_DESTROY:
// End the game and exit the application
GameEnd();
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWindow, msg, wParam, lParam);
}
You've now seen all the code for the game engine, which successfully hides generic Windows code while providing a basic framework for games. Let's now take a look at an example that puts this embryonic game engine to work.

Twitter

 

Developed by Virtualinfocom