Problems with my pong clone

Started by
9 comments, last by Terradigits 17 years, 10 months ago
Hi, I recently got into gamedev again, so I started working on a pong clone. I have a problem with ball movement, however. For some reason, I cant get the ball to move in random directions. It sorta does at the moment, but its not truly random, and its buggy. You can see my code below:

#include <allegro.h>
#include <iostream>
#include <stdlib.h>
#include <cstdlib>
#include <time.h>

void init();
long speed_counter = 0;
void speed_increment();
void speed_increment()
{
     speed_counter++;
}
END_OF_FUNCTION(speed_increment);
int main()
{
     init();
     srand((unsigned)time(0)); 
     //create bitmaps
     BITMAP *paddle1=NULL;
     BITMAP *paddle2=NULL;
     BITMAP *ball=NULL;
     BITMAP *buffer=NULL;
     paddle1 = load_bitmap("paddle1.bmp",NULL);
     paddle2 = load_bitmap("paddle2.bmp",NULL);
     ball = load_bitmap("ball2.bmp",NULL);
     buffer = create_bitmap(640,480);
     //variables
     int ballstart = 0;
     int yrand = (rand()%2)+1; 
     int ballposx = 200, ballposy = 200;
     int paddle1x = 0, paddle1y = 0;
     int paddle2x = 632, paddle2y = 0;
     //collision variables
     //paddle 1 variables
     int paddle1bbleft = paddle1x;
     int paddle1bbtop = paddle1y;
     int paddle1bbright = (paddle1bbleft + paddle1->w);
     int paddle1bbbottom = (paddle1bbtop + paddle1->h);
     //paddle 2 variables
     int paddle2bbleft = paddle2x;
     int paddle2bbtop = paddle2y;
     int paddle2bbright = (paddle2bbleft + paddle1->w);
     int paddle2bbbottom = (paddle2bbtop + paddle1->h);
     //ball variables
     int ballbbleft = ballposx;
     int ballbbtop = ballposy;
     int ballbbright = (ballbbleft + ball->w);
     int ballbbbottom = (ballbbtop + ball->h);
     //frame rate thing
     install_int_ex(speed_increment,BPS_TO_TIMER(60));
     //ball minus thing
     int ballminus = 1;
     //game loop
     while (!key[KEY_ESC])
     {
           while (speed_counter >= 0)
           {
                 //controls for player 1
                 if (key[KEY_W])
                 {
                                paddle1y = paddle1y - 5;
                 }
                 if (key[KEY_S])
                 {
                                   paddle1y = paddle1y + 5;
                 }
                 //controls for player 2
                 if (key[KEY_UP])
                 {
                                 paddle2y = paddle2y - 5;
                 }
                 if (key[KEY_DOWN])
                 {
                                   paddle2y = paddle2y + 5;
                 }
                 //paddle1
                 paddle1bbleft = paddle1x;
                 paddle1bbtop = paddle1y;
                 paddle1bbright = (paddle1bbleft + paddle1->w);
                 paddle1bbbottom = (paddle1bbtop + paddle1->h);
                 //paddle2
                 paddle2bbleft = paddle2x;
                 paddle2bbtop = paddle2y;
                 paddle2bbright = (paddle2bbleft + paddle1->w);
                 paddle2bbbottom = (paddle2bbtop + paddle1->h);
                 //ball
                 ballbbleft = ballposx;
                 ballbbtop = ballposy;
                 ballbbright = (ballbbleft + ball->w);
                 ballbbbottom = (ballbbtop + ball->h);
                 //collisions for paddle 1
                 if ((paddle1bbleft >= ballbbleft) && (paddle1bbtop >= ballbbtop) && (paddle1bbleft <= ballbbright) && (paddle1bbtop <= ballbbbottom))
                 {
                         ballminus = 1;
                         ballposy = ballposy + yrand;
                 }
                 else if ((paddle1bbright <= ballbbright) && (paddle1bbright >= ballbbleft) && (paddle1bbtop >= ballbbtop) && (paddle1bbtop <= ballbbbottom))
                          {
                                           ballminus = 1;
                                           ballposy = ballposy + yrand;
                          }
                 else if ((paddle1bbleft >= ballbbleft) && (paddle1bbleft <= ballbbright) && (paddle1bbbottom <= ballbbbottom) && (paddle1bbbottom >= ballbbtop))
                 {
                      ballminus = 1;
                      ballposy = ballposy + yrand;
                 }
                 else if ((paddle1bbright <= ballbbright) && (paddle1bbright >= ballbbleft) && (paddle1bbbottom <= ballbbbottom) && (paddle1bbbottom >= ballbbtop))
                 {
                      ballminus = 1;
                      ballposy = ballposy + yrand;
                 }
                 else if ((ballbbleft >= paddle1bbleft) && (ballbbtop >= paddle1bbtop) && (ballbbleft <= paddle1bbright) && (ballbbtop <= paddle1bbbottom))
                 {
                      ballminus = 1;
                      ballposy = ballposy + yrand;
                 }
                 else if ((ballbbright <= paddle1bbright) && (ballbbright >= paddle1bbleft) && (ballbbtop >= paddle1bbtop) && (ballbbtop <= paddle1bbbottom))
                 {
                      ballminus = 1;
                      ballposy = ballposy + yrand;
                 }
                 else if ((ballbbright <= paddle1bbright) && (ballbbright >= paddle1bbleft) && (ballbbbottom <= paddle1bbbottom) && (ballbbbottom >= paddle1bbtop))
                 {
                      ballminus = 1;
                      ballposy = ballposy + yrand;
                 }
                 else if ((ballbbright <= paddle1bbright) && (ballbbright >= paddle1bbleft) && (ballbbbottom <= paddle1bbbottom) && (ballbbbottom >= paddle1bbtop))
                 {
                      ballminus = 1;
                      ballposy = ballposy + yrand;
                 }
                 //collisions for paddle 2
                 else if ((paddle2bbleft >= ballbbleft) && (paddle2bbtop >= ballbbtop) && (paddle2bbleft <= ballbbright) && (paddle2bbtop <= ballbbbottom))
                 {
                         ballminus = 0;
                         ballposy = ballposy - yrand;
                 }
                 else if ((paddle2bbright <= ballbbright) && (paddle2bbright >= ballbbleft) && (paddle2bbtop >= ballbbtop) && (paddle2bbtop <= ballbbbottom))
                          {
                                           ballminus = 0;
                                           ballposy = ballposy - yrand;
                          }
                 else if ((paddle2bbleft >= ballbbleft) && (paddle2bbleft <= ballbbright) && (paddle2bbbottom <= ballbbbottom) && (paddle2bbbottom >= ballbbtop))
                 {
                      ballminus = 0;
                      ballposy = ballposy - yrand;
                 }
                 else if ((paddle2bbright <= ballbbright) && (paddle2bbright >= ballbbleft) && (paddle2bbbottom <= ballbbbottom) && (paddle2bbbottom >= ballbbtop))
                 {
                      ballminus = 0;
                      ballposy = ballposy - yrand;
                 }
                 else if ((ballbbleft >= paddle2bbleft) && (ballbbtop >= paddle2bbtop) && (ballbbleft <= paddle2bbright) && (ballbbtop <= paddle2bbbottom))
                 {
                      ballminus = 0;
                      ballposy = ballposy - yrand;
                 }
                 else if ((ballbbright <= paddle2bbright) && (ballbbright >= paddle2bbleft) && (ballbbtop >= paddle2bbtop) && (ballbbtop <= paddle2bbbottom))
                 {
                      ballminus = 0;
                      ballposy = ballposy - yrand;
                 }
                 else if ((ballbbright <= paddle2bbright) && (ballbbright >= paddle2bbleft) && (ballbbbottom <= paddle2bbbottom) && (ballbbbottom >= paddle2bbtop))
                 {
                      ballminus = 0;
                      ballposy = ballposy - yrand;
                 }
                 else if ((ballbbright <= paddle2bbright) && (ballbbright >= paddle2bbleft) && (ballbbbottom <= paddle2bbbottom) && (ballbbbottom >= paddle2bbtop))
                 {
                      ballminus = 0;
                      ballposy = ballposy - yrand;
                 }
                 //ball movement code
                 if (ballminus == 0)
                 {
                               ballposx = ballposx - 3;
                               ballposy = ballposy + yrand;
                 }
                 else
                 {
                     ballposx = ballposx + 3;
                 }
                 if (ballposy <= 0)
                 {
                              ballposy = ballposy +3;
                 }
                 if (ballposy >= 472)
                 {
                              ballposy = ballposy -3;
                 } 
                 speed_counter--;
           }
           draw_sprite(buffer,paddle1,paddle1x,paddle1y);
           draw_sprite(buffer,paddle2,paddle2x,paddle2y);
           draw_sprite(buffer,ball,ballposx,ballposy);
           blit(buffer,screen,0,0,0,0,640,480);
           clear(buffer);
     }
     return 0;
}
END_OF_MAIN()


