9 Replies - 4072 Views - Last Post: 11 April 2013 - 09:50 AM

#1 s0me0ne  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 35
  • Joined: 05-November 11

Multiple Side Collision Detection on Obstacles

Posted 17 February 2013 - 06:27 AM

Hello folks. I am working on a little XNA game and I am kinda stuck at the moment.

So, my issue is how to properly do some Collision Detection on obstacles. Take a look on the picture below:

Posted Image

Basically, this is my player and I want him to collide with that kind of obstacles from every side. So there are 4 cases as shown on the picture.

For example, if we are on case 2, then this means that our player was falling from a higher position and we need to stop him on the top of that obstacle.

Below is my code's logic which is trying to detect case 1. In that case our player should stop moving and if he tried to jump on the obstacle but didnt jump high enough, he should fall back.

Heres a part of the code:
List<Obstacle> obstacles;
Player player;
Texture2D texture;
 
foreach (Obstacle ob in obstacles)
{
        // We are either in case 1 or case 3 
        if ((position.Y + texture.Height / 2 > ob.Position.Y) && (position.Y + texture.Height / 2 < ob.Position.Y + ob.Texture.Height))
        {
                if((position.X + texture.Width > ob.Position.X) && (position.X < ob.Position.X))
                {
                 // We detected case 1 and we could knowback the player or stop him from moving
                }
        }
}


- position is a Vector2 (X, Y) which holds the current position of our player or the obstacle.
- Texute.Height returns the Height of the obstacle.

So, my thought was that firstly I had to seperate the 4 cases into 2 cases. I groupped up case 1 with case 3 and case 2 with case 4.

So, applying the above logic for all the cases causes many bugs and basically it became quite complex.
I really doubt it that this is the best way to go, but I was not able of finding some good examples around in the web. So, my (finally) question to you guys is if there exists some better way to do such collision detection or I will have to keep struggling on the technique until everything works.

Later on I will have to add collision detection for enemies-obstacles, player-enemies and the above CD player-obstacles.
Some enlightenment would really help me move forward. Anything that you could add or notice or comment is welcome.

Thanks in advance for any kind of replies :)

This post has been edited by s0me0ne: 17 February 2013 - 06:31 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Multiple Side Collision Detection on Obstacles

#2 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1355
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Multiple Side Collision Detection on Obstacles

Posted 18 February 2013 - 06:42 AM

Your best bet here is to have the player class keep track of a bounding rectangle around the character at it's current position. You'll also want a bounding rectangle that represents the location of each obstacle, or any other object, that you want to check collision with. Then there's an easy method of testing whether two objects collide using the Intersects boolean of the Rectangle class.

What I like to do with simple bounding volume collisions is to add the current position of the player, and a vector2 that keeps track of the speed that the player object is moving to create a new position to check for collisions. If there is not a collision at the new location, then allow the player to move to that position. If there is a collision, then prevent the movement and set speed to 0.

There are many more advanced and more accurate ways of doing this, for instance I go further than that on a few projects by checking for the collision using the method I mentioned above, and if there is a collision with the rectangles, I then check the pixel data and use a per-pixel collision detection to see if the player's sprite actually collided with an object, or if it was just the bounding rectangle. If the sprite would collide at the new position, I stop movement. If the sprite doesn't collide at the new position, then I allow the movement and check again for the new position based on the speed.
Was This Post Helpful? 0
  • +
  • -

#3 s0me0ne  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 35
  • Joined: 05-November 11

Re: Multiple Side Collision Detection on Obstacles

Posted 18 February 2013 - 06:48 AM

Thanks a bunch for your detailed reply Kilorn :)

What you said helps me a lot, but still I am not pretty sure if I am on the right way.

I am doing a collision prediction too. Almost the same thing like the one with the speed that you mentioned.

Although, I am not sure if there will be problems laters when I will need to do collision detection between enemies, player and obstacles.

So, I am not sure if I understood well.

Do you think that my way of seperating the 4 cases in the player-obstacle collision is fine? Or is there something better to go with ?

Thanks again for your time.
Was This Post Helpful? 0
  • +
  • -

#4 Hapro  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 7
  • Joined: 14-August 12

Re: Multiple Side Collision Detection on Obstacles

Posted 02 March 2013 - 06:11 AM

I have been testing out some collision resolution code recently, and this seems to work pretty well.

