Advertisement

Collision Detection error

Started by August 24, 2016 08:43 AM
2 comments, last by Nanoha 8 years, 3 months ago

I have a list of game objects I'm trying to check collision against. I've used the Debug class to write to the console and it seems that i'm getting a collision where there is none.


private bool Intersects(Rectangle player, Rectangle other, CollisionDirection direction, out Vector2 depth)
    {
        if (direction == CollisionDirection.Vertical)
        {
            depth = new Vector2(0, GetVerticalIntersectionDepth(player, other));
        }
        else
            depth = new Vector2(GetHorizontalIntersectionDepth(player, other));

        return depth.Y != 0 || depth.X != 0;
    }

    public float GetHorizontalIntersectionDepth(Rectangle rectA, Rectangle rectB)
    {
        float halfWidthA = rectA.Width / 2;
        float halfWidthB = rectB.Width / 2;

        float centerA = rectA.Left + halfWidthA;
        float centerB = rectB.Left + halfWidthB;

        float distanceX = centerA - centerB;
        float minDistanceX = halfWidthA + halfWidthB;

        if (Math.Abs(distanceX) >= minDistanceX)
            return 0;

        return distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
    }

    public float GetVerticalIntersectionDepth(Rectangle rectA, Rectangle rectB)
    {
        float halfWidthA = rectA.Height / 2;
        float halfWidthB = rectB.Height / 2;

        float centerA = rectA.Top + halfWidthA;
        float centerB = rectB.Top + halfWidthB;

        float distanceX = centerA - centerB;
        float minDistanceX = halfWidthA + halfWidthB;

        if (Math.Abs(distanceX) >= minDistanceX)
            return 0;

        return distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
    }

    private void CheckCollisions(CollisionDirection direction, List<GameObject> objects)
    {
        foreach(GameObject obj in objects)
        {
            Vector2 depth;
            if(Intersects(CollisionRectangle, obj.g_CollisionRectangle, direction, out depth))
            {
                g_WorldPosition += depth;
                Debug.WriteLine("true");
                if (direction == CollisionDirection.Horizontal)
                    g_Velocity.Y = 0;
                else
                    g_Velocity.X = 0;
            }
        }
    }

And in my update method.



....
if(ks.IsKeyDown(Keys.S))
        {
            g_WorldPosition.Y += 10f;
            playerFacing = Direction.DOWN;
            CheckCollisions(CollisionDirection.Vertical, objectList);
        }
        if(ks.IsKeyDown(Keys.A))
        {
            g_WorldPosition.X -= 10f;
            playerFacing = Direction.LEFT;
            CheckCollisions(CollisionDirection.Horizontal, objectList);
        }
...

In the CheckCollision method the Debug line is writing true to the output even when i'm not colliding with anything. I know the g_CollisionRectangle is being set correctly because I have lines being drawn around the outside of each collidable object.

What happens is my player kinda moves sporadically because I'm getting collisions in places where I shouldnt. Can anyone see where I'm going wrong here? I realize that g_Velocity is not being used in my update method, but I don't think that it should effect what is happening at this point. From what I can tell, my GetVertical and GetHorizontal methods are wrong somewhere because of the Debug line in the CheckCollision method.

How are g_WorldPosition and CollisionRectangle related? g_WorldPosition is your player position I assume and CollisionRectangle is it's collision rectangle? I don't see any code that is keeping them in sync though, you do change g_WolrdPosition but I don't see anything moving the collision rect. That could potentially be a source of this problem. The lines you draw are only in the correct position when you actually draw them, in between they could be going out of sync, giving you incorrect collision and then being re-synced up before you render your objects again.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Advertisement

Collision Rectangle is just a rectangle with a getter method


        public Rectangle CollisionRectangle
        {
            get
            {
                return new Rectangle(
                    (int)g_WorldPosition.X,
                    (int)g_WorldPosition.Y,
                    g_Texture.Width,
                    g_Texture.Height);
            }
        }

unless I'm using it wrong? I'll put it in the update method and see if that changes anything

Those globals are going to ruin your day. I'm not sure what is causing your exact problem but from looking at your code it is not very good design-wise. I would advice against trying to fix this problem and instead remove all those globals you have, that will then force you to redo how you solve your collision detection/response which should hopefully no longer exhibit the problem you have. It's better to build on a strong foundation now than end up with worse problems later.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

This topic is closed to new replies.

Advertisement