Skip to main content
gamedev.net
🔒 Locked

Somewhat basic collision

Started by Crow_ Jul 3, 2007 at 9:19 AM 2 replies 750+ views
Original Post
Crow_
Crow_
So, in a glOrtho'd 2D-esque side-scroller, I'm trying to get bullet vs. wall collision detection. The problem is as follows: bx is the bullet's x, by the bullet's y tx is the tile's x, ty is the tile's y size is the width AND height of the tile (both are the same) bsize is the width AND height of the bullet (both are the same) For hitting the top of the wall, my collision is like this
if(bx > tx && bx < tx + size && by + bsize > ty && by + bsize < ty + bsize) { collision stuff; }
/*If bullet x is in the tile, and the bottom of the bullet is more than the top of the wall and less than the top of the wall + bullet size*/

Left of the wall:
if(bx + bsize > tx && bx + bsize < tx + bsize && by > ty && by < ty + size) { collision stuff; }

Bottom of the wall:
if(bx > tx && bx < tx + size && by < ty + size && by > ty + size - bsize) { collision stuff; }

Right of the wall:
if(bx < tx + size && bx > tx + size - bsize && by > ty && by < ty + size) { collision stuff; }

However, for example, the bullet is hitting the left of the wall, the IF statement matches the same as the bottom of the wall, because all parameters match for both! So there isn't a way, in this method, I can check which side it's truly hitting. So I need a new method. I tried checking each corner of the bullet, and deciding things like "If the top right and bottom right corners are in the wall, it's hitting the left side", but it doesn't work in that instance where all 4 corners are in the wall (it happens: the bullet's x and y is increased by a velocity every loop, so if it happens to put all 4 corners inside than there isn't anything I can do about it) So any help? >.<
Omid Ghavami
Omid Ghavami
Note that this might not be exactly what you are looking for, but I hope you find it useful nevertheless.
If you want to do it properly you have to look at the move which has been made and check which side of the wall it must have first passed to get to where it is now given it's starting position:
    A_____B    |     |[]--|->[] |    |_____|    D     C

What you need to do is to check the intersection point between the line represented as an arrow in the picture and the lines corresponding to the sides of the tile, and see which intersection takes place first.
Let's say the initial position is given by the vector x0 and the new position is given by the vector x.
You get the displacement vector dx = x - x0
We can now represent our line as
x0 + t dx
Where 0 ≤ t ≤ 1

So we now have a single variable t controlling our position along the path.
Now we create similar line functions for the sides of the tile.
For example for the left side of the tile we have the line:
A + t' (D - A)

To check at what t we collide with the left wall we need to solve the following equation:

x0 + t dx = A + t' (D - A)

We have two unknown, and two equations (vector equation, so n-dimensions, in this case n = 2, since 2D) so we can solve it. Separate into two equations, one for each dimension:

x0x + t dxx = Ax + t' (Dx - Ax)

x0y + t dxy = Ay + t' (Dy - Ay)

We have the equation in matrix form:
| dx<sub>x</sub>    A<sub>x</sub> - D<sub>x</sub> | |t | =  |A<sub>x</sub> - x<sub>0x</sub>|| dx<sub>y</sub>    A<sub>y</sub> - D<sub>y</sub> | |t'|    |A<sub>y</sub> - x<sub>0y</sub>|


Which you can solve with your favorite method to get values for t and t'.
Doing this for all sides of the tile you then compare their t values and the side which gives the lowest value is the one you are interested in (values outside of the range [0,1] are obviously misses, since then you'll be passing a part of the line outside of the segment of interest which is a side of the tile). Note that you don't actually have any use for the t', so you can simplify your equation by specifying the t' values explicitly since you have straight sides (i.e finding t' is trivial).

I left out some details which were off-topic, hoping you'd either know of them or figure them out for yourself since the post already got extremely long. But feel free to ask if something is unclear, and I obviously may have made mistakes, so if something doesn't make sense don't be shy [smile]
Best regards, Omid
Crow_
Crow_
Hm, that's a method that sounds like it'd work xD

However, what about corners? Going through both lines at the same exact place, such as the bullet being 1pixel in y and x both?


Also, I have no idea how to put that into programming form :P

What's the difference between t' and t?

Possibly:

//pbx = previous bullet x//pby = previous bullet y//Left wall checkif(pbx + (bx - pbx) > 0 /*Left Wall = (0, 0) -> (0, 32)*/ && pbx + (bx - pbx) < bsize && pby + (by - pby) > 0 /*Tile total is 32x32*/ && pby + (by - pby) < 32)


Nah nevermind that wouldn't do it...
Omid Ghavami
Omid Ghavami
Quote:
Original post by Crow_
However, what about corners? Going through both lines at the same exact place, such as the bullet being 1pixel in y and x both?


Well, I can't immediately tell how far this can be stretched before you have to take another step and increase the complexity (introduce bounding forms for example). The idea was to keep the system relatively simple by considering the projectile as a point when determining the side of interest and once that has been established take it's dimensions into account to make more precise collision detection between it and the side.

Quote:
Original post by Crow_
What's the difference between t' and t, and what's the "d" in the equation for (dx)?

t is displacement along the line representing the bullets movement. t' is displacement along the line representing a side of the wall.
The dx was merely a name I chose to give the vector x - x0, it's NOT the derivative. Sorry if I confused you!

Quote:
Original post by Crow_
Also, I have no idea how to put that into programming form :P


Collision detection is a pretty advanced topic, even at such simple levels it may seem quite complicated. In order to implement something such as this you first need to introduce the notion of vectors. If you don't already have a vector class, or don't want to write one, there are several free open-source vector classes available.
The next thing you need is a linear equation system solver. For the simple case of a 2-dimensional problem, I can derive the explicit solution for you.
ax + by = e
cx + dy = f

In matrix form
|a  b| |x|     | e ||    | | |  =  |   ||c  d| |y|     | f ||a         b      | |x|     |       e       ||                 | | |  =  |               | |0  d - b * c / a | |y|     | f - e * c / a |

Solution is given by:
y = (f - e * c / a) / (d - b * c / a)  = (f * a - e * c) / (d * a - b * c)x = (e - b * y) / a


Hopefully I made no arithmetic errors [smile]

So given the last two equations in your case x = t and y = t' and you just need to insert values for a, b, c, d, e and f and you have your results.
a = x-component of x - x0
b = x-component of (A - D)
c = y-component of x - x0
d = y-component of (A - D)
e = x-component of A - x0
f = y-component of A - x0

If I got it right [smile]

Hope this helps

EDIT: typo
Best regards, Omid

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.