Jump to content
  • Advertisement
Sign in to follow this  
ISDCaptain01

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.

If you intended to correct an error in the post then please contact us.

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);
		paddle1.drawpaddle(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
		moveStar(starball, paddle1);

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

		//Get input to move the paddles
		if(key[KEY_LEFT])
			paddle1.movePaddleLeft();
		if(key[KEY_RIGHT])
			paddle1.movePaddleRight();

		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 this post


Link to post
Share on other sites
Advertisement

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 this post


Link to post
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 this post


Link to post
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
	if(star.x > paddle.x && star.x < paddle.x + paddle.height &&
	   star.y > paddle.y && star.y < paddle.y + paddle.height)
	{
		star.y = paddle.y - star.height - 1;
        star.diry = rand() % 2 - 4;
	}	
}

Edited by ISDCaptain01

Share this post


Link to post
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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

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!