Pong failure -_-

I've recently been introducing myself to the awful world of Win32 API. I figured Pong would be a reasonable first exercise. It's been going fairly well so far, but it seems to stop drawing about 2-3 seconds in. I have no idea why this is happening.

I know I'm not following all the standards, but I'm very new at this, and it's my first win32 program.

This is my cpcPongLib.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
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

#include<windows.h>
#include<assert.h>

bool RChange = FALSE;
bool LChange = FALSE;
int LPTop = 50;
int RPTop = 50;
int RPSpeed = 0;
int LPSpeed = 0;
HWND* ParentWindow;
void cpcInitialize(HWND);
void cpcDraw(HWND);
void cpcHandleInput(WPARAM);
void DrawLeftPaddle(HDC*);
void DrawRightPaddle(HDC*);
void UpdateLeftPaddle();
void UpdateRightPaddle();
void cpcHandleInputUp(WPARAM keyReleased);
void cpcBeginLoop(HWND);
void cpcGetKeys();

void cpcBeginLoop(HWND ThisWindow)
{	
	cpcGetKeys();
	UpdateLeftPaddle();
	UpdateRightPaddle();
	InvalidateRect(ThisWindow, NULL, FALSE);
	Sleep(30);
	UpdateWindow(ThisWindow);
}
	
void cpcInitialize(HWND thisWindow)
{
	ParentWindow = &thisWindow;
}
void cpcDraw(HWND* thisWindow)
{
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(*thisWindow, &ps);	
			DrawLeftPaddle(&hdc);
			DrawRightPaddle(&hdc);
			EndPaint(*thisWindow, &ps);
}
void DrawLeftPaddle(HDC* ptr_hdc)
{
			HBRUSH greyBrush=CreateSolidBrush(RGB(0,0,20));
			RECT NewScreen = {0,0,1280,720};
			FillRect(*ptr_hdc, &NewScreen, greyBrush);	

			int LPBottom = LPTop + 80;
			HBRUSH blueBrush=CreateSolidBrush(RGB(0,0,255));
			static int x = 100;
			RECT rctB = {20,LPTop,40,LPBottom};
			FillRect(*ptr_hdc, &rctB, blueBrush);
}
void DrawRightPaddle(HDC* ptr_hdc)
{
			int RPBottom = RPTop + 80;
			HBRUSH redBrush=CreateSolidBrush(RGB(255,0,0));
			static int x = 100;
			RECT rctB = {950,RPTop,970,RPBottom};
			FillRect(*ptr_hdc, &rctB, redBrush);
}
void UpdateLeftPaddle()
{
	LPTop += LPSpeed;
}
void UpdateRightPaddle()
{
	RPTop += RPSpeed;
}
void cpcGetKeys()
{
	if(GetAsyncKeyState(VK_DOWN))
	{
		RPSpeed =10;
	}
	if(GetAsyncKeyState(VK_UP))
	{
		RPSpeed = -10;
	}
	else if(!GetAsyncKeyState(VK_DOWN) && !GetAsyncKeyState(VK_UP))
	{
		RPSpeed = 0;
	}
	if(GetAsyncKeyState('S'))
	{
		LPSpeed =10;
	}
	if(GetAsyncKeyState('W'))
	{
		LPSpeed = -10;
	}
	else if(!GetAsyncKeyState('S') && !GetAsyncKeyState('W'))
	{
		LPSpeed = 0;
	}
	
}




And this is my Main file
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

#include "cpcPongLib.h"

LRESULT CALLBACK WndProc(HWND thisWindow, UINT msg, WPARAM wParam, LPARAM lParam);  //Declare my window message handler


//BEGIN MAIN CLASS --------------------------------------------------------------------------------

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCMD){   
  WNDCLASS wc = {0};
  MSG msg;
  wc.lpszClassName = TEXT( "Windows" );
  wc.hInstance     = hInstance ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc ;
  wc.hCursor       = LoadCursor(0,IDC_ARROW);
  
  RegisterClass(&wc);
  CreateWindow( wc.lpszClassName, TEXT("   :D"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 1000, 500, 0, 0, hInstance, 0);  
    while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return (int) msg.wParam;
}

//END MAIN CLASS ----------------------------------------------------------------------------------



//BEGIN MESSAGE HANDLING --------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND thisWindow, UINT msg, WPARAM wParam, LPARAM lParam){
	switch(msg)
	{
		case WM_CREATE:
			{
				cpcInitialize(thisWindow);
				cpcBeginLoop(thisWindow);
				break;
			}
		case WM_PAINT:
			{
				cpcDraw(&thisWindow);
				cpcInitialize(thisWindow);
				cpcBeginLoop(thisWindow);
				break;
			}
 		case WM_DESTROY:
			{
				PostQuitMessage(0);
				break;
			}
	}
	return DefWindowProc(thisWindow, msg, wParam, lParam);
}



Any help is greatly appreciated. Thank you all!

Sorry for some unnecessary bits, I've changed this code so many times, and I haven't really been nearly as neat as I usually am.

Last edited on
You are treating HWND and HDC like structures. They are simply unsigned ints and should be passed by value. However, as long as you did all your address-taking and dereferencing properly (which you did), it will work. But still, DON'T DO THAT!