I am using allegro with devc++. the code is kinda messy, and I have around 3 different implementations for random movement along the y axis in the code(one for when it hits a paddle, one for when it hits the outside of the level, etc.). I was trying out different things to see which worked. anyways, if anyone could help me that would be great. I would prefer if, instead of telling me exactly what to do, you could just give me a hint or lead me in the right direction. Thanks.
Advertisement
Quote:Original post by Terradigits
the code is kinda messy,


Yeah, it really is. I'm sure that someone will make quite a bit of effort to help you out anyway, but you really should at least partition it into a few different functions to make it a little easier. Finding bugs like yours in that kind of code aren't all that easy to find.

If your actually planning on expanding this clone at all, I really do suggest you tidy up the code. You'll probably also find your bug will magically dissappear after doing this.
"Leave it to the computer programmers to shorten the "Year 2000 Millennium Bug" to "Y2K." Isn't that what caused this problem in the first place?"
This doesn't really answer your question, but why would you want the ball to move in a random direction? Then again, it's your game and you can do what ever you want ;) In any case, it may appear as though you're not getting a real 'random' yrand value because you set the value once at the beginning, but then don't generate a new random value after it is used. Perhaps you might consider putting your calculation - yrand = (rand()%2)+1 - after each time it is used. As far as the 'buggy' part. If you post an example of an error or unwanted behavior, I'd be happy to offer a suggestion.

