#### Archived

This topic is now archived and is closed to further replies.

# Updated Pong

This topic is 5682 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have been working on Pong game. A couple of you have seen the first version, and I encourage everyone to look at this new version. During my coding spree I have fixed a few collision detection quirks, made a few minor graphical improvements (including changing the square ball into an actual circle), and even added a MENU SYSTEM! I am happiest with the menu system. Right now, it allows you to resume game, start a new game, change the ball and paddle speed and paddle length, and exit the game. Other improvements were made to the code layout where I seperated the Draw and Update functions into smaller, seperate functions (not a big deal right now, but it will be helpful when I release the code). You can grab Pong right here: Pong Thanks for looking. Feedback and criticism are wanted and appreciated.

##### Share on other sites
It''s much better than the old version, but I''ve found a couple of bugs:
The paddle suddenly jumps to the bottom of the screen occasionaly
The ball once seemed to ''stick'' to the cpu''s paddle (looked like it was quickly bouncing back and forth)

Also, some graphics would be great, such as a wood texture on the paddles, a background image etc.

##### Share on other sites
Hmm, I thought I had fixed the paddle jump in this version. I am not really sure what causes it, but I think it may be due to a jump in the time (for instance, the reading from GetTickCount() spikes when the down arrow is pressed). Otherwise, I have no idea what could cause that jump, because I only change the paddle position during VK_UP or VK_DOWN. I did add a little "spike" protection, and I didn't see it happen to me. I'll fool around with it tomorrow and hopefully be able to post an updated version.

As for the sticking ball, I also am not sure what causes it. I'll search for the problem tomorrow, and if I don't make any progress, I'll post my paddle collision code here and hopefully someone will be able to diagnose my problem. I think the ball might be getting stuck between the paddle and the ball, but it really shouldn't because I reverse the direction and place the ball a few pixels away from the paddle.

As for graphical improvements, I'll fool around with some ideas after I iron out the two problems you mentioned. Personally, I think Pong works best as a black and white game, but I guess a little variety couldn't hurt. Perhaps I'll even overhaul my menu system and add a seperate options section (where color could be selected, computer difficulty level, speed, etc). I might even throw in some texture options if I find some suitable ones and they look good enough.

Thanks for the feedback, Sibbo. I'll probably be back in this thread tomorrow asking for help, but I guess having bugs is the only way you learn. By the way, how did you fare against the computer? It still only tracks the y-axis movement of the ball, which is probably the most accurate AI you can implement short of using trigonometry. In future version I hope to make the computer a little less difficult (I was thinking of limiting the computer's "vision"; on a lower difficulty, it would only react when the ball is on its half of the screen; on a higher level, it would react wherever the ball is, like it does now... what do you think of that?).

To everyone else: More feedback is welcome!

EDIT: Whoops, I hit the Post button before I even finished writing the message. Guess I got excited.

[edited by - Erunama on June 27, 2002 11:28:29 PM]

##### Share on other sites
quite possible thats the reason for the spikes. basically you should be using WM_KEYUP and WM_KEYDOWN which will set a varible to let the paddle to know which way to move. it should move along with the other game logic and not be seperated like you seem to have it.

when you recieve a WM_KEYDOWN, you check whether its VK_LEFT or VK_RIGHT. then set a varible paddleDirection to the correct value. maybe 1 for left 2 for right and 0 more no movement. when the player releases the key, you will recieve a WM_KEYUP. you check to make sure its either VK_LEFT or VK_RIGHT. if it is you set playerDirection to 0.

now in yoru movement code (ie where you handle moving the ball and cpu paddle), you do a simple switch statement:

{
case 0: // dont move
break;
case 1: // move left
break;
case 2: // move right
break;
}

dont forget to check and make sure the paddle dont go off the edge of the screen. this should fix any jumping you are having. i only suggest this since no one has complained about the ball jumping, so its very likly the cause.

aslo remove the paddle code you have from WM_CHAR if thats where you are checking stuff now. it will mess things up if you choose to use the approach i suggested.