You are creating brushes every time you draw the paddles, but you are never destoying the brushes! You may as well create your brushes during initialization, instead of creating (and destroying) them every time you want to draw something.

Also, in WinMain, you are calling DefWindowProc even when you handle an event. Only call it if you don't handle an event.

Your main problem is overall program structure. One method of doing what you want is to use a timer. See the code below and read up on timers on MSDN: http://msdn.microsoft.com/en-us/library/ms632592(VS.85).aspx

I won't mention that you put executable code in a .h file. Oh, wait, I guess I did mention it. In the code below, I didn't try to fix everything, but it does "work".

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
/* main.c */

#include <windows.h>
#include "Pong.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE unused, LPSTR cmd, int show){
  WNDCLASS wc = {0};
  MSG msg;
  wc.lpszClassName = TEXT( "Windows" );
  wc.hInstance     = hInst ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc ;
  wc.hCursor       = LoadCursor(0,IDC_ARROW);
  
  RegisterClass(&wc);
  CreateWindow( wc.lpszClassName, TEXT("   :D"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 1000, 500, 0, 0, hInst, 0);
  while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
	switch(msg)
	{
	case WM_CREATE:
		cpcInitialize(hwnd);
		SetTimer (hwnd, 1, 50, 0);
		break;
	case WM_TIMER:
		cpcBeginLoop(hwnd);
		break;
	case WM_PAINT:
		cpcDraw(hwnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* Pong.h */

#ifndef _PONG_H_
#define _PONG_H_

#include <windows.h>

HWND ParentWindow;
void cpcInitialize(HWND);
void cpcDraw(HWND);
void cpcHandleInput(WPARAM);
void DrawLeftPaddle(HDC);
void DrawRightPaddle(HDC);
void cpcHandleInputUp(WPARAM keyReleased);
void cpcBeginLoop(HWND);
void cpcGetKeys();

#endif 


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
/* Pong.c */

#include "Pong.h"

BOOL RChange = FALSE;
BOOL LChange = FALSE;
int LPTop = 50;
int RPTop = 50;
int RPSpeed = 0;
int LPSpeed = 0;
HBRUSH greyBrush;
HBRUSH blueBrush;
HBRUSH redBrush;

void cpcBeginLoop(HWND ThisWindow)
{	
	cpcGetKeys();
	LPTop += LPSpeed;
	RPTop += RPSpeed;
	InvalidateRect(ThisWindow, NULL, FALSE);
	UpdateWindow(ThisWindow);
}

void cpcInitialize(HWND thisWindow)
{
	ParentWindow = thisWindow;
	greyBrush=CreateSolidBrush(RGB(0,0,20));
	blueBrush=CreateSolidBrush(RGB(0,0,255));
	redBrush=CreateSolidBrush(RGB(255,0,0));
}
void cpcDraw(HWND thisWindow)
{
	PAINTSTRUCT ps;
	HDC hdc = BeginPaint(thisWindow, &ps);
	DrawLeftPaddle(hdc);
	DrawRightPaddle(hdc);
	EndPaint(thisWindow, &ps);
}
void DrawLeftPaddle(HDC ptr_hdc)
{
	RECT NewScreen = {0,0,1280,720};
	FillRect(ptr_hdc, &NewScreen, greyBrush);
	int LPBottom = LPTop + 80;
	static int x = 100;
	RECT rctB = {20,LPTop,40,LPBottom};
	FillRect(ptr_hdc, &rctB, blueBrush);
}
void DrawRightPaddle(HDC ptr_hdc)
{
	int RPBottom = RPTop + 80;
	static int x = 100;
	RECT rctB = {950,RPTop,970,RPBottom};
	FillRect(ptr_hdc, &rctB, redBrush);
}
void cpcGetKeys()
{
	if(GetAsyncKeyState(VK_DOWN))
		RPSpeed =10;
	else if(GetAsyncKeyState(VK_UP))
		RPSpeed = -10;
	else
		RPSpeed = 0;
	if(GetAsyncKeyState('S'))
		LPSpeed =10;
	else if(GetAsyncKeyState('W'))
		LPSpeed = -10;
	else
		LPSpeed = 0;
}

Last edited on
Thank you so very very much!

I know it's frustrating to see someone make such stupid mistakes, but I appreciate your help nonetheless. I'm still very new at all this, but I'm learning and I'm very willing to change my methods of doing things, because I know I'm doing things wrong.

I'm pretty happy with myself for coming as far as I did, my only reference was a single Win32 API tutorial. The most difficult part of this process is finding information. I find MSDN to be very confusing at times... occasionally I'll look for a function and then find one that seems completely different from the one I'm trying to use.

Also, I'm trying to figure out the whole "Don't code in header files" thing. I understand it's just a standard, but where else should I code other than my main .cpp file and my header files?

Thanks again!
Last edited on
MSDN is insane. Probably not the place to learn from. A good author for windows programming is Petzold. But you do have to get used to browsing through MSDN and finding the correct functions. It takes a while to get used to.

You can have as many cpp files as you want. Just put them in the same project and they will all be compiled separately and then linked together to create the executable. The purpose of header files is to provide the information to allow separate compilation of multiple code files.
Topic archived. No new replies allowed.