Good luck.

-> By the way, it's ok to 'peek' at someone elses implementation just for ideas. I'm sure if you look you can find some.
by random direction, I mean that when it hits the paddle, I want it to bounce off in a random direction, not just, say, go strait when it hits the paddle. As for buggy, i'll give you one example. When the ball reaches the edge of the screen, instead of bouncing up and away from it like it should, it just goes along the bottom of the screen in a strait line, and continues doing that. I'll do what you said and see if its fixes anything. For now, if anyone else can look at my code and help me that would be appreciated.

EDIT: I did what you said, but it would'nt compile. I modified it a bit, and now there is no movement on the y-axis at all. basically, what i did was my normal computation ex. ballposy = ballposy + yrand, and then I did yrand = (rand()%2)+1 right after it.

[Edited by - Terradigits on June 8, 2006 6:08:43 PM]
Hmm. Instead of a random direction off the paddle, you might want to get a more realistic ball movement such that if the ball is approaching from the left, it would be deflected off the paddle continuing in the same path with the x and y velocity reversed. Modifying your code to do that might be a little tricky the way it is organized.

Regarding the odd ball behavior you mentioned, there's two ways you can handle this. You can either have the ball bounce off the walls of the playing area, or do what's called 'clipping' so that as the ball moves off the screen at the top, it re-enters the playing field on the bottom. The latter option is more complicated but worth the effort of learning. Again, there are lots of examples to follow for this.

Keep at it.

EDIT: I felt bad about not offering any real code suggestions so here's a little example I found online by Googling 'pong clone c++'. This shows what I meant about reversing the velocity of the ball on impact
    // if the ball touch the wall, it will change the direction    if (Ball.y < 0) dirY = 5;    if ((Ball.y + 15) > HEIGHT) dirY = -5;    // if the ball touch the player paddle    if ((Ball.x >= player.left) && (Ball.x <= player.right)) {        if ((Ball.y >= player.top) && (Ball.y <= player.bottom)) {            dirX = BALLSPEED;        }    }    // if the ball touch the computer paddle    if ((Ball.x >= computer.left-15) && (Ball.x <= computer.right-15)) {        if ((Ball.y >= computer.top) && (Ball.y <= computer.bottom)) {            dirX = -BALLSPEED;        }    }


Hope that helps.

[Edited by - vinb on June 8, 2006 8:50:15 PM]
I tried implementing that, but couldn't really get it to work. Here is my current code:

init.cpp
#include <allegro.h>void init();void init(){     allegro_init();     install_keyboard();     install_timer();     set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);}


main.cpp
#include <allegro.h>#include <iostream>#include <stdlib.h>#include <cstdlib>#include <time.h>void init();long speed_counter = 0;void speed_increment();void collision();void positionupdate();void speed_increment(){     speed_counter++;}END_OF_FUNCTION(speed_increment);int main(){     //allegro init stuff//     init();     //srand//     srand((unsigned)time(0));      //create bitmaps//     BITMAP *paddle1=NULL;     BITMAP *paddle2=NULL;     BITMAP *ball=NULL;     BITMAP *buffer=NULL;     paddle1 = load_bitmap("paddle1.bmp",NULL);     paddle2 = load_bitmap("paddle2.bmp",NULL);     ball = load_bitmap("ball2.bmp",NULL);     buffer = create_bitmap(640,480);     //variables//     int paddle1x = 0, paddle1y = 0;     int paddle2x = 632, paddle2y = 0;     int ballstart = 0;     int yrand = (rand()%2)+1;     int ballposx = 200, ballposy = 200;     //frame rate thing//     install_int_ex(speed_increment,BPS_TO_TIMER(60));     //ball minus thing//     int ballminus = 1;     //game loop//     while (!key[KEY_ESC])     {           while (speed_counter >= 0)           {                 //controls for player 1//                 if (key[KEY_W])                 {                                paddle1y = paddle1y - 5;                 }                 if (key[KEY_S])                 {                                   paddle1y = paddle1y + 5;                 }                 //controls for player 2//                 if (key[KEY_UP])                 {                                 paddle2y = paddle2y - 5;                 }                 if (key[KEY_DOWN])                 {                                   paddle2y = paddle2y + 5;                 }                 //do collisions//                 //paddle 1 variables//                 int paddle1bbleft = paddle1x;                 int paddle1bbtop = paddle1y;                 int paddle1bbright = (paddle1bbleft + paddle1->w);                 int paddle1bbbottom = (paddle1bbtop + paddle1->h);                 //paddle 2 variables//                 int paddle2bbleft = paddle2x;                 int paddle2bbtop = paddle2y;                 int paddle2bbright = (paddle2bbleft + paddle1->w);                 int paddle2bbbottom = (paddle2bbtop + paddle1->h);                 //ball variables//                 int ballbbleft = ballposx;                 int ballbbtop = ballposy;                 int ballbbright = (ballbbleft + ball->w);                 int ballbbbottom = (ballbbtop + ball->h);                 //collisions for paddle 1//                 if ((paddle1bbleft >= ballbbleft) && (paddle1bbtop >= ballbbtop) && (paddle1bbleft <= ballbbright) && (paddle1bbtop <= ballbbbottom))                 {                      ballminus = 1;                 }                 else if ((paddle1bbright <= ballbbright) && (paddle1bbright >= ballbbleft) && (paddle1bbtop >= ballbbtop) && (paddle1bbtop <= ballbbbottom))                 {                      ballminus = 1;                 }                 else if ((paddle1bbleft >= ballbbleft) && (paddle1bbleft <= ballbbright) && (paddle1bbbottom <= ballbbbottom) && (paddle1bbbottom >= ballbbtop))                 {                      ballminus = 1;                 }                 else if ((paddle1bbright <= ballbbright) && (paddle1bbright >= ballbbleft) && (paddle1bbbottom <= ballbbbottom) && (paddle1bbbottom >= ballbbtop))                 {                      ballminus = 1;                 }                 else if ((ballbbleft >= paddle1bbleft) && (ballbbtop >= paddle1bbtop) && (ballbbleft <= paddle1bbright) && (ballbbtop <= paddle1bbbottom))                 {                      ballminus = 1;                 }                 else if ((ballbbright <= paddle1bbright) && (ballbbright >= paddle1bbleft) && (ballbbtop >= paddle1bbtop) && (ballbbtop <= paddle1bbbottom))                 {                      ballminus = 1;                 }                 else if ((ballbbright <= paddle1bbright) && (ballbbright >= paddle1bbleft) && (ballbbbottom <= paddle1bbbottom) && (ballbbbottom >= paddle1bbtop))                 {                      ballminus = 1;                 }                 else if ((ballbbright <= paddle1bbright) && (ballbbright >= paddle1bbleft) && (ballbbbottom <= paddle1bbbottom) && (ballbbbottom >= paddle1bbtop))                 {                      ballminus = 1;                 }                 //collisions for paddle 2//                 else if ((paddle2bbleft >= ballbbleft) && (paddle2bbtop >= ballbbtop) && (paddle2bbleft <= ballbbright) && (paddle2bbtop <= ballbbbottom))                 {                         ballminus = 0;                 }                 else if ((paddle2bbright <= ballbbright) && (paddle2bbright >= ballbbleft) && (paddle2bbtop >= ballbbtop) && (paddle2bbtop <= ballbbbottom))                 {                          ballminus = 0;                 }                 else if ((paddle2bbleft >= ballbbleft) && (paddle2bbleft <= ballbbright) && (paddle2bbbottom <= ballbbbottom) && (paddle2bbbottom >= ballbbtop))                 {                      ballminus = 0;                 }                 else if ((paddle2bbright <= ballbbright) && (paddle2bbright >= ballbbleft) && (paddle2bbbottom <= ballbbbottom) && (paddle2bbbottom >= ballbbtop))                 {                      ballminus = 0;                 }                 else if ((ballbbleft >= paddle2bbleft) && (ballbbtop >= paddle2bbtop) && (ballbbleft <= paddle2bbright) && (ballbbtop <= paddle2bbbottom))                 {                      ballminus = 0;                 }                 else if ((ballbbright <= paddle2bbright) && (ballbbright >= paddle2bbleft) && (ballbbtop >= paddle2bbtop) && (ballbbtop <= paddle2bbbottom))                 {                      ballminus = 0;                 }                 else if ((ballbbright <= paddle2bbright) && (ballbbright >= paddle2bbleft) && (ballbbbottom <= paddle2bbbottom) && (ballbbbottom >= paddle2bbtop))                 {                      ballminus = 0;                 }                 else if ((ballbbright <= paddle2bbright) && (ballbbright >= paddle2bbleft) && (ballbbbottom <= paddle2bbbottom) && (ballbbbottom >= paddle2bbtop))                 {                      ballminus = 0;                 }                 //update the position of stuff//                 //paddle1                 paddle1bbleft = paddle1x;                 paddle1bbtop = paddle1y;                 paddle1bbright = (paddle1bbleft + paddle1->w);                 paddle1bbbottom = (paddle1bbtop + paddle1->h);                 //paddle2                 paddle2bbleft = paddle2x;                 paddle2bbtop = paddle2y;                 paddle2bbright = (paddle2bbleft + paddle1->w);                 paddle2bbbottom = (paddle2bbtop + paddle1->h);                 //ball                 ballbbleft = ballposx;                 ballbbtop = ballposy;                 ballbbright = (ballbbleft + ball->w);                 ballbbbottom = (ballbbtop + ball->h);                                  //ball movement code                 if (ballminus == 0)                 {                               ballposx = ballposx - 3;                               ballposy = ballposy - 3;                 }                 else                 {                     ballposx = ballposx + 3;                     ballposy = ballposy - 3;                 }                 if (ballposy < 0)                 {                              ballposy = 5;                 }                 if (ballposy >= 472)                 {                            ballposy = -5;                 }                  //speed counter//                 speed_counter--;           }           //do double buffering, then draw the buffer to the screen.           draw_sprite(buffer,paddle1,paddle1x,paddle1y);           draw_sprite(buffer,paddle2,paddle2x,paddle2y);           draw_sprite(buffer,ball,ballposx,ballposy);           blit(buffer,screen,0,0,0,0,640,480);           //clear buffer           clear(buffer);     }     return 0;}END_OF_MAIN()


