Static Bool gameOver Variable issues

The code may seem overwhelming at first glance but the intent is simple. Currently, I am having issues figuring out how to assign false to "static bool gameOver member variable" in the "static LRESULTS CALLBACK System::WinProc" function.

If you look at my System::Run function under the D3D game engine loop, you can see the game loop depends on the static gameOver variable to control the loop. When the class checks PeekMessage() and calls WndProc(), I cannot set gameOver to false during the WM_CLOSE message. Can someone help me figure the reason why?

I believe the issue has to do with using a static variable inside a static function.

Compiler Results:
1>System.obj : error LNK2001: unresolved external symbol "public: static bool System::gameOver" (?gameOver@System@@2_NA)


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
/**************/
/*  System.h  */
/**************/

#pragma once
#include <Windows.h>

class System
{
public:
	System(HINSTANCE);  
	~System(void);
	bool InitializeWindow();										//Initialize , register, show, and update the class
	System* globalSystemInstance;
	bool InitializeDirectx(HWND);
	static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);	//Message Processing
	WPARAM Run(bool);													//Windows Application Loop
	HINSTANCE GetHinstance() { return hInstance; };
	HWND GetHwnd() { return hwnd; };
	void Render();
	static bool gameOver;

private:
	//WNDCLASSEX wcex;     //Cplusplus User Cire's Correction: Removed from Class member to InitializeWindow Function
	HINSTANCE hInstance;
	HWND hwnd;
	MSG msg;
	RECT rc;
	LPCSTR newClassName;

};


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
/**************/
/*  System.cpp  */
/**************/

#include "System.h"
#include <Windows.h>


System::System(HINSTANCE instance)
{
	hwnd = 0;
	hInstance = instance;
	newClassName = "Colby";
	gameOver = false;       //No Errors
}

bool System::InitializeWindow() {
	
	WNDCLASSEX wcex;		//Cplusplus User Cire's Correction: Moved WNDCLASSEX object from private class object to function internal
	//const char newClassName[] = {"D3D Application"};

	//Set Class
	wcex.cbSize = sizeof(wcex);
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
	wcex.hCursor = LoadCursor(hInstance, IDC_ARROW);
	wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
	wcex.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
	wcex.hInstance = hInstance;
	wcex.lpfnWndProc = WndProc;
	wcex.lpszClassName = newClassName;
	wcex.lpszMenuName = NULL;                       //Cplusplus User Cire's Correction: Initialized missing wcex lpszMenuName
	wcex.style = CS_HREDRAW | CS_VREDRAW;

	//Register Windows Class
	if(!RegisterClassEx(&wcex)) { return false; }
	
	//Create Window
	hwnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, newClassName, "D3DApplication", WS_OVERLAPPEDWINDOW, 
		CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, 
		NULL, NULL, hInstance, 0);

	if(!hwnd) { return false; }

	//Show Window and Update Window
	ShowWindow(hwnd, SW_SHOW);
	UpdateWindow(hwnd);

	return true;
}

LRESULT CALLBACK System::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

	switch(msg){
	case WM_CLOSE:
		DestroyWindow(hwnd);
		gameOver = true;           //Source of the problem
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}

WPARAM System::Run(bool d3dApplication){
	//Dual purpose run function, one for normal Win32 application and one for D3D applications
	
	//Test for D3D appliaction. If false we will use GetMessage for better windows application performance
	if(!d3dApplication) {
		//Normal Win32 Message Loop
		while(GetMessage(&msg, hwnd, 0, 0 ) > 0) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		
	} else { 
		//D3D Game Engine Application Loop
		while(!gameOver) {                       //No Errors
			while(PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			} 
			Render();
		}
	}
	return msg.wParam;
}

System::~System(void)
{
	//Release interface objects
}

void System::Render() {
	//Code used for rendering
}

bool System::InitializeDirectx(HWND hwnd){
	//Code for Directx
}


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
/**************/
/* Main.cpp  */
/**************/

#include <Windows.h>
#include "System.h"
#include <d3d9.h>
#include <d3dx9.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	System EngineWindow(hInstance);

	if(!EngineWindow.InitializeWindow()) { return -1; }

	//Define Direct3D interfaces and Present_Parameter
	IDirect3D9*				pd3d;
	IDirect3DDevice9*		d3dDevice;
	D3DPRESENT_PARAMETERS	d3dpp;
	HRESULT hr;

	//Set the interfaces to zero and zero present_parameters memory
	pd3d = NULL;
	d3dDevice = NULL;
	ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

	//Create D3D Object
	pd3d = Direct3DCreate9(D3D_SDK_VERSION);
	if(!pd3d) { MessageBox(NULL, "Error Creating pd3d Interface", "D3D Error", MB_OK); return -3; }

	try {
		d3dpp.BackBufferCount = 1;
		d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
		d3dpp.BackBufferHeight = 640;
		d3dpp.BackBufferWidth = 480;
		d3dpp.hDeviceWindow = EngineWindow.GetHwnd();
		d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
		d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
		d3dpp.Windowed = true;

	} catch(...) {
		MessageBox(NULL, "Error in Present Parameters", "Error", MB_OK);
		return -3;
	}

	D3DCAPS9 caps;
	DWORD behavior;  //After figuring out hardware support, behavior object will be used when creating d3dDevice

	hr = pd3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
	
	//Chreak for hardware transform and lighting support
	if((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == FALSE || caps.VertexShaderVersion < D3DVS_VERSION(1,1)) {
		behavior = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
	} else {
		behavior = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	}

	//Create Device
	hr = pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 
		EngineWindow.GetHwnd(), behavior, &d3dpp, &d3dDevice);
	//Check for failure
	if(FAILED(hr)) { 
		MessageBox(NULL, "Failed to create D3DDevice", "D3D Error", MB_OK);
		return -3;
	}


	// ************Rendering Function**************
	d3dDevice->Clear(NULL, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 0.0f, 0);
	//You Draw Stuff in between these two statments
	d3dDevice->Present(NULL, NULL, NULL, NULL);
	
	
	EngineWindow.Run(true);

	//Destructure
	if(d3dDevice) d3dDevice->Release(); d3dDevice = NULL; //Release and set to NULL
	if(pd3d) pd3d->Release(); pd3d = NULL;				//Relase and set to NULL
	
	
	return 0; //static_cast<int>( msg.wParam );
}
Last edited on
You never define the variable.

In System.cpp at file scope (outside of any functions) you need:

bool System::gameOver = false ;
Quick reply.

Once again, you solve the problem. I did not know you needed to define the variable inside the file scope of System.cpp.

I continue to learn more c++ everyday.

Thanks again, Cire


Topic archived. No new replies allowed.