Jump to content

  • Log In with Google      Sign In   
  • Create Account


Two rectangles colliding


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
14 replies to this topic

#1 P0jahn   Members   -  Reputation: 242

Like
0Likes
Like

Posted 21 November 2012 - 06:08 AM

There is a tutorial here that explain how to check if two 2D-rectangles collide. It works excellent in most cases in my game.
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#)?

Sponsor:

#2 Patriarch K   Members   -  Reputation: 212

Like
0Likes
Like

Posted 21 November 2012 - 11:11 AM

I use to solve this by having a "direction" of the objects. If you have for example an enemy object then you can use
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 DgekGD   Members   -  Reputation: 374

Like
1Likes
Like

Posted 21 November 2012 - 12:00 PM

You can use Dot Product for this purpose.

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 thok   Members   -  Reputation: 662

Like
0Likes
Like

Posted 22 November 2012 - 12:36 AM

I've implemented a simple collision detection/response method for a 2d platform game project. At the moment, the only response I've coded is between player and platform collisions.

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 Yrjö P.   Crossbones+   -  Reputation: 1412

Like
0Likes
Like

Posted 22 November 2012 - 11:55 AM

We have rectangles R1 and R2. R1 has middle point (x1,y1), height h1, width w1, and is moving at velocity (vx1, vy1). Same stuff for R2.

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.


#6 P0jahn   Members   -  Reputation: 242

Like
0Likes
Like

Posted 27 November 2012 - 06:59 PM

Thanks for the help.
I have resolved this problem.

I appreciate the great help, looking forward to stay here :)

#7 Yrjö P.   Crossbones+   -  Reputation: 1412

Like
1Likes
Like

Posted 28 November 2012 - 05:28 AM

I have resolved this problem.

It would be considerate to tell how you resolved your problem, both for the benefit of those who have the same problem later, and for the benefit of those who tried to give you advice.

#8 Serapth   Crossbones+   -  Reputation: 5179

Like
0Likes
Like

Posted 28 November 2012 - 11:12 AM

Funny you should mention this, I just finished posting a two part tutorial on bounding box collisions.

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 ).

#9 P0jahn   Members   -  Reputation: 242

Like
0Likes
Like

Posted 30 November 2012 - 02:26 PM

My solution is irrelevant because uses variables that are exclusive to my game(and not to an actual rectangle) to calculate this.

Edited by P0jahn, 30 November 2012 - 02:26 PM.


#10 P0jahn   Members   -  Reputation: 242

Like
0Likes
Like

Posted 13 December 2012 - 11:27 AM

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?

#11 BeerNutts   Crossbones+   -  Reputation: 2555

Like
0Likes
Like

Posted 13 December 2012 - 12:21 PM

The simplest method is to 1st move the object in the X-axis, check if it's intersects anything; if so, you know if u hit it on left or right (based on velocity), and you should move it back along the x-axies.

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.
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

#12 P0jahn   Members   -  Reputation: 242

Like
0Likes
Like

Posted 13 December 2012 - 01:04 PM

Sounds like a working solution. But what would happen if this test is performed when they are intersecting already?

#13 BeerNutts   Crossbones+   -  Reputation: 2555

Like
0Likes
Like

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.
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

#14 Khatharr   Crossbones+   -  Reputation: 2818

Like
0Likes
Like

Posted 13 December 2012 - 03:20 PM

It can happen if you have a moving object that's driving collision detection and a moving object that's not. I ran into that problem in my breakout clone - the ball drives collision, but the paddle can also move (and thus come to intersect the ball).

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.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

#15 Yrjö P.   Crossbones+   -  Reputation: 1412

Like
0Likes
Like

Posted 13 December 2012 - 04:00 PM

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?

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.

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.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS