How to do simple brick collision...

Started by
18 comments, last by Codejoy 20 years, 12 months ago
This is really wierd. I have this game with stationary bricks..and a ball moving around the screen. Sorta like breakout i guess, and I just want to see how the ball collides with the brick and then reflect its velocity apprpriately. I have a function that is a for loop with a check to see if there was a collision with the ball and a brick. If so it then goes into a if else statement to see what kind of collision based on: The xv and yv of the ball...i.e. what direction was it previously traveling when it hit the brick, was it up, up-right (xv > 0 yv<0), down right (xv>0, yv>0) down left (xv < 0, yv>0) up left (xv<0 yv <0 ). Say it decides it was down right, well then the ball can only collide with the brick on the top or on the left side of the brick. This means that if it hits the left side of the brick, then the ball.x+ball.width >= brick.x correct? and if it hit the top of the brick then the ball.y+ball.height > brick.y ? Is this close? because its what I have and its doing funky stuff. I didnt think such a collision test would be so difficult, but im just smoking crack i guess..so any help would be great.. also the above "Algorithms" for collision detection are very simple...after it determines if it hit say the left side of the brick after traveling down right, it just makes the ball then reflect about the y axis, and it travels down left. So I reverse the xv. Since I cannot get this working properly I have stalled my efforts to put in more advance collision detection because a) I cannot get even the simple stuff working and: B) i am not sure how to do more advance collision detection given just ball x,y,width,height and xv, yv and brick x,y width and height. Any suggestions here as well? perhaps the sharper angle it hits at the sharper angle it returns at. I am sure there are some equataions to get an angle given a velocity and a coordinate (vector some how?) but not sure what the are since any real math I have done has been years ago. Thanks, Shane
Advertisement
check out the articles & resources section here on GameDev and read the articles on collision detection. Click here for the link.
Evillive2
Thanks for the link, ill check it out...but it might be over kill since i have a collision routine that works, just cannot get it to work *right* and well also, the code on paper looks right but its not doing what its supposed to. I can put a row of my bricks and a column of my bricks. the following code bounces the ball just right on the top or bottom of the rows of bricks, but when it hits the sides of a brick (like runs into a column) it goes through the "wall" of bricks! and bounces around within the sprite... its very perplexing. Here is the code:

  for(int i=0; i<g_currNumBricks; i++) //check all bricks on field{	if(Collision(&theBall, &picBrick[i])==TRUE) //we collided with a bricks rectangle	{		if((Ballxv > 0) && (Ballyv > 0)) //ball traveling down right		{					 //Check the left side.  Check bottom side.			if((theBall.y+theBall.height)> picBrick[i].y)			{				//we in the clear				Ballyv=-Ballyv;			}			else if( (theBall.x+theBall.width) > picBrick[i].x)						{				Ballxv=-Ballxv;			}		}		else if((Ballxv < 0) && (Ballyv < 0)) //travling up left		{				//Check the right side, top			if( (theBall.y) < (picBrick[i].y+picBrick[i].height) ) 			{				//we in the clear				Ballyv=-Ballyv;			}			else if( theBall.x < (picBrick[i].x+picBrick[i].width) )						{				Ballxv=-Ballxv;			}			}		else if((Ballxv > 0) && (Ballyv < 0)) //up right		{				//top check right.			 //Check the left side.  Check bottom side.			if(theBall.y < (picBrick[i].y+picBrick[i].height))			{				//we in the clear				Ballyv=-Ballyv;			}			else if( (theBall.x+theBall.width) > picBrick[i].x)						{				Ballxv=-Ballxv;			}		}		else if((Ballxv < 0) && (Ballyv > 0) ) //traveling down left		{	//Right side, bottom.		  	//Check the right side, top			if( (theBall.y+theBall.height) > picBrick[i].y ) 			{				//we in the clear				Ballyv=-Ballyv;			}			else if( theBall.x < (picBrick[i].x+picBrick[i].width) )						{				Ballxv=-Ballxv;			}			}	}							}  
yes, a surprisingly irritanting problem witch almost always arises when coding a breakout like game.. yet the solution is rather simple.

first you should realise you dont want perfect collisiondetection, if youre going for a breakoutlike reflection style: balls in a breakout game ALWAYS deflect around the x or y axis: even if a ball hits the cornr of a brick, still the speed is flipped around one axis, instead of a 'proper' collision around a normal.
if this is not your intention, you should use standard collision routines between lines, points and balls. but what i can make from your post, you dont want to do that.