First, you need to find the intersection distance:
public Vector2 FindIntersectionDepth(Rectangle rec1, Rectangle rec2)
        {
            Vector2 depth = new Vector2(0, 0);

            if (rec1.Intersects(rec2))
            {
                //Gets the amount of intersection from the left, right, top and bottom of the sprite
                int x1 = rec1.Left - rec2.Right;
                int x2 = rec1.Right - rec2.Left;
                int y1 = rec1.Top - rec2.Bottom;
                int y2 = rec1.Bottom - rec2.Top;

                //Returns the smallest intersections
                depth.X = Math.Abs(x1) < Math.Abs(x2) ? x1 : x2;
                depth.Y = Math.Abs(y1) < Math.Abs(y2) ? y1 : y2;

            }
            return depth;
        }


This function returns a Vector2 of the depth of the collision.

public void HandleCollisions()
        {
            //Find the collision depth
            Vector2 depth = FindIntersectionDepth(player.Bounds, tile.Bounds);

            //If there has been a collision
            if (depth != Vector2.Zero)
            {
                //Resolve the smallest distance first, then call HanldeCollions()
                //again to resolve on the next axis
                if (Math.Abs(depth.X) > Math.Abs(depth.Y))
                {
                    player.location.Y -= depth.Y;
                    HandleCollisions();
                }
                else
                {
                    player.location.X -= depth.X;
                    HandleCollisions();
                }
            }
        }


This procedure gets the intersection depth, and adds the smallest intersection to the players location.
It then uses recursion to make sure there are no further collisions with this sprite. For this code to work,
you must use a property in your Sprite class to make sure that the bounds are always in line with the location:
public Rectangle Bounds
        {
            get { return new Rectangle((int)location.X, (int)location.Y, texture.Width, texture.Height); }
        }

Hopefully you should be able to figure out how to implement this into your code.
Note that this code will produce a 'jittering' effect unless you draw your sprites using this property, instead of using a Vector2.

I hope this helps :)/>/>.
Was This Post Helpful? 0
  • +
  • -

#5 s0me0ne  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 35
  • Joined: 05-November 11

Re: Multiple Side Collision Detection on Obstacles

Posted 03 March 2013 - 12:18 PM

@Hapro

Thanks for your reply mate :)/>. I have some questions though.

1) Why did you choose recursion in order to implement this? If I try your way, I get a Stack Overflow exception right after the first collision happens. This makes sense since the HandleCollision function will be called so many many times since my enemy remains on an obstacle for long time. On the other hand, when I tried limiting the number of recursive calls it didn't work.

My game's gravity forces the player to go through the obstacles since it updates its location.Y faster than the HandleCollision function. Unless if I call this function all the time recursively like you, but then I keep getting Stack Overflow exception.

Any ideas ?

Your logic seems quite simple compared to mine, if only I could make it work heh.

This post has been edited by s0me0ne: 03 March 2013 - 12:23 PM

Was This Post Helpful? 0
  • +
  • -

#6 Hapro  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 7
  • Joined: 14-August 12

Re: Multiple Side Collision Detection on Obstacles

Posted 03 March 2013 - 04:13 PM

I only call HandleCollisions() again in case the sprite is still intersecting after the collision is resolved, in which case it will resolve on the next axis. Let me try and explain again:

  • Apply X and Y speeds to your sprites
  • If there is a collision, get the depth of the intersection
  • Add the smallest intersection to the sprites location - this should move the sprite just enough that it isn't intersecting any more.
  • Call HandleCollisions() once more just to make sure.


Therefore, it doesn't matter if you are adding velocity to your sprite, as it should be 'pushed' out of the sprite it is intersecting by the exact amount of pixels.

>My game's gravity forces the player to go through the obstacles since it updates its location.Y faster than the HandleCollision function

You should only be adding velocity to your sprites once per update loop, it should be something like this:
Update()
         Add velocity to sprite location


Was This Post Helpful? 0
  • +
  • -

#7 Hapro  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 7
  • Joined: 14-August 12

Re: Multiple Side Collision Detection on Obstacles

Posted 03 March 2013 - 04:19 PM

View PostHapro, on 03 March 2013 - 04:13 PM, said:

