Code Examples
  Home arrow Code Examples arrow Page 8 - Creating an Engine for Games for Windows
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
ASP Web Hosting  
ASP.NET Web Hosting 
Mobile Linux 
App Generation ROI 
Windows Web Hosting
 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
CODE EXAMPLES

Creating an Engine for Games for Windows
By: Sams Publishing
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 4 stars4 stars4 stars4 stars4 stars / 41
    2004-10-13

    Table of Contents:
  • Creating an Engine for Games for Windows
  • What is a Game Engine?
  • Breaking a Game Down into Events
  • Developing a Game Engine
  • The GameEngine Class
  • Source Code for the WinMain Function
  • Initializing Variables
  • HandleEvent Method
  • Put the Engine to Work
  • Resource.h Header File
  • Testing the Finished Product

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Creating an Engine for Games for Windows - HandleEvent Method


    (Page 8 of 11 )

    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.h>
    //————————————————————————————————-
    // 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.


    Note - If you're a bit intimidated by seeing this much code in only the second chapter of the book, let me ease your concerns by explaining that building games on top of the game engine is more straightforward than building the game engine itself. You'll find that game code is made much simpler thanks to the work put into the game engine.


    SamsThis chapter is from Beginning Game Programming, by Michael Morrison (Sams, ISBN: 0672326590). Check it out at your favorite bookstore today.

    Buy this book now.

    More Code Examples Articles
    More By Sams Publishing


     

    CODE EXAMPLES ARTICLES

    - Handling Animations and Bitmaps Using GDI+ f...
    - Download a Web Page using the WebClient
    - Creating a Chart using Data from a Database ...
    - The Basics of Charting with the MS Chart Con...
    - Searching Body Text with textRange: Enter th...
    - Searching Body Text with textRange: Building...
    - Searching Body Text with textRange, part 1: ...
    - First Steps in Programming
    - Programming in C
    - Quick Introduction to ASF,ASX, and Networkin...
    - SatView: Pointer Perfect, Part 2: Constructi...
    - SatView: Pointer Perfect, Part 1
    - Style Case Studies: Construction Unions
    - Creating an Engine for Games for Windows
    - Style Case Studies: Generic Callbacks





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 4 hosted by Hostway
    Stay green...Green IT