I also have an EXE you can look at. You can download it here. if anybody else has any comments they are welcome.
I am also doing a pong clone.. right now I am doing what you are.. having the ball bounce off the paddle in a random way but not off the wall. Off the wall it just bounces in the opposite direction. Eventually what I will do, and you should to. is segment the paddle into separate bounding boxes that change angle. So if you were to hit the ball in the middle of the paddle it would just change the direction of the ball but not the angle it was traveling while the left or right side would increase angle accordingly.

I think its a good step to get it working just with a random bounce ONLY on the paddle though. What I did was something like this. (In pseudo code)

If ball collides with paddle
{
randombounce();
}

void randombounce()
{
randomint = (rand() % 2);
move.x = randomint;
}
http://lempface.blogspot.com/Read about the RogueLike I'm Developing at my blog!
Thats kinda what I'm doing. My progblem is though, according to the way i've written my code, everything SHOULD work fine, but its not, and thats what I'm trying to figure out. and your idea of segmenting the paddle into different bounding boxes was interesting, too.

could the problem be that I am only having y be random, and not x too?
Can anybody help? this should be a pretty simple problem to fix.
good luck with the pong..
I just finished my pong with no random bounce, similar to the previous post with pattle having 3 sections. I can post my code if you like it wont help with the random or allegro but may give you different idea.

this is where i got most of my help from
http://www.aaroncox.net/tutorials/arcade/index.html

This topic is closed to new replies.

Advertisement