Perfect collision for breakout-style game

Started by
13 comments, last by ByteMe95 21 years, 8 months ago
If you know the starting block (3,5) and ending block (5,6) just take all blocks in the X range 3..5 and Y range 5..6, that is, 6 blocks. Most of the time (unless the game is really slow, your ball will be in 1 2 or 4 blocks).

As for the line collision, you only have to check for two lines since its impossible to collide an edge from behind. See what I mean?

If the ball is coming from top right, it''s impossible to collide with bottom or left sides. Even more, if your vertical displacement is smaller than one block, you don''t have to test for top and bottom edges. Same for horizontal displacement and left-right edges. If the total ball movement is constrained in only ONE block, you don''t have to test at all!

Never forget to take the ball size into account.
Editor42 ...builds worlds
Advertisement
(Long post - the bottom paragraph may be all you care about)

No good replies yet (sorry everyone who posted before me - you''re all stupid!!!, jk)

Anyways. First, inorder for what I''m about to say you need to have your blocks mapped on the level such that every block is the same number of pixels high and wide. Basically this will allow you to find what block a pixel is in using a simple divide.

i.e. running and 800 by 600 every block is 40px wide(20 blocks across) and 15px high(# of blocks up and down depend on how much of the screen you decide to use) starting at 0,0. That means a pixel at 201, 48 would be the 5th block on the X axis and the 3rd block down.

Also, the blocks should be stored in a 2 dimensional array (or if 1d, have a macro to access blocks based on 2 dimensions). After you have this, its quite simple.

The ball has TWO leading edges, an X and Y. If the ball is going to the top right of the screen the two leading edged are the top and right. Check the top middle pixel of the ball bitmap, and the right middle pixel of the ball bitmap for collisions. It should be as simple as getting the coordinate, dividing it to find what block its in. THEN use the modulus operator to find out wether to the coordinate is closer to the top or bottom of the block, or left or right.

In psuedo algorithm here is what you do:

-Get leading X coordinate based ball''s velocity.
-Divide to find out what block row and col the block is in.
-If there is a block there, negate the X velocity of the ball.
-Repeat steps with Y axis collision.
"Ogun's Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
Ebony:
your suggestion is very itneresting as well, and I do have everything set up as you said (800x600, each block is 32x16 I believe).
Your solution is definately doable, BUT you completely neglected the second part of my problem.

Coin: Now I see what you''re saying, good call.
I have yet to decide waht t go with that wont be a CPU hogf or many balls, though coin your solution does sound most efficient

ByteMe95::~ByteMe95()
My S(h)ite
ByteMe95::~ByteMe95()My S(h)ite
You are making the problem more complicated that you have to. You already have a ray cast for you between frames. The ray is the velocity of the ball. Plus you already know the positions of the blocks. If the blocks are static, it is simple. If the blocks are moving, then it is complicated.

If your ball is 5 pixels by 5 pixels, and its current position is 200,200(on center). If the ball is moving at xv=5 and yv=-25 then you could possibly jump a block. If you have a block at 170,180(top left corner) then the ball could jump this block. The bottom right corner of this block is 202,196. Now you do a bounding box type of check. The four corners of the ball are:

198,198 ball_corner[1]
202,198 ball_corner[2]
202,202 ball_corner[3]
198,202 ball_corner[4]

The four corners of the block are:

170,180 block_corner[1]
202,180 block_corner[2]
202,196 block_corner[3]
170,196 block_corner[4]

Now you check the blocks corners against the starting and ending corners of the ball to see if there is a collision. If a velocity is positive, then the ball start corner should be greater than the blocks and the ending corner should be less:

  for(int i=1;i<=4;i++) {  for(int j=1;j<=4;j++) {    if(xv>0) {      if(ball_corner[j].x < block_corner[i].x && ball_corner[j].x+xv > block_corner[i].x) {        if(yv>0) {          if(ball_corner[j].y < block_corner[i].y && ball_corner[j].y+yv > block_corner[i].y) {            return true;          }        }        else if(yv<0) {          if(ball_corner[j].y > block_corner[i].y && ball_corner[j].y+yv < block_corner[i].y) {            return true;          }        }      }    }    else if(xv<0) {      if(ball_corner[j].x > block_corner[i].x && ball_corner[j].x+xv < block_corner[i].x) {        if(yv>0) {          if(ball_corner[j].y < block_corner[i].y && ball_corner[j].y+yv > block_corner[i].y) {            return true;          }        }        else if(yv<0) {          if(ball_corner[j].y > block_corner[i].y && ball_corner[j].y+yv < block_corner[i].y) {            return true;          }        }      }    }  }}return false;  


Worst case, this could be slow. But you get the point and you could optimize it from here.

This is set up as a function call to make it easy to exit the loop. You might even be able to make the compiler inline it.

---
Make it work.
Make it fast.

"I’m happy to share what I can, because I’m in it for the love of programming. The Ferraris are just gravy, honest!" --John Carmack: Forward to Graphics Programming Black Book
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]
captain that is very basic bounding box collision detection which I already have implemented.

You didnt address my real problem which is which way to make the ball bounce (which is becoming less and less of an issue) and more importantly problem #2

coin: if i do raycasting adn follow the ray through X possible colisions until i reach the magnitutde of the velocity vector of the ball (say in a perfect world, but slow running game, it was supposed to collide with 3 blocks in one frame), I actually have to move the position of the ball in addition to it''s x/y velocities correct? As of right now i never touch the ball''s coordinates frmo the collision detection, it just adjusts the balls velocities based on a collision, but that has the problems I started this thread with of course.

ByteMe95::~ByteMe95()
My S(h)ite
ByteMe95::~ByteMe95()My S(h)ite

This topic is closed to new replies.

Advertisement