Public Group

# Having problems detecting hits in my breakout game

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

## Recommended Posts

The star(ball) hits the blocks, but it just goes through despite me coding collision detection, something is not right. Here is the block class

class Block
{
public:

//Variables for the block class
int x, y;
int life;
int width, height;
BITMAP *sprite;

//constructor
Block()
{
x = 0;
y = 0;
life = 0;
sprite = NULL;
}

//Initialization function
void initialize(int px, int py, int plife, BITMAP *source)
{
//Sets all the data for the blocks according to the player
x = px;
y = py;
life = plife;
sprite = source;
}

//Sets the dimensions of the blocks
void setdimensions()
{
width = sprite->w;
height = sprite->h;
}

//Detects if a collision detection occured or not
int inside (int x, int y, int left, int top, int right, int bottom)
{
if(x > left && y > top && x < right && y < bottom)
return 1;
else
return 0;
}

//Checks to see if the star collided with the blocks
int collided(Star &star, int border = 0)
{
int width1 = star.x + star.width;
int height1 = star.y + star.height;

//see if the corners of the star hit the block
if(inside(star.x, star.y, x, y, width, height))
{
return 1;
}
if(inside(width1, star.y, x, y, width, height))
{
return 1;
}
if(inside(star.x, height1, x, y, width, height))
{
return 1;
}
if(inside(width1, height1, x, y, width, height))
{
return 1;
}

//If no collision detected
return 0;
}

};


It has a life variable, which determines if it should be drawn again or not. This is the collision detection function:

int checkBlockCollision(Star &star, Block block[][8])
{
//Go through each block and see if the star hit any of them
for(int y = 0; y < 3; y++)
{
for(int x = 0; x < 8; x++)
{
if(block[y][x].collided(star) == 1)
{
//If a collision occurred, than destroy the block
block[y][x].life = 0;

//And move the star away from the block
star.y = block[y][x].y + block[y][x].width + 1;
star.diry = rand() % 2 + 4;

return 0;
}
else
return 1;
}
}
}


And here's the main game loop, where I check for detection. It only works on the top left most block, and none of the others

//Game loop
while(!key[KEY_ESC])
{
//Blit the background onto to the buffer
blit(background, buffer, 0, 0, 0, 0, background->w, background->h);

//Draw the star and the paddles
starball.rotate(buffer);

//draw the blocks
for(int y = 0; y < 3; y++)
{
for(int x = 0; x < 8; x++)
{
if(blocks[y][x].life != 0) //is the block still there?
{
draw_sprite(buffer, blocks[y][x].sprite, blocks[y][x].x, blocks[y][x].y);
}
}
}

//update an move the paddles and the stars

//Update the blocks
checkBlockCollision(starball, blocks);

//Get input to move the paddles
if(key[KEY_LEFT])
if(key[KEY_RIGHT])

remaining = blocksRemaining(blocks);
textprintf_ex(buffer, font, 10, SCREEN_H-10, BLUE, -1, "Blocks left: %d", remaining);

//Lock the screen
acquire_screen();

//Blit the updated buffer to screen
blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

//Unlock screen
release_screen();

rest(10);
}

allegro_exit();

return 0;

}


Ive been trying to fix this, but I just cant find out why it isn't working. Im using allegro 4.2 and c++

##### Share on other sites

You need test the star not as point, but like line it's moving object if you test that's how you did it, it will jump from place to place and skip collisions.

##### Share on other sites

Collision detection can be a tricky thing. As skmskm as pointed out, you can miss collision checks on moving objects. Imagine when your star moves with high velocity, one frame it's in front of a box and the next frame it's behind the box, you're collision test won't detect that at the moment. That being said, I'm not sure if that's the case right now.

If your star has a round collision shape, you could implement continuous collision detection by measuring the distance between box edges and the trajectory of the star.

##### Share on other sites

Well heres my star class

class Star
{
public:

//Individual variables
int x, y;
int width, height;
BITMAP *sprite;
int dirx, diry;
double angle;

//Constructor
Star()
{
x = 0;
y = 0;
width = 0;
height = 0;
sprite = NULL;
dirx = 0;
diry = 0;
angle = 0;
}

//Initialization function
void initialize(int px, int py, BITMAP *source)
{
x = px;
y = py;
sprite = source;
dirx = 1;
diry = 2;

if(source == NULL)
{
allegro_message("Failed to load image in star class");
return;
}
}

//Set dimensions
void setdimensions()
{
width = sprite->w;
height = sprite->h;
}

//Set the speed of the star
void changespeed(int x, int y)
{
dirx = x;
diry = y;
}

//rotates the star in the game
void rotate(BITMAP *dest)
{
//rotate star in 256 angles
if(angle > 256)
{
angle = 0;
}
else
{
angle += 1;
rotate_sprite(dest, sprite, x, y, itofix(angle));
}
}

};



Hmm maybe I ought to make a function that continuously checks collision against the ball for every block... Im gonna think about it

I also use this function to move the star and detect hits with my paddle:

void moveStar(Star &star, Paddle &paddle)
{
//update the star's x position
star.x += star.dirx;

//If star hits the left side of the screen
if(star.x < 0)
{
star.x = 1;
star.dirx = rand() % 2 + 4;
}

//If star hits the right side of the screen
if(star.x > SCREEN_W - star.width - 1)
{
star.x = SCREEN_W - star.width - 1;
star.dirx = rand() % 2 - 4;
}

//Update the star's y position
star.y += star.diry;

//if star hits the top of the screen
if(star.y < 0)
{
star.y = 1;
star.diry = rand() % 2 + 4;
}

//if star hits bottom of the screen
if(star.y > SCREEN_H - star.width - 1)
{
star.y = SCREEN_H - star.width - 2;
star.diry = rand() % 2 - 4;
}

//Check if star hits the paddle
{
star.y = paddle.y - star.height - 1;
star.diry = rand() % 2 - 4;
}
}


Edited by ISDCaptain01

##### Share on other sites

I didn't recognize anything in the code that removes the object and stops the motion loop (although the latter isn't needed if you remove). Could this be a potential reason, or did I overlook something? Did you remember to dispose the object?

Edited by Malabyte

##### Share on other sites

Your collision code seems wrong, is hard to read, and is inefficient.  There's something wrong in there, I'd bet it.

Let me suggest a function, and explain the issues in comments:

bool Block::HasCollided(Star& star)
{
// We simple want to check these statements

//  if the right side of the star is left of the left side of the block, no collision
if (star.x + star.width < x) {
return false;
}
//  if the left side of the star is right of the right side of the block, no collision
if (star.x > x + width) {
return false;
}

//  if the top side of the star is below of the bottom side of the block, no collision
if (star.y > y + height) {
return false;
}
//  if the bottom side of the star is above of the top side of the block, no collision
if (star.y + star.height < y) {
return false;
}

// otherwise, some part of star has collided with the block
return true;
}


Obviously, all those checks could be added in one if () using || operators, but I wanted to spell it out.

Hope that clears things up.

EDIT:  I see you have a correct collision check if the ball hits the paddle (although doing the inverse of my suggest, both valid);  Why didn't you use that when checking for block collision?  It would've solved your issues, instead of making 4 calls to the inside() function, which seems incorrect anyway.

Edited by BeerNutts

1. 1
2. 2
3. 3
4. 4
5. 5
frob
11

• 16
• 13
• 20
• 12
• 19
• ### Forum Statistics

• Total Topics
632172
• Total Posts
3004569

×

## Important Information

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!