##### Share on other sites
I''m not sure you understand what I am doing. I am using WM_KEYDOWN and checking for VK_UP and VK_DOWN (not left and right... pong is vertical, not horizontal). I am not using WM_CHAR (in case you were wondering how keyboard input is configured, I am using NeHeGL).

And keyboard input moves along with the rest of the game logic. Basically, my Update function checks for a few certain keys (like ESC, F for framerate toggle, P for pause, F1, +, and -). Then, if the game is currently looping, I go into an UpdateGame function (which handles ball movement, scoring, collision detection, and paddle movement). Yes, it is in a seperate function, but that was necessary. Otherwise, when the menu is up, the ball would still be bouncing around. And it is called with the other game logic. If the game is not looping, an UpdateMenu function is called (handles up and down selection of menu options and checks for hitting Enter).

If you want to see some code, here is the code to handle the UP and DOWN keys:

      // User paddle movement    if (g_keys->keyDown [VK_UP] == TRUE)    {        if(paddleA > (20 + (pLength/2)))        {            if((time/10) < 50)            {                paddleA -= pSpeed*(time/10);            }            if((paddleA - (pLength/2)) < 20)                paddleA = 20 + (pLength/2);        }    }    if (g_keys->keyDown [VK_DOWN] == TRUE)    {        if((paddleA + (pLength/2)) < HEIGHT)        {            if((time/10) < 50)            {                paddleA += pSpeed*(time/10);            }            if((paddleA + (pLength/2)) > HEIGHT)                paddleA = HEIGHT - (pLength/2);        }    }

paddleA is the current y-axis position of the paddle (x-axis stays the same). pLength is the length of the paddle. HEIGHT is a macro to the window HEIGHT (g_window->init.height). pSpeed is a speed constant for the paddles (allows them to be sped up in game). Time is an int passed into the UpdateGame function. It comes from the main loop from GetTickCount, which is subtracted from the previous frames count and passed as DWORD milliseconds into the Update function. I switch it to an int because I wasn''t sure if there were any problems with multipying integers by a DWORD.

I hope that clears up some of the concerns you had, Person.

##### Share on other sites
You could try using GetAsyncKeyState for keyboard input (trouble is on slower computers you''ll lose keypresses). At the very least, it''ll show you whether the spike is caused by WM_KEYDOWN.

The cpu is impossible to beat at low speed setting, but I can beat it when speed is 6 or above. Maybe you could give the cpu paddle a max speed, and if the ball is too high or too low, increase its speed, but not letting it exceed its max speed. Not sure if it''ll work well but it''s an idea.

Another idea to make the game better is add music/sfx which should be easy enough with a library like bass or fmod.

Also, I think the paddle quirk could be caused by the delta time. If you are checking for collision, and inverting the direction, try also moving the ball so that it only touches the paddle, but is not half inside it.

Eg.
{
BallSpeedX = 1;
}

That''ll prevent it switching direction again next frame and bouncing back and forth.

Hope you can understand my jibberish

##### Share on other sites
Thanks for the suggestions. I am looking into GetAsyncKeyState right now. I hope it is simply a drop in function call (and I hope it is not a DirectX function).

I''ll try fooling around with some Computer AI today. The hardest part will probably be adding an options menu. I have actually been thinking about adding CD music play to the game. It seems extremely easy to implement through FMOD and FSOUND_CD_PLAY, but I might hold off because that would add yet another .dll to the package. Is there anyway to get the program to find a DLL in a subfolder?

And I already invert the direction and move the ball outside of the paddle. Since my entire ball-paddle collision code is in a seperate function, I''ll just drop it in here for you to look at:

  void CheckBallPaddle(void){    if(ballX <= 13)    {        if(((ballY + 2) >= (paddleA - (pLength/2))) && ((ballY + 2) <= (paddleA + (pLength/2))))        {            ballX = 13;            dirX = -dirX;            if(((ballY + 2) >= (paddleA - (pLength/2))) && (ballY + 2 < paddleA))                dirY = -1;            else if(ballY == paddleA) { }            else { dirY = 1; }        }    }    if(ballX >= 627)    {        if(((ballY + 2) >= (paddleB - (pLength/2))) && ((ballY + 2) <= (paddleB + (pLength/2))))        {            ballX = 627;            dirX = -dirX;            if(((ballY + 2) >= (paddleB - (pLength/2))) && ((ballY + 2) < paddleB))                dirY = -1;            else if(ballY == paddleB) { }            else { dirY = 1; }        }    }}

