Window opens, then closes

Pages: 12
So I've made a game engine according to Michael Morrison's "Beginning Game Programming". My first real program using the engine didn't work, so I decided to try to test it with a "GameEngine Test" project. When I compile and run the program, it opens and immediately closes the window. Here's the code:
---"Game Engine.cpp"---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//------------------------------------------------------------------------------
// Game Engine.cpp Source code
//------------------------------------------------------------------------------
#include "Game Engine.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);
}
    
    // Game Engine 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_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 on 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 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;
                    break;
               case WM_SETFOCUS:
                    // Activate the game and update the Sleep status
                    GameActivate(hWindow);
                    SetSleep(FALSE);
                    return 0;
                    break;
               case WM_KILLFOCUS:
                    // Deactivate the game and update the Sleep status
                    GameDeactivate(hWindow);
                    SetSleep(TRUE);
                    return 0;
                    break;
               case WM_PAINT:
                    HDC            hDC;
                    PAINTSTRUCT    ps;
                    hDC = BeginPaint(hWindow, &ps);
                    
                    // Paint the game
                    GamePaint(hDC);
                    
                    EndPaint(hWindow, &ps);
                    return 0;
                    break;
               case WM_DESTROY:
                    // End the game and exit the application
                    GameEnd();
                    PostQuitMessage(0);
                    return 0;
               }
        return DefWindowProc(hWindow, msg, wParam, lParam);
}
Last edited on
(Continued)
---"Game Engine.h"---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#ifndef GAMEENGINE_H
#define GAMEENGINE_H

//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
These functions are game-specific and must be specified per game */
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);
             //For different sizes, change this ^^^       and this  ^^^
             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; };
};

#endif 
Last edited on
For the love of... I have never been one to refuse to help people because they didn't use code blocks. But this has no code blocks, no indentation, multiple declerations of the same stuff as far as I can tell, inadequate spacing, non-standard notation... The list just keeps going. How can you even read this?
@OP Your code would indeed be more readable if, for a start, you used code tags:
[code]int main()[/code] = int main()
As for indentation, most common IDEs will do that for you these days... Which one are you using?

@Computergeek:
because they didn't use code blocks

Lol, at first I thought you meant the IDE!
Ah! Code Tags, yes I did mean Code Tags. Brain Fart.
Still, Code::Blocks is good too :P
EDIT: I assumed then that by code blocks (no scope resolution operator), you meant splitting code segments with frequent vertical white space - also a good idea ;)
Last edited on
@Xander: How in the wooooorld do you manage to write [ code ] without making it a code block!?? LOL. It kills me not to know!
I use Teletype when ever it comes up. [tt][/tt]
Hehe I saw someone else do it - and I worked out how from seeing the unformatted summary on the "My Topics" page.

I do this:
[co[i][/i]de]...[/co[i][/i]de]

And I have now done the same thing for italic tags :)

EDIT: It was 58 characters unformatted!

PS: @OP I feel bad we haven't provided any help yet and have started chatting on your thread. I'm just about to go out now, so I can't look now, but if you add code tags, and preferably indentation, I'll take a closer look at your code later if I get the chance :)
Last edited on
Sorry about that. This was my first post ever on cplusplus.com, so I didn't know how to use the code tag.
As for my IDE, I'm using Bloodshed Dev-C++, but I'd be inclined to use a different one if someone suggested another. I've tried Microsoft Visual C++ 2010 already, though, and it's not as straightforward as Dev-C++.
You can try CodeBlocks (http://www.codeblocks.org )

and read why you shouldn't use Dev-C++: http://www.cplusplus.com/forum/articles/36896/
wxDev-C++ is sort of the succesor to Bloodshed: http://wxdsgn.sourceforge.net/
There's nothing wrong with Code::Blocks but with wx you'll have less of a learning curve.
It seems that Code::Blocks is pretty straightforward. Now that I run the GameEngine Test file with Code::Blocks, I get a different error message:
"Warning `x -c' after last input file has no effect
no resources"
I'll post the rest of the code for the GameEngine Test project soon.
Sorry about that. This was my first post ever on cplusplus.com

Don't worry about it - it takes a while for any of us to get used to the conventions of any new forum :)
Code that I promised:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//Game Engine Test.cpp file
#include "GameEngine Test.h"

BOOL GameInitialize(HINSTANCE hInstance)
{
       g_pGame = new GameEngine(hInstance, TEXT("GameEngine Test"), TEXT("GE Test"),
               IDI_SMILEY, IDI_SMILEY_SM);
       if (g_pGame == NULL)
       return FALSE;
       
       g_pGame->SetFrameRate(1);
       
       return TRUE;
}

void GameStart(HWND hWindow)
{
}

void GameEnd()
{
     delete g_pGame;
}

void GameActivate(HWND hWindow)
{
}

void GameDeactivate(HWND hWindow)
{
}

void GamePaint(HDC hDC)
{
}

void GameCycle()
{
}

1
2
3
4
5
6
7
8
9
10
//GameEngineTestResources
//A.K.A. GETRes.h

#ifndef GETRES_H
#define GETRES_H

#define IDI_SMILEY       1000
#define IDI_SMILEY_SM    1001

#endif 

1
2
3
4
5
6
7
8
9
10
11
12
//GameEngine Test.h Header file

#ifndef GAMEENGINETEST_H
#define GAMEENGINETEST_H

#include <windows.h>
#include "Game Engine.h"
#include "GETRes.h"

GameEngine* g_pGame;

#endif 

1
2
3
4
5
6
//GameEngine Test.rc

#include "GETRes.h"

IDI_SMILEY         ICON     "SkelRes\\Skeleton.ico"
IDI_SMILEY_SM      ICON     "SkelRes\\SkeletonSm.ico"
I very much doubt any of that code is causing the error you still have. If anything, it sounds like something to do with Code::Blocks configuration.
That last warning you mentioned sounds like you have some stray commands in your linking section of the IDE.

EDIT: Also if your window is opening and imediatly closing then This may be caused by Line 19 + 20 in your WinMain function. You have return FALSE; on Line 20 which would quite the program immediatly when that condition is met.
Last edited on
The If statement closes the window if the game engine cannot be initialized, so as long as the game engine is initialized, it won't need to return FALSE. Besides that, I only had the opening/closing problem on Dev-C++.
Any ideas what I might need to change in Code::Blocks so the project runs correctly? I'm using the default specifications. To make the file, I used New Project > Win32 GUI Application, and ticked the "Do not create any files" box.
Did you find any stray commands in your linker section?
Linker section? Excuse me, I'm still a little new to programming. How do I view the linker section with Code::Blocks?
Pages: 12