[SFML] Special Collision Detection

Started by
17 comments, last by superman3275 11 years, 7 months ago
So, I've been programming Breakout (I'm still trying!) and I ran into a problem: Using floatrects, how do I create proper collision detection. The ball can hit the blocks from all sides, which means there's four different ways the ball can collide, which means simply using
if (MyFloatRect.Intersects(MyOtherFloatRect))
{
// Collision detection
}

won't work? How should I handle collision? Thank you for reading my post, I'm sure there's a glaring solution I can't figure out :)

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !

Advertisement
Sounds like a good time to read up on _collision_ detection, which is a lot more interesting than _intersection_ detection. Just moving the ball and checking for intersection with a rectangle is going to fail anyway if your ball is moving too fast.

It also depends on whether you want to treat your ball as a point (for simplicity) or an actual sphere (requiring special handling for the corners) or if you don't need perfectly precise collisions anyway.

Of course, it could also be a good time to grab some simple 2D physics engine, if you just want it working without diving into the math behind it.
f@dzhttp://festini.device-zero.de
There are a few ways to do collision detection.

Grids, bounding box, pixel perfect, ect...

For something like this, I would learn bounding box collision if you're new to how collision works.

Your main objective here is to get the x and y values for each object, and their current height and width to create a top, bottom, left, and right. Now, you will be checking if one box (or several) collide with another box, which means collision has been detected. I will show you a basic example.

Paddle:

Paddle_BB_Top = Paddle_Y
Paddle_BB_Left = Paddle_X
Paddle_BB_Right = Paddle_Width + Paddle_BB_Left
Paddle_BB_Bottom = Paddle_Height + Paddle_BB_Top

Ball:

Ball_BB_Top = Ball_Y
Ball_BB_Left = Ball_X
Ball_BB_Right = Ball_Width + Ball_BB_Left
Ball_BB_Bottom = Ball_Height + Ball_BB_Top

Now to detect if collision is true, you would simply have basic check seeing if anything collides.

if (Paddle_BB_Bottom > Ball_BB_Top &&
Paddle_BB_Top < Ball_BB_Bottom &&
Paddle_BB_Right > Ball_BB_Left &&
Paddle_BB_Left < Ball_BB_Right)
{
Collision = true;
}

I hope this helps, feel free to ask any additional questions.

Edit: The most important thing to never forget!!! You must update these values for each frame, or your bounding boxes will have incorrect values. So make a function to update the values before checking for collision.
GameDev Journal: http://www.gamedev.n...-rooks-journal/

OpenChess - 1.0 done!

Classic RPG #1 - Task 9 -> January 1st 2013

There are a few ways to do collision detection.

Grids, bounding box, pixel perfect, ect...

For something like this, I would learn bounding box collision if you're new to how collision works.

Your main objective here is to get the x and y values for each object, and their current height and width to create a top, bottom, left, and right. Now, you will be checking if one box (or several) collide with another box, which means collision has been detected. I will show you a basic example.

Paddle:

Paddle_BB_Top = Paddle_Y
Paddle_BB_Left = Paddle_X
Paddle_BB_Right = Paddle_Width + Paddle_BB_Left
Paddle_BB_Bottom = Paddle_Height + Paddle_BB_Top

Ball:

Ball_BB_Top = Ball_Y
Ball_BB_Left = Ball_X
Ball_BB_Right = Ball_Width + Ball_BB_Left
Ball_BB_Bottom = Ball_Height + Ball_BB_Top

Now to detect if collision is true, you would simply have basic check seeing if anything collides.

if (Paddle_BB_Bottom > Ball_BB_Top &&
Paddle_BB_Top < Ball_BB_Bottom &&
Paddle_BB_Right > Ball_BB_Left &&
Paddle_BB_Left < Ball_BB_Right)
{
Collision = true;
}

I hope this helps, feel free to ask any additional questions.