A couple things about the code:
- I only check for collisions if the ball is near the edges of the screen (under 13 or above 627 pixels). That way, I can avoid going into more complex IF statements the majority of the time.
- If the ball is near the edges, then I check to see if the ball''s y-axis value is within the paddle''s reach. If it is, then a collision is "detected."
- The ball''s x value is moved 6 pixels outside of the paddle''s center.
- If the ball hits the top half of the paddle, the ball is deflected upward; if it hits the middle, the y direction stays the same; if it hits the bottom, the ball is deflected downward.
- The (ballY + 2) is to give a little more room to make successful contact. Since the ballY value is located at the center of the ball, and the ball has a radius of 5, a person make score even if there appears to be successful contact.

Thanks for the input!

##### Share on other sites
Ok, I threw GetAsyncKeyState in there and the paddle still jumps to the bottom. I am really perplexed by this problem, since 'a person' brought up a good point: it really can't be a jump in time, since the ball does not jump as well.

In case your curious, here is the updated key code:

        // User paddle movement    //if (g_keys->keyDown [VK_UP] == TRUE)    if (GetAsyncKeyState(VK_UP))    {        if(paddleA > (20 + (pLength/2)))        {            if((time/10) < 50)            {                paddleA -= pSpeed*(time/10);            }            if((paddleA - (pLength/2)) < 20)                paddleA = 20 + (pLength/2);        }    }    //if (g_keys->keyDown [VK_DOWN] == TRUE)    if (GetAsyncKeyState(VK_DOWN))    {        if((paddleA + (pLength/2)) < HEIGHT)        {            if((time/10) < 50)            {                paddleA += pSpeed*(time/10);            }            if((paddleA + (pLength/2)) > HEIGHT)                paddleA = HEIGHT - (pLength/2);        }    }

Should I even bother keeping this code now, since it didn't fix the problem? Is using keyDown a more efficient way of working?

EDIT: And, by the way, that if((time/10 < 50) is supposed to protect from time spikes.

[edited by - Erunama on June 28, 2002 10:53:19 AM]

##### Share on other sites
Hmm, I did some more testing, and it seems the paddle jump only occurs when the paddle speed is 6 or above, though I can''t think of any reason why that should happen.

If the GetAsynKeyState doesn''t help, I''d suggest going back to WM_KEYDOWN, due to potentially losing keypresses.

Also, about the dll''s, I''m not sure about searching sub-dirs but it is possible to include it as a resource, write it to disk during run-time, and delete it when your app closes. If you have BASS, it has an example on how to do this (if not, go to www.un4seen.com)

##### Share on other sites
I was on a coding spree today, so if you get a chance, here is an updated version:
Pong

Unfortunately, I wasn''t able to hash out the jumping problem, because I still have no idea what is causing it. Hopefully, some other people will stop by this thread and make some suggestions.

New features:
- CD playback! I am really proud of myself for this one. For my computer, the default drive setting (passing ''0'' into the FSOUND functions) looks to my CD burner, not my main CD/DVD drive. So I made a little while loop to search for a CD drive with a CD inserted. Make sure the CD is an audio CD, because I don''t think FMOD has any protection against ''playing'' data CDs.
- I wanted to have color options in this version, and the structure for it is in there (there are even options), but I was having a little trouble with a switch statement to change the color arrays. I also added code to display a colored box next to ''Background'' and ''Paddle Color'' to show the current color, but it isn''t coming up.

Hopefully I don''t have to add any more menus, because they are a pain in the butt to add. It is fairly easy to add additional options, but a whole new menu requires a bunch of additional if statements and a couple of switches.

Hope you enjoy the new version. All changes were aesthetic, because I still can figure out the physics problems I am having. If we (me and you, Sibbo) can''t figure it out, I''ll probably post something in the ''Game Programming'' forum.

Enjoy!

##### Share on other sites
Looking good Erunama. Other than a few collision detect problems with the paddles, I didn''t notice any problems. Keep it up.

I know only that which I know, but I do not know what I know.

##### Share on other sites
It ran VERY slow on my computer to the extent that it was unplayable. I tried messing with the speed settings in the options and it made a difference, but it was slow none the less. The odd thing was that I was getting around 294 FPS, but the slowness looked like it was going 2-3 FPS.

Aside from that, I think the menus look pretty good. Add some graphics on the ball and the paddles, and maybe a background picture and you''d have a fullblown pong game

My system specs:

Intel Pentium III (500 MHz)
256 MB RAM
Riva TNT2

I''m running it on Windows98.

##### Share on other sites
Actually, I have noticed the slowness too. Most of the time, the game runs very smoothly on my computer, but everyone once and a while it will look choppy and the speed will slow down for a couple seconds (I noticed this a week ago, when the game normally runs around 60 fps on my computer, but sometimes it shoots up to 120 fps and it runs slower). I thought this was just something with my computer, but since you seem to have the problem (on a better computer), there must be a bug.

A possible item of good news: I have not seen the ball getting stuck in the paddle after playing for a little while. I guess one of my little tweaks got rid of it, but I am not really sure.

blueEbola: You didn''t specifically mention it, but did you notice the paddle flying to the bottom or the ball getting stuck in the paddle? And did you try out the CD player feature? I was dancing around the room when my Weezer CD actually played inside of my program.

Colors should be coming in the next update. Textures and sound effects in a week or two (where can I get some nice textures from?).

I''m going to head over to the ''Game Programming'' forum and post a question about this problem. I can''t think of anywhere else to ask for help (since this isn''t an OGL-specific problem).

##### Share on other sites

When I was patient enough for the ball to reach the paddle (still goin pretty slow) it got stuck to it The right paddle jumped around quite a bit too, like when the paddle was at the bottom I pressed up about twice and it jumped to the top ..

So yeah, basically I was having all the problems that have been listed by everybody else. The "ball sticking to the paddle" problem may be due to the collision detection your using, but I don''t know about the other problems, but I think the slowness may be a problem with the time-based movement.

Now for the good news: Yeah, the CD player works! I was dancing to AoE2 music, lol

##### Share on other sites
If any of you stopped by the Game Programming forum, you might know that the left paddle problem has been solved. Whenever a paddle moves below the bottom of the screen, I reset it to the bottom of the screen before it is drawn. I wrote the code for this for the left paddle first, and then I just copied and pasted the code for the right paddle, changing all of the paddleA variables to paddleB. Turns out that I forgot to change one, so whenever the right paddle went below the bottom of the screen, the left paddle was moved to the bottom (and I guess that the right paddle also went a little below the screen, but since the ball moves pretty fast and it tracks the ball, it was not noticeable). A huge thanks to CWizard, because his observation led me to check that part of the code.

I won''t upload a new version yet. I''d like to hold off and try to get the colors working and hopefully fix the timing issue. Here''s what I am thinking regarding the slowness: As the frame rate increases, the time variable continues to drop. Since I divided this variable by 10 (or 5, can''t remember) in the movement calculations, and since that variable is an integer, it may be truncated to 0 some frames, and other times be 1 or more. Does this sound reasonable? I suppose I could make the variable 1 when it is 0, but that may lead to a speed increase. I think I may change it to a float.

##### Share on other sites
Ok, I updated the pong.zip file. The paddle problem has been completely fixed. I am not sure if the ball getting stuck in the paddle problem has been fixed, because I haven''t noticed it in a while. The color of the background and the paddle can now now be changed in the Options menu (paddle color also changes the text color, because I didn''t want to have to use a bunch of IF statements to get the text readable with different color backgrounds). In the next version, I will work on a good looking menu that stays the same (i.e., its color does change with the pong table).

Also, I switched a lot of my variables to GLfloat to try and avoid truncation. I hope that was the problem on your computer, blueEbola. Hopefully it runs at a reasonable speed now.

Here''s the file:
Updated Pong

##### Share on other sites
Yay! It works great now. I can''t believe the paddle thing was such a simple problem.

The floats make things much smoother, but is the speed/paddle speed value not supposed to be there? It could be caused by using "%d" and a float variable with sprintf, vprintf etc, so just typecast it to an int if that''s the problem.

Also, I''ve found a way to cheat Just click on the title bar and hold the button down for a second when the ball''s about to hit the cpu paddle, it''ll jump past and you''ll score! You might want to fix that.

##### Share on other sites
A few things I noticed (and suggestions):

• In menu mode, if I change the window size in any way, the "marker" disappear and never comes back. It seem to work, though.
• Also in menu mode, it doesn''t seem to react on the first keystroke(s). A problem I usually have too; not sure what''s causing it. Probably ''cus they aren''t queued.
• If I press escape in menu mode, I end up in play mode. Should I come to the previous menu, and if it''s the main menu, quit the application?
• Perhaps what Sibbo2001 pointed out, but I can''t see the Speed nor Paddle Speed in the Game Options menu.
• Text color seems to work, but if I press enter on background color, the entire display turns white, and maybe hangs, as I can''t get out or see anything else. I can close though, without killing it.
• If I press ''p'' to pause, the ''game paused'' text appear next to the ball. If I then press escape, return to the main menu, and then start a new game, the ''game paused'' text still appear next to the ball while it runs around (looks kinda funny ).
Just a few things to fix. Lot of fun to play, now when the paddle thingy is done with

##### Share on other sites
Thanks for the replies.

Sibbo: Yeah, I was really mad at myself for making such a stupid mistake that ended up causing so much grief. When I changed some of the variables to floats, I forgot to change the text print out for the menu (it is using %2.0i... not sure if that is what causes it not to print, but it should be an easy fix). As for the "cheat," I think that has more to do with the window code than the game logic. At least I think that is it. Any suggestions on this problem?

CWizard: Thanks for the list. I also tried changing the window size, and the marker went away. I''ll look through my code for a reason to this, but I cannot think of why this would happen. Could you clarify the second comment? If I understand you correctly, when you first go into the menu your first couple of keystrokes aren''t recognized. I wasn''t able to reproduce it, so perhaps a little clarification would help.

The Escape button was designed that way. All it does is gameLoop = !gameLoop. So, if you are in the menu and hit ESC, you''ll go back into the game and vice versa. That is why I added the Exit option on the menu. Do you think I should change it to work the way you explained it?

The Background color button switches the color of the background, and it just so happens that white is the color after black. So, just hit enter again and you should see a red background. This will be fixed in the next version, which will have an unchanging menu (and little boxes next to the color selectors to show to current color).

Good observation on the Pause/New Game bug. "Game Paused" is written if my paused variable is true. The ''P'' button toggles the paused variable, and sets the ball''s speed variables to 0 after saving those variables in oldSpeed. This is not the best way to do a paused game, but it was easy to implement (you might also notice that ''Speed'' reads 0 in the menu if you pause the game, then go into the menu). This will be an extremely easy fix, because all I have to do is set ''paused'' to false in ResetGame().

I could fix those problems right now, but I am fairly busy today and I''d hate to have to upload another version for you guys to check out. Luckily, none of them are game stopping bugs (the only ones that really annoy me are the speed and length variables not showing up). Also, I''d like to see how this version functions on blueEbola''s machine, since he was a having a lot of trouble with speed.

Thanks again for the helpful comments. I''ll fix these problems next week, and hopefully have a better version by Friday (with a better menu and textures for the background and paddles). One question: I''ll add a little ''tick'' sound when the ball hits a paddle. Should I use FMOD for this (not sure if there is an easy function to play a sound) or just use PlaySound()?

##### Share on other sites
To sort out the 'cheat' here's what to do:

  ......static BOOL g_isProgramLooping;											// Window Creation Loop, For FullScreen/Windowed Toggle																		// Between Fullscreen / Windowed Modestatic BOOL g_createFullScreen;											// If TRUE, Then Create Fullscreen// Add the  line belowbool g_bWait = false;void TerminateApplication (GL_Window* window)							// Terminate The Application{......

In the NeHeGL.cpp file's WindowProc function:

  ......		case WM_TOGGLEFULLSCREEN:										// Toggle FullScreen Mode On/Off			g_createFullScreen = (g_createFullScreen == TRUE) ? FALSE : TRUE;			PostMessage (hWnd, WM_QUIT, 0, 0);		break;															// Break// Add the code below		case WM_WINDOWPOSCHANGING:			{				g_bWait = true;			}			break;......

  ......Keys*		g_keys;// User Defined Variablesfloat		angle;												// Used To Rotate The Trianglesint			rot1, rot2;											// Counter Variables// Add the line belowextern bool g_bWait;......

  ......void Update (DWORD milliseconds)								// Perform Motion Updates Here{	if (g_bWait)	{		g_bWait = false;		return;	}......

I'm pretty sure that should work.

For playing sound, I'd suggest using FMod, as PlaySound sometimes causes a one time drop in framerate the first time a sound is played (which may not be noticable for a small file) when it loads it from disk.
I think for Fmod you have to call FSOUND_Sample_Load to load a sound, and FSOUND_PlaySound to play it.
Also using FMod will allow it to be hardware accelerated (not that it should matter for just a sound effect).

EDIT: Fixed source tags and green text.

[edited by - sibbo2001 on June 29, 2002 3:45:23 PM]

##### Share on other sites
quote:
Original post by Erunama
Could you clarify the second comment? If I understand you correctly, when you first go into the menu your first couple of keystrokes aren''t recognized. I wasn''t able to reproduce it, so perhaps a little clarification would help.

Yeah, I think this is due to my heavily loaded computer (P3 500MHz / 128MB) under WinXP. It start thrashing/paging all the time, and I notice when I run your pong (or most of my games) that when I first hit a button, it needs to load something from the hd (probably key-logic stuff), which probably causes a delay in the execution, and when it comes alive the key is no longer pressed. So, nevermind this.

quote:
Original post by Erunama
The Escape button was designed that way. All it does is gameLoop = !gameLoop. So, if you are in the menu and hit ESC, you''ll go back into the game and vice versa. That is why I added the Exit option on the menu. Do you think I should change it to work the way you explained it?

No, no need to; it''s your game, it should have your touch . Although, I thought the it was pretty standard that way I explained (then, I don''t play many games).

About the background color, my mistake. I thought I pressed enter a few extra times, but nothing happened. Now I tried again, and it worked like you said. Probably my worn out keyboard .

##### Share on other sites
Erunama,

It works great! The speed is smooth, the ball didn''t stick to the paddle and no jumping. I got around 260 FPS. Keep up the good work

##### Share on other sites
Yes! Thanks for trying it again, blueEbola. I''m glad that fix worked, because I couldn''t think of any other solution.

Sibbo: Thanks for taking the time to write that code. I''ll be sure to try it out when I get some free coding time. I looked up those two FMOD functions you mentioned, and I will definitely be using FMOD for playing sounds. I didn''t realize how easy it is (I must have missed FSOUND_Sample_Load while I was browsing).

CWizard: Good to see some of your concerns were cleared up. I think having white come after black isn''t a great idea, so I will change the order. Also, I have noticed that the paddle colors don''t show up correctly. For instance, I cannot get a white background with black paddles and text. What should the alpha value be in the glClearColor calls?

As for the menu, I will change one thing: having the game go to the main menu if it is in the sound or options menu and ESC is pressed. I don''t want to have it Exit, though, because I want to avoid accidental exits. Most recent games work this way (such as Return to Castle Wolfenstein, while it is in-game). If I knew how to do a GUI, I might add a little "Are you sure you want to quit?" dialog, but alas...