I only call HandleCollisions() again in case the sprite is still intersecting after the collision is resolved, in which case it will resolve on the next axis. Let me try and explain again:

  • Apply X and Y speeds to your sprites
  • If there is a collision, get the depth of the intersection
  • Add the smallest intersection to the sprites location - this should move the sprite just enough that it isn't intersecting any more.
  • Call HandleCollisions() once more just to make sure.


Therefore, it doesn't matter if you are adding velocity to your sprite, as it should be 'pushed' out of the sprite it is intersecting by the exact amount of pixels.

>My game's gravity forces the player to go through the obstacles since it updates its location.Y faster than the HandleCollision function

You should only be adding velocity to your sprites once per update loop, it should be something like this:
Update()
         Add velocity to sprite location



Oops, accidentally posted before finishing - the site won't let me delete the post for some reason >.</>

Anyway as I was saying, your update loop should be something like this
Update()
      {
         Update all sprites
         HanldeCollisions()
      }



I hope that helps. I guess I could post the entire program if you still can't get it to work.
Was This Post Helpful? 0
  • +
  • -

#8 d4rks1027  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 03-April 13

Re: Multiple Side Collision Detection on Obstacles

Posted 03 April 2013 - 06:05 PM

Hi, I found this post to be tremendously helpful as I was attempting to do similar collision. I know this post is about a month old at this point so I doubt i'll get a response but how exactly do you fix the jittering issue? I know you say to draw the sprite without using a vector two, but could you elaborate a bit more as Im a little unclear of what you mean

Thanks!
Was This Post Helpful? 0
  • +
  • -

#9 Hapro  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 7
  • Joined: 14-August 12

Re: Multiple Side Collision Detection on Obstacles

Posted 07 April 2013 - 04:46 AM

View Postd4rks1027, on 03 April 2013 - 06:05 PM, said:

Hi, I found this post to be tremendously helpful as I was attempting to do similar collision. I know this post is about a month old at this point so I doubt i'll get a response but how exactly do you fix the jittering issue? I know you say to draw the sprite without using a vector two, but could you elaborate a bit more as Im a little unclear of what you mean

Thanks!


When you draw the sprite, you should have a Rectangle defined for the bounds (used for collisions) and a Vector2 for accurate movement. So basically, instead of doing:
spritebatch.Draw(texture, location, color);

do this:
spritebatch.Draw(texture, bounds, color)


The collision resolution algorithm isn't perfect, and it keeps adjusting itself by tiny amounts, which causes the jittering. The Rectangle can only take coordinates in integers, which means that only adjustments of 1 coordinate or greater will make the sprite appear to move. This is fine, as the minimum distance a sprite can move on the screen is 1 pixel in any direction. However, you must only apply speed to the Vector2, and then move the bounds to the position of the Vector2 to allow for more accurate processing of movement.

The Rectangle basically rounds the Vector2 coordinates to a whole number, which prevents tiny movements, which in turn prevents the jittering. I hope that helped :)/>/>
Was This Post Helpful? 0
  • +
  • -

#10 d4rks1027  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 03-April 13

Re: Multiple Side Collision Detection on Obstacles

Posted 11 April 2013 - 09:50 AM

View PostHapro, on 07 April 2013 - 04:46 AM, said:

When you draw the sprite, you should have a Rectangle defined for the bounds (used for collisions) and a Vector2 for accurate movement. So basically, instead of doing:
spritebatch.Draw(texture, location, color);

do this:
spritebatch.Draw(texture, bounds, color)


The collision resolution algorithm isn't perfect, and it keeps adjusting itself by tiny amounts, which causes the jittering. The Rectangle can only take coordinates in integers, which means that only adjustments of 1 coordinate or greater will make the sprite appear to move. This is fine, as the minimum distance a sprite can move on the screen is 1 pixel in any direction. However, you must only apply speed to the Vector2, and then move the bounds to the position of the Vector2 to allow for more accurate processing of movement.

The Rectangle basically rounds the Vector2 coordinates to a whole number, which prevents tiny movements, which in turn prevents the jittering. I hope that helped :)/>/>/>



I ended up figuring out the jittering issue, but thanks for the reply :)

Do you know if there's anyway off hand to fine tune the collision a little? Mainly I'm trying to make sure that when my player lands of the very edge of the platform that they stop on it, because right now if he's falling and hits the edge he gets pushed to the side and falls. I'm not sure if this is something that needs to be added in the collision code or my movement code, but any advice would be appreciated :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1