0
\$\begingroup\$

I have a list of game objects I'm trying to check collision against. My collision system is using code ive seen posted here before, but I'm not sure where I'm going wrong here.

 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 I do this.

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

\$\endgroup\$
1
\$\begingroup\$

Make sure you don't check collision against itself.

It is not entirely obvious from the code you posted, but if the player is also part of objectlist it will be part of the collision code and it checks against itself (since it occupies the same space obviously) resulting in 'true'.

Alter your code CheckCollisions like this:

foreach(GameObject obj in objects)
    {
        if(obj==this)
        {
            continue; // Don't check for collisions against self.
        } 

      Vector2 depth;
     ... //do rectangle intersection etc.
    }

That is, I assume the object is included in the collection you pass to this method.

\$\endgroup\$
  • \$\begingroup\$ the player is not part of the object list. I'm able to move the player around just a little bit \$\endgroup\$ – bob saget Aug 24 '16 at 9:49
  • \$\begingroup\$ Do you correct the player position after a collision has occured? So if the player hits the floor, it is moved so it won't collide again the next frame? Have you debugged the positions of the colliding objects or are able to check the names/id or anything that identifies the object causing the collision? \$\endgroup\$ – Felsir Aug 24 '16 at 9:57
  • \$\begingroup\$ the checkCollision method has the line g_woorldPosition += depth should be correcting the position of the player after collision. I hadn't done any kind of debugging with ids of objects yet because I assumed that the collision boxes were all correct, because they were drawn correctly \$\endgroup\$ – bob saget Aug 24 '16 at 10:09
  • \$\begingroup\$ Debug the corrected position, you may need to add a +1 to the collision when going down or right since a 16x16 rectangles is 0 zero based (thus 0-15,0-15) this may affect your position; so after the collision you did a correction but the rectangles still overlap a tiny bit. \$\endgroup\$ – Felsir Aug 24 '16 at 10:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.