Point me in the right direction please

Hello, I am working out of the book "Beginning Game Programming, Third Edition" by Jonathan S. Harbour and I am stuck on one of the end of chapter exercises.

I am being introduced into direct x by first learning the basic windows programming and getting a quick understanding of that before moving on to direct x.

The code I am posting takes a bitmap image, and runs it through a modified version of winmain to run as a "game loop" while continuing to post the image in the window to show how the loop works.



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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/**
	Beginning Game Programming, Third Edition
	Chapter 2
	GameLoop Project
**/

#include <windows.h>
#include <iostream>
#include <time.h>
using namespace std;

const string APPTITLE = "Game Loop";
HWND window;
HDC device;
bool gameover = false;

/**
 ** Loads and draws a bitmap from a file and then frees the memory
 **/
void DrawBitmap(char *filename, int x, int y)
{
	//load the bitmap image
	HBITMAP image = (HBITMAP)LoadImage(0, "c.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

	//read the bitmap's properties
	BITMAP bm;
	GetObject(image, sizeof(BITMAP), &bm);

	//create a device context for the bitmap
	HDC hdcImage = CreateCompatibleDC(device);
	SelectObject(hdcImage, image);

	//draw the bitmap to the window (bit block transfer)
	BitBlt(
		device,						//destination device context
		x,y,						//x,y location on destination
		bm.bmWidth, bm.bmHeight,	//width,height of source bitmap
		hdcImage,					//source bitmap device context
		0, 0,						//start x,y on source bitmap
		SRCCOPY);					//blit method

	//delete the device context and bitmap
	DeleteDC(hdcImage);
	DeleteObject((HBITMAP)image);
}

/**
 ** Startup and loading code goes here
 **/
bool Game_Init()
{
	//start up the random number generator
	srand(time(NULL));

	return 1;
}

/**
 ** Updage function called from inside gameloop
 **/
void Game_Run()
{
	if (gameover == true) return;

	//get the drawing surface
	RECT rect;
	GetClientRect(window, &rect);

	//draw bitmap at random location
	int x = rand() % (rect.right - rect.left);
	int y = rand() % (rect.bottom - rect.top);
	DrawBitmap("c.bmp", x, y);
}

/**
 ** Shutdown code
 **/
void Game_End()
{
	//free the device
	ReleaseDC(window, device);
}

/**
 ** Window callback function
 **/
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_DESTROY:
			gameover = true;
			PostQuitMessage(0);
			break;
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}

/**
 ** MyRegiserClass function sets program window properties
 **/
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	//create the window class structure
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX);
	//fill the struct with info
	wc.style			= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc		= (WNDPROC)WinProc;
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= hInstance;
	wc.hIcon			= NULL;
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= APPTITLE.c_str();
	wc.hIconSm			= NULL;

	//set up the window with the class info
	return RegisterClassEx(&wc);
}

/**
 ** Helper fnction to create the window and refresh it
 **/
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	//create a new window
	window = CreateWindow(
		APPTITLE.c_str(),		//window class
		APPTITLE.c_str(),		//title bar
		WS_OVERLAPPEDWINDOW,	//window style
		CW_USEDEFAULT,			//x postion of window
		CW_USEDEFAULT,			//y position of window
		640,					//width of the window
		450,					//height of the window
		NULL,					//parent window
		NULL,					//menu
		hInstance,				//application instance
		NULL);					//window parameters

		//was there an error creating the window?
		if (window == 0) return 0;

		//display the window
		ShowWindow(window, nCmdShow);
		UpdateWindow(window);

		//get device context for drawing
		device = GetDC(window);

		return 1;
	}

	/**
	 **Entry point function
	 **/
	int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
		LPSTR lpCmdLine, int nCmdShow)
	{
		MSG msg;

		//create window
		MyRegisterClass(hInstance);
		if (!InitInstance (hInstance, nCmdShow)) return 0;

		//initialize the game
		if (!Game_Init()) return 0;

		//main message loop
		while(!gameover)
		{
			//process Windows events
			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}

			//process game loop
			Game_Run();
		}

		//free game resources
		Game_End();

		return msg.wParam;
	}


Now I understand all of this code here, but what is getting me is the ending question.


"Modify the GameLoop program so that it draws just a single bitmap that moves around in the window. (Hint: You will need to make sure the bitmap doesn't "fly off" the boundaries of the window.)"

He also says on his website, regarding this question

"Well, all the code for the solution is already in the example, you just need to modify it so only one bitmap draws at a time, and then adjust the x,y position every frame so it will move. This is done by clearing the screen at the beginning of each frame before drawing."


Sorry for the long post, any help would be greatly appreciated.
You don't need to worry about boundry checking because the "GetClientRect(...)", which should NOT be run at every iteration of the game loop by the way, is used to get the coords that you draw to. So that part should be done already; unless you need to offset by the size of the image.

You have a "InitInstance(...)" function written which will clear your screen and draw the stuff to it, but it's not being called in your running loop. Double check the code in the book since this isn't the only function not being called. This is how you should render the image on the Rendering context.

Again, calling a function like "GetDC(...)" in a function that should be part of a loop is an amatuer move. If you say this is how it is in the book I'd believe you as long as you understand that it is not the way it should be done. Even if you want the window to be resizable, you should remember that resizing the window sends a message to the app which can be reacted upon.
Last edited on
Thank you for your advice, and help, greatly appreciated

- Sabal
Topic archived. No new replies allowed.