Two rectangles colliding
#1 Members - Reputation: 204
Posted 21 November 2012 - 06:08 AM
There is an other case where I need to check if the unit is colliding from the right, left, up or down. I am having trouble getting this function to work.
Anyone have or know a piece of code that works(C/C++/Java/C#)?
#2 Members - Reputation: 212
Posted 21 November 2012 - 11:11 AM
if(x1.intersects(x2)){
if(enemy.dx == 1)
- do something
if(enemy.dx == -1)
- do something
if(enemy.dy == 1)
- do something
if(enemy.dy == -1)
- do something
Maybe that's a bad method, but I use it
#3 Members - Reputation: 363
Posted 21 November 2012 - 12:00 PM
Consider PlayerDir as a vector pointing in direction the player looks and EnemyDir is the direction in which an enemy moves.
Using following calculation :
(PlayerDir.x * EnemyDir.x + PlayerDir.y * EnemyDir.y);
you get the value of cosine between their directions. Importantly, make sure that PlayerDir and EnemyDir are normalized! Otherwise you have to divide your result by length of both vectors!
If result was positive it means, that player and enemy moved in the same direction, so the player was hit in the back. If negative than, they moved in opposite directions. If you get value really close to 0, it means the player was hit from the side.
Edited by DgekGD, 21 November 2012 - 12:04 PM.
#4 Members - Reputation: 432
Posted 22 November 2012 - 12:36 AM
Collision util functions are defined here:
https://github.com/larsbutler/gamedemo/blob/master/src/com/larsbutler/gamedemo/math/Collision.java
And everything is used here:
https://github.com/larsbutler/gamedemo/blob/master/src/com/larsbutler/gamedemo/core/GameState.java#L95
This method would need to be optimized for lots of collisions, but for a low number it works well; it's reliable and stable.
I hope that helps.
#5 Crossbones+ - Reputation: 1094
Posted 22 November 2012 - 11:55 AM
Now let's assume we know there's a sideways collision between rectangles R1 and R2. It's really easy to determine which side the collision is on: you just look at their relative velocities. If vx2-vx1>0, R2 hit R1 from the left, otherwise it hit R1 from the right. If we know we have a vertical collision, same thing, we check vy2-vy1>0.
Looking at the middle points, x2-x1>0, would also work if the rectangles move slowly relative to their size. If they move so fast that one rectangle is already more than halfway inside the other when the collision check happens, this will produce a collision from the wrong side whereas velocities would produce the right result. Of course, if the rectangles move even faster, they will get past each other entirely before the collision check happens. To prevent that you'd have use a different strategy to check for collisions in the first place.
So that was trivial. The more interesting part is determining whether your collision is sideways or vertical. This is how I'd go about checking it:
1) For a collision to have happened, the rectangles must now be overlapping in both x and y directions.
2) We assume this is the first frame when the collision happens.
3) Therefore, on the last frame, the collision was not happening, and that means either the rectangles were overlapping in x direction, overlapping in y direction, or neither.
4) The last direction of those two directions which came to overlap is the collision direction.
(how to check presence of overlap between two rectangles in x-direction: abs(x1-x2) < (w1+w2)/2)
5) We check overlap between oldR1 and oldR2.
(we can get the old coordinates from new coordinates and velocity; oldx1 = x1-vx1, oldy1 = y1-vy1 and so on).
6) If there was x overlap between oldR1 and oldR2, the collision is vertical, because it's impossible for two rectangles overlapping in x direction to move in a straight line and collide horizontally. If there was y overlap between oldR1 and oldR2, the collision is horizontal.
7) In the special case that there was no x-overlap and no y-overlap, both overlaps occurred between last frame and this frame. Now it is slightly harder to figure out which of those overlaps occurred first and which occurred last. We'll call the moment of time when x overlap happened as timex and its counterpart as timey. With the exact same logic as before, if timex < timey is true, the collision is vertical, otherwise it is horizontal.
8) How to get timex and timey? It's elementary physics; distance divided by velocity equals time. In this case, the distance is the gap between the rectangles, and the velocity is the rectangles' relative velocity.
(timex = gapx / vx = (abs(oldx2-oldx1)-(w1+w2)/2) / abs(vx2-vx1))
Edited by Stroppy Katamari, 13 December 2012 - 04:02 PM.
#8 Members - Reputation: 3363
Posted 28 November 2012 - 11:12 AM
Part One -- covers the concept of an AABB in the first place, as well as having the code to check for a rectangle on rectangle collision.
Part Two -- which I literally posted 15 minutes ago, covers resizing the bounding box as your sprite rotates.
Both samples have a running example in the browser ( JavaScript using Easel ), but break out the math specific parts into their own section and have a complete explanation how everything works. Although the samples are in JavaScript, the code is basically 90% compatible with C#/C++/Java, so you only need to change a few key words to get it to compile in your language of choice ( which is why I went with JavaScript for examples... that and obviously it runs in the browser ).
#10 Members - Reputation: 204
Posted 13 December 2012 - 11:27 AM
I want a global method to check this, so I have looked a bit closer at Stroppy Katamaris post.
With all due respect, your text is cryptic. Why is velocity needed? Old R2? timex/timey?
Could you please clarify your post?
#11 Members - Reputation: 1613
Posted 13 December 2012 - 12:21 PM
Then, move it on the y-axis, and check if it collided, and, if so, you know if it hit top or bottom based on Y velocity.
The obvious downside is you do 2 checks, but it's probably not a problem unless you have tons of objects you are checking against. If so, you should do some spatial hashing, but don't worry about that unless you have to.
Good luck.
---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)
#13 Members - Reputation: 1613
Posted 13 December 2012 - 01:42 PM
But what would happen if this test is performed when they are intersecting already?
How can that happen, and why is it any different from any other collision test check? If you've written your code right, you should never enter a new movement loop when your character is already intersecting with something else, unless it's meant to be.
---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)
#14 Members - Reputation: 1677
Posted 13 December 2012 - 03:20 PM
I solved that by adding a property to the paddle that caused it to cease being collidable for a few frames after collision. There was no other reasonable response in that case since the paddle does not react to the ball physically. In terms of objects that follow the normal rules of physics, though, the answer is simply to run testing for all objects as they move.
There are ten kinds of people in this world: those who understand binary and those who don't.
#15 Crossbones+ - Reputation: 1094
Posted 13 December 2012 - 04:00 PM
If you just have the locations of two overlapping rectangles, there is no way to tell accurately whether they collided vertically or horizontally. You have to know where they came from, in other words, where they were at last frame. Current position minus velocity gives you that last position, so you don't have to store the last position separately.Well my so called "solution" was limited to work with one single situation and the code is not reusable.
I want a global method to check this, so I have looked a bit closer at Stroppy Katamaris post.
With all due respect, your text is cryptic. Why is velocity needed? Old R2? timex/timey?
Could you please clarify your post?
I have revised the post. It was indeed cryptic but should be a lot easier to follow now. I also made an error with a formula that is now fixed. Please follow the logic of the numbered steps, trying to understand each one before moving to the next, and ask for help if you get stuck at some specific part.