Edit: The most important thing to never forget!!! You must update these values for each frame, or your bounding boxes will have incorrect values. So make a function to update the values before checking for collision.


This is going to be exactly the same as doing a pure intersect check, and unless it is done as a per-pixel update it isn't going to solve the problem. An intersect check, as outlined by the OP, or as done by you, checks if one object has hit another (as Trienco said, either of these is going to fail if the ball is moving too fast).

The problem that the OP is having is determining where the ball has hit an object. By using an intersect I can tell that the ball has hit a block. I can't tell that it hit the left and should reflect left, or hit the top and should reflect up.

Even just considering the previous position of the ball before the intersect doesn't work perfectly, in particular when striking near the corner of the object.



In order to get this to work perfectly you have to consider the previous position, calculate the path of the ball up until the point of collision, and then determine which side of the block the ball hit. If you can give details on how you're storing and updating your positions then I might be able to help with a bit more detail.
Maybe I'm reading the question wrong... But I would just create four collision lines, one for top, bottom, left, and right for each block. Then if the ball hits a block's left collision line, it will act in the way you want it to, the same for the block's right collision line..

Edit: Just to explain how you would do this encase you ask. You would make four "collision boxes", one for left, right, top, bottom in your block class. This is very easy to setup based on your blocks X and Y values. Then you would just make a line pretty much that outlines the block for collision checking. You can even have the ball hit the corner of the block - meaning it hit the left and bottom lines then move the in proper direction.
GameDev Journal: http://www.gamedev.n...-rooks-journal/

OpenChess - 1.0 done!

Classic RPG #1 - Task 9 -> January 1st 2013

Maybe I'm reading the question wrong... But I would just create four collision lines, one for top, bottom, left, and right for each block. Then if the ball hits a block's left collision line, it will act in the way you want it to, the same for the block's right collision line..


This may work, but it would depend on a few things: How they want to handle corners, how often the ball's position is refreshed, how they would handle it if the ball intersected two collision objects (if the ball hit near the corner and intersected both left and top).
Answered the corner part in my edit.

"Edit: Just to explain how you would do this encase you ask. You would make four "collision boxes", one for left, right, top, bottom in your block class. This is very easy to setup based on your blocks X and Y values. Then you would just make a line pretty much that outlines the block for collision checking. You can even have the ball hit the corner of the block - meaning it hit the left and bottom lines then move the in proper direction."

He should be refreshing the balls position each frame which makes it impossible to miss a collision check. I've used this method before and it does work.
GameDev Journal: http://www.gamedev.n...-rooks-journal/

OpenChess - 1.0 done!

Classic RPG #1 - Task 9 -> January 1st 2013

He should be refreshing the balls position each frame which makes it impossible to miss a collision check.


This isn't true. In a lot of 2D games it is probably 'Good Enough.' But unless you can guarantee a limited speed there is a chance of missing a collision detection. Even with a limited speed there's still a chance of missing collision in certain circumstances.

If we assume a game of pong running at 60FPS. The paddles are 20 pixels wide. The ball is 30 x 30 pixels. The ball takes two seconds to cross between the paddles (moving purely horizontally). There's 1000 pixels between the two paddles.

Each update the ball moves 17(ish) pixels. At this rate, it's never going to pass straight through a paddle.

If the ball is moving faster. One second between paddles, it'll move at 34 pixels per redraw. 1/2 a second and the ball moves 68 pixels, skipping straight through the paddle becomes quite likely.

If we take the smaller speed. Moving 17 pixels per redraw, but also include now a vertical motion too at the same speed, 17 pixels per redraw, there's still a chance at missing a collision detection:

pixelchecka.png

The image above is drawn to scale. The two black boxes are the before and after position of the ball (moving either diagonally up left, or down right, doesn't matter), the blue box is a paddle. Now, clearly between these two positions it should collide with the top, or right of the paddle (depending on direction of movement), but based on intersect checking it won't.

Moving on to the problem of determining which side the ball hit:


"Edit: Just to explain how you would do this encase you ask. You would make four "collision boxes", one for left, right, top, bottom in your block class. This is very easy to setup based on your blocks X and Y values. Then you would just make a line pretty much that outlines the block for collision checking. You can even have the ball hit the corner of the block - meaning it hit the left and bottom lines then move the in proper direction."


Assuming:
If the ball hits the right or left, you want it to bounce back right or left, so you reverse the X motion.
If the ball hits the top or bottom, you want it to bounce back up or down, so you reverse the Y motion.
If the ball hits a corner, you want it to bounce back diagonally, so you reverse both the X and Y motion.

This is going to be another case whereby having intersect checking in the way you described may be 'Good Enough' but isn't going to be perfect.

pixelcheck2.png

Considering the above image. This ball is moving upwards and left, and on the update it hits the paddle. According to intersect checking with different bounding boxes per side, this is a perfect corner hit (it hit both the top and right sides) and so it reverses direction in both X & Y, and moves back down and right.

If you did a per-pixel check on the motion of the ball, then the ball actually hits the right side of the paddle and continues to bounce up and right.

You could define each action based on each corner individually, ie, "if the ball hits the top right corner make the ball travel up and right" "if the ball hits the top left corner make the ball travel up and left" to minimise this. Although this is rather cumbersome way of doing it. There is also still the problem of missing the paddle, or of hitting an incorrect side (ie, if the update is partially inside the paddle but hitting the bounding box for a different side then the direction of travel)

The way to get it to behave perfectly is either to redraw upon every pixel of movement (an obscenely intensive thing to do in most circumstances), or using vector math to determine if the path of the ball passed through an object, calculate point of impact, and react accordingly.

Now, I do agree that having bounding boxes for different sides can be good enough. It depends on the game, how often you're redrawing, how fast the ball will move. It'll depend on how the OP wants to handle it, but if he does want perfect behaviour I don't think this would be the way to do it.

Considering that this is for a breakout style game, even though the path based collision may seem more complicated, it would be simpler in the long run I think because it also reduces the need for consideration of how to react to multiple collisions. If you use intersect checking against two blocks together, then there's a high likelihood that the ball is going to intersect with (for example) the bottom left corner of one block, and the bottom right corner of another, or even intersecting with 3 (or more) blocks.

If you calculate the path and react according to point of impact, if it hits two blocks then you still know that it has hit the bottom of two blocks together, or the right, etc, and can react accordingly.
I do see your point indeed. However this is not exactly a beginner topic.

In some of my projects I do what's called back tracking for a collision check. Even though I preform standard collision checks, I also check to see if any possible collision could have happened during that given movement. I've rarely seen this discussed or explained to new game developers, but it's indeed a great thing to learn.

This would only be required if movement per frame of an object has the possibility of jumping over an object. Example a unit moves 4 pixels per frame and you intend on moving up, yet there is a bush 2x2 pixels ahead of you. You would simply jump over the object if you landed 2 pixels below and then proceeded to move up.

superman3275 could program a check which will "ghost" move the ball, check from the point of movement to where it had landed per move in the logic, then if the ball would have jumped the first block, or a left/right side, or corner, then backtrack the ball to that location of contact, other wise continue. Which is pretty much as you stated.

I can see how this will turn into a lengthy process. I hope you're able to work out a good solution.
GameDev Journal: http://www.gamedev.n...-rooks-journal/

OpenChess - 1.0 done!

Classic RPG #1 - Task 9 -> January 1st 2013
I normally just use some basic guards so that objects don't go past each other, but that's not my question. The only thing I could think of doing is setting up four boxes, one for every side (I made pong, I know what bounding box collision is). I'm going to try to look into some more Collision Detection ideas. Also, from what I understand, all you have to do to make sure your ball doesn't go past your paddle is use a few variables and run a check every game loop, if I'm correct?

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !

This topic is closed to new replies.

Advertisement