the solution to breakout like collision is much easier, yet hard to come up with. simply put, you should update the x position and y position in seperate loops, note, not nested loops, but coming after eachother.
so first move along one axis, check for collision, if so flip around that axis, and when youre done for all balls, start doing this for the other axis.
i know, this is not a perfect collision detection, but youll never see any strange things, and its dead easy to code

//edit: oh btw, if your bricks are aligned in a grid, you should not iterate though them all, but put them in an array instead and do collision detection with the array: MUCH faster.

[edited by - eelco on April 21, 2003 4:43:26 PM]
Thanks, ill look into this, sorta confused what u mean by updating the x,y position (that code snippet above was from my Move Ball function). Ya im not looking for perfect collision detection, because most of the game the ball WONT be colliding with a brick, just in some instances (its a different kind of game).

I am no dummy in coding, but was very perplexed by this problem since it looked right on paper though in practice it wasnt doing anything near correct.


So I have to ask, how do u mean update x and y position in seperate loops? they are updated in the game loop by adding the xv and yv of the ball to them? There is no nesting of the loop.

So i am abit confused as to the response here...


-Shane

<< Thanks, ill look into this, sorta confused what u mean by updating the x,y position (that code snippet above was from my Move Ball function). Ya im not looking for perfect collision detection, because most of the game the ball WONT be colliding with a brick, just in some instances (its a different kind of game). >>

You can check how I did this. Just wrote my first Windows game, VazBreak (a breakout clone). Yes, figuring out how to detect a brick and remove it was tricky. I did it by checking each corner of the ball (treated as a 16 pixel square). And in my case I check the NEXT position of the ball (or xball + xmove, yball + ymove). It works fine. The ball is 16 pixels around, and the bricks are 47 across and 15 down.

Therefore my IF statement looks like this:


      x = xblock[ i ]; y = yblock[ i ];            if ( block_exist[ i ] &&((xball+xmove+16 > x && xball+xmove+16 < x+47 && yball+ymove+16 > y && yball+ymove+16 < y+15) ||(xball+xmove > x && xball+xmove < x+47 && yball+ymove+16 > y && yball+ymove+16 < y+15) ||(xball+xmove+16 > x && xball+xmove+16 < x+47 && yball+ymove > y && yball+ymove < y+15) ||(xball+xmove > x && xball+xmove < x+47 && yball+ymove > y && yball+ymove < y+15))  ){  IF TRUE, THE BLOCK IS HIT  }    


edit: left off a closed paran above.

What this does is check each of the 4 corners of the ball (regardless of direction) treated as a square (16 pixels round). Works fine for me.

See the thread below with links to the source and game VazBreak.

www.bringyou.to/games

Phil P

[edited by - PhilVaz on April 21, 2003 11:14:13 PM]
I apologize, for I think my initial question was misleading, that or im really lost. I dont need help checking collisions between the ball and the brick, I have that, and it works fine...I need help figuring how it collided with the brick, what side it hit and how to reflect it again. The code post by PhilVaz didnt seem to provide that, but again its late so perhaps i didnt read into it right. Hmmm back to the drawing board...hmm its late maybe tomorrow zzzzz

Thanks again though,
-Shane
Could be wrong but doesnt breakout just reverse the velocity and vector of the ball when a hit is scored? Dont have the atari hooked up at the moment to take a look, but generally id just reverse your velocity. Though it is late so I could be thinking the wrong thing.
<< I need help figuring how it collided with the brick, what side it hit and how to reflect it again. >>

Well, with my version no need to worry about what side. If any corner of the ball hits anywhere inside the brick (my IF statement above), you just reverse the direction of y (ymove for mine), direction of x stays the same. See my VazBreak, I made it as simple as I could.

VazBreak.cpp

This is breakout of course, not a simulation that lands the space shuttle. :lol

Phil P
quote:Original post by Codejoy
for(int i=0; i<g_currNumBricks; i++) //check all bricks on field
{
if(Collision(&theBall, &picBrick)==TRUE) //we collided with a bricks rectangle
{
if((Ballxv > 0) && (Ballyv > 0)) //ball traveling down right
{
//Check the left side. Check bottom side.
if((theBall.y+theBall.height)> picBrick.y)<br> {<br> //we in the clear<br> Ballyv=-Ballyv;<br> }<br> else if( (theBall.x+theBall.width) &gt; picBrick.x) <br> {<br> Ballxv=-Ballxv;<br> }<br> }<br> else if((Ballxv &lt; 0) &amp;&amp; (Ballyv &lt; 0)) //travling up left<br> { <br> //Check the right side, top<br> if( (theBall.y) &lt; (picBrick.y+picBrick.height) ) <br> {<br> //we in the clear<br> Ballyv=-Ballyv;<br> }<br> else if( theBall.x &lt; (picBrick.x+picBrick.width) ) <br> {<br> Ballxv=-Ballxv;<br> } <br> }<br> else if((Ballxv &gt; 0) &amp;&amp; (Ballyv &lt; 0)) //up right<br> { //top check right.<br> //Check the left side. Check bottom side.<br> if(theBall.y &lt; (picBrick.y+picBrick.height))<br> {<br> //we in the clear<br> Ballyv=-Ballyv;<br> }<br> else if( (theBall.x+theBall.width) &gt; picBrick.x) <br> {<br> Ballxv=-Ballxv;<br> }<br> }<br> else if((Ballxv &lt; 0) &amp;&amp; (Ballyv &gt; 0) ) //traveling down left<br> { //Right side, bottom.<br> //Check the right side, top<br> if( (theBall.y+theBall.height) &gt; picBrick.y ) <br> {<br> //we in the clear<br> Ballyv=-Ballyv;<br> }<br> else if( theBall.x &lt; (picBrick.x+picBrick.width) ) <br> {<br> Ballxv=-Ballxv;<br> } <br> }<br> } <br>}<br> [/source] <hr height=1 noshade></SPAN></BLOCKQUOTE> <br><br>Just do this: like Eecole said, you need to seperate your X and Y testing. In your code, for eg, when the ball is travelling down right: You check for bottom collision or left side collision<br>but not both. That means, &#111;nly 1 of the if statements gets exectuted and ball will not bounce off if it hits a corner. I guess you need to do this:<br><br>for(int i=0; i&lt;g_currNumBricks; i++) //check all bricks &#111;n field<br>{<br> if(Collision(&amp;theBall, &amp;picBrick)==TRUE) //we collided with a bricks rectangle<br> {<br> if((Ballxv &gt; 0) &amp;&amp; (Ballyv &gt; 0)) //ball traveling down right<br> { <br> //Check the left side. Check bottom side.<br> if((theBall.y+theBall.height)&gt; picBrick.y)<br> {<br> //we in the clear<br> Ballyv=-Ballyv;<br> }<br> <br> if( (theBall.x+theBall.width) &gt; picBrick.x) //else removed<br> {<br> Ballxv=-Ballxv;<br> }<br> }<br> else if((Ballxv &lt; 0) &amp;&amp; (Ballyv &lt; 0)) //travling up left<br> { <br> //Check the right side, top<br> if( (theBall.y) &lt; (picBrick.y+picBrick.height) ) <br> {<br> //we in the clear<br> Ballyv=-Ballyv;<br> }<br> if( theBall.x &lt; (picBrick.x+picBrick.width) ) //else removed <br> {<br> Ballxv=-Ballxv;<br> } <br> }<br> else if((Ballxv &gt; 0) &amp;&amp; (Ballyv &lt; 0)) //up right<br> { //top check right.<br> //Check the left side. Check bottom side.<br> if(theBall.y &lt; (picBrick.y+picBrick.height))<br> {<br> //we in the clear<br> Ballyv=-Ballyv;<br> }<br> if( (theBall.x+theBall.width) &gt; picBrick.x) //else removed <br> {<br> Ballxv=-Ballxv;<br> }<br> }<br> else if((Ballxv &lt; 0) &amp;&amp; (Ballyv &gt; 0) ) //traveling down left<br> { //Right side, bottom.<br> //Check the right side, top<br> if( (theBall.y+theBall.height) &gt; picBrick.y ) <br> {<br> //we in the clear<br> Ballyv=-Ballyv;<br> }<br> if( theBall.x &lt; (picBrick.x+picBrick.width) ) //else removed <br> {<br> Ballxv=-Ballxv;<br> } <br> }<br> } <br>}<br> <br>I have removed a few &quot;else&quot; keywords from the code. comments indicate where I have done so. I think the above should improve the bounce-off simulation a better. It won''t be perfect still, but it should look much better!<br><br>Hope this helps!<br><br>-Arjun </i>

This topic is closed to new replies.

Advertisement