# Thread: Allegro Pong Collision Problems

1. ## Allegro Pong Collision Problems

Hi

I've been learning some 'Allegro' (a game programming library) for c++. i decided to compile what i'd learned and to try and make a pong clone called 'bat and ball'. ive run into a problem that i have been un-able to fix. when i run this code everything works as it should but the colision on the bat to ball doesn't work. please help:

Code:
```#include <allegro.h>
#include <cstdlib>

int BallX = 100;
int BallY = 100;

int TempX = 100;
int TempY = 100;

int Dir = 1; //This will keep track of the circles direction
//1= up and left, 2 = down and left, 3 = up and right, 4 = down and right

int PlayerX = 300;
int PlayerY = 400;

int TempPlayerX = 300;
int TempPlayerY = 400;

void MovePlayer(){

TempPlayerX = PlayerX;
TempPlayerY = PlayerY;

if (key[KEY_LEFT] && PlayerX > 10) {
PlayerX = PlayerX - 5;
}
else if (key[KEY_RIGHT] && PlayerX < 570) {
PlayerX = PlayerX + 5;
}
acquire_screen();
rectfill( screen, TempPlayerX, TempPlayerY, (TempPlayerX + 50), (TempPlayerY + 20), makecol ( 0, 0, 0));
rectfill( screen, PlayerX, PlayerY, (PlayerX + 50), (PlayerY + 20), makecol ( 255, 255, 255));
release_screen();

}

void MoveBall(){

TempX = BallX;
TempY = BallY;

if (Dir == 1 && BallX != 10 && BallY != 20 && (BallX < PlayerX || BallX > PlayerX + 50)) {

BallX = BallX - 1;
BallY = BallY - 1;

} else if (Dir == 2 && BallX != 20 && BallY != 460) {

BallX = BallX - 1;
BallY = BallY + 1;

} else if (Dir == 3 && BallX != 620 && BallY != 20)  {

BallX = BallX + 1;
BallY = BallY - 1;

} else if (Dir == 4 && BallX != 620 && BallY != 460) {

BallX = BallX + 1;
BallY = BallY + 1;

} else if ((BallX > PlayerX || BallX < (PlayerX + 50)) && BallY == 395) {

BallY = BallY - 5;
Dir = rand() % 4 + 1;

}

else {
Dir = rand() % 4 + 1;
}

acquire_screen();
circlefill ( screen, TempX, TempY, 5, makecol( 0, 0, 0));
circlefill ( screen, BallX, BallY, 5, makecol( 255, 255, 255));
release_screen();

rest(10);

}

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

while( !key[KEY_ESC]){

MoveBall();
MovePlayer();

}

return 0;

}
END_OF_MAIN();```

2. Collision is best done by ruling out all the false possibilities first. What remains must be true.

To determine which side the object hit on you subtract the center of the two objects. If the x distance is greater than or equal to the stationary object's (the test object) width or bounding width then the hit was either on the left or right, else it was top or bottom.

3. k howz this?

Code:
```#include <allegro.h>
#include <cstdlib>

int BallX = 300;
int BallY = 300;

int TempX = 300;
int TempY = 300;

int Dir = 3; //This will keep track of the circles direction
//1= up and left, 2 = down and left, 3 = up and right, 4 = down and right

int PlayerX = 300;
int PlayerY = 400;

int TempPlayerX = 300;
int TempPlayerY = 400;

void MovePlayer(){

TempPlayerX = PlayerX;
TempPlayerY = PlayerY;

if (key[KEY_LEFT] && PlayerX > 10) {
PlayerX = PlayerX - 5;
}
else if (key[KEY_RIGHT] && PlayerX < 570) {
PlayerX = PlayerX + 5;
}
acquire_screen();
rectfill( screen, TempPlayerX, TempPlayerY, (TempPlayerX + 50), (TempPlayerY + 20), makecol ( 0, 0, 0));
rectfill( screen, PlayerX, PlayerY, (PlayerX + 50), (PlayerY + 20), makecol ( 255, 255, 255));
release_screen();

}

void MoveBall(){

TempX = BallX;
TempY = BallY;

if (Dir == 1 && BallX != 10 && BallY != 20) {

BallX = BallX - 1;
BallY = BallY - 1;

} else if (Dir == 2 && BallX != 20 && BallY != 460) {

BallX = BallX - 1;
BallY = BallY + 1;

} else if (Dir == 3 && BallX != 620 && BallY != 20)  {

BallX = BallX + 1;
BallY = BallY - 1;

} else if (Dir == 4 && BallX != 620 && BallY != 460) {

BallX = BallX + 1;
BallY = BallY + 1;

} else if ((BallX < PlayerX || BallX > (PlayerX + 50)) && BallY != 395) {

if (Dir == 1) {

BallX = BallX - 1;
BallY = BallY - 1;

} else if (Dir == 2) {

BallX = BallX - 1;
BallY = BallY + 1;

} else if (Dir == 3) {

BallX = BallX + 1;
BallY = BallY - 1;

} else if (Dir == 4) {

BallX = BallX + 1;
BallY = BallY + 1;

}

} else {
Dir = rand() % 4 + 1;
}

acquire_screen();
circlefill ( screen, TempX, TempY, 5, makecol( 0, 0, 0));
circlefill ( screen, BallX, BallY, 5, makecol( 255, 255, 255));
release_screen();

rest(10);

}

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

while( !key[KEY_ESC]){

MoveBall();
MovePlayer();

}

return 0;

}
END_OF_MAIN();```
now the ball isnt recognising any collision

4. Code:
```bool Sprite::Collide(float left,float top,float right,float bottom)
{
float SrcLeft   = m_vecPos.x + m_vecMin.x;
float SrcRight  = m_vecPos.x + m_vecMax.x;
float SrcTop    = m_vecPos.y + m_vecMin.y;
float SrcBottom = m_vecPos.y + m_vecMax.y;

if (SrcRight < left) return false;
if (SrcLeft > right) return false;
if (SrcBottom > top) return false;
if (SrcTop < bottom) return false;

return true;
}```
This code assumes that m_vecPos is a 3D vector and m_vecMin and m_vecMax are two 3D vectors describing the min and max values of the bounding volume for the Sprite.

5. Code:
`Dir = rand() &#37; 4 + 1;`
Is this the collision response? Two directions out of four will always make the ball move in an unwanted direction...

It might be simpler to represent Dir as the X and Y component of the ball's movement instead (see code below).

Then you'll need to detect collisions with the edges of the screen and reverse movement direction. If we are colliding with the sides, reverse X component. If colliding with the top, reverse Y component. If colliding with the bottom, do something special (e.g substract from player's "lives" and reset the ball to the centre).

Also check collision with the bat and reverse the ball's Y movement (make it go up). Below I only considered the top surface of the bat for collisions. You might also want to check collisions against other sides of the bat.

Code:
```#include <allegro.h>
#include <cstdlib>

int BallX = 300;
int BallY = 300;

int BallMoveX = -1;
int BallMoveY = -1;

int PlayerX = 300;
int PlayerY = 400;

void MovePlayer(){
//temporary local variables
int TempPlayerX = PlayerX;
int TempPlayerY = PlayerY;

if (key[KEY_LEFT] && PlayerX > 10) {
PlayerX = PlayerX - 5;
}
else if (key[KEY_RIGHT] && PlayerX < 570) {
PlayerX = PlayerX + 5;
}

acquire_screen();
rectfill( screen, TempPlayerX, TempPlayerY,
(TempPlayerX + 50), (TempPlayerY + 20), makecol ( 0, 0, 0));
rectfill( screen, PlayerX, PlayerY,
(PlayerX + 50), (PlayerY + 20), makecol ( 255, 255, 255));
release_screen();

}

void MoveBall(){
//These variables are only used temporarily in this function
int TempX = BallX;
int TempY = BallY;

//detect collisions with sides
if (BallX <= 5 || BallX >= SCREEN_W - 5) {
BallMoveX = -BallMoveX;
}
//detect collision with top
if (BallY <= 5) {
BallMoveY = 1;
}
//detect collision with pad
else if ( BallY + 5 == PlayerY && BallX >= PlayerX && BallX <= PlayerX + 50) {
BallMoveY = -1;
//determine horizontal direction (which half of pad was hit?)
BallMoveX = (BallX < PlayerX + 25 ? -1 : 1);
}
//detect collision with bottom
else if (BallY >= SCREEN_H - 5) {
//reset ball
BallX = BallY = 300;
BallMoveX = BallMoveY = -1;
}
//move ball
BallX += BallMoveX;
BallY += BallMoveY;

acquire_screen();
circlefill ( screen, TempX, TempY, 5, makecol( 0, 0, 0));
circlefill ( screen, BallX, BallY, 5, makecol( 255, 255, 255));
release_screen();

rest(10);

}

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

while( !key[KEY_ESC]){

MoveBall();
MovePlayer();

}

return 0;

}
END_OF_MAIN() //<-- no semicolon here```
Other than that the graphics output is rather poor. It wouldn't flicker so much, if you used double buffering (and separated drawing from logic).

You should also check out this to improve the general quality of your code: Magic numbers and Global variables (morale: try to avoid them).

Popular pages Recent additions