2
\$\begingroup\$

I have a collision method where the parameters for the method are the rectangle of the player and a list with the rectangles of the tiles.

I work with booleans like bLeft, bRight,... and this creates a problem if my player collides with two tiles at the same time, then one tile may say True while the other says false.

This is my collision method (NOTE: Very buggy and incomplete collision detection, this is because the reason above)

public override void Collision(Rectangle collisionRect, List<Rectangle> tileCollision)
{

    foreach (Rectangle rect in tileCollision)
    {
        if (collisionRect.Intersects(rect))
        {

            rect2 = Rectangle.Intersect(rect, collisionRect);

            collision = true;
            stopping = true;
            walking = false;

            if (collisionRect.X < rect.X && !(collisionRect.Y <= rect.Y - 50))
            {
                bLeft = true;
            }

            if (collisionRect.X > rect.X && !(collisionRect.Y <= rect.Y - 50)) 
            {
                bRight = true;
            }

            if (collisionRect.Y <= rect.Y - 50)
            {
                bUp = true;
            }

            if (collisionRect.Y >= rect.Y + rect.Height)
            {
                bDown = true;
            }

            if (bLeft && !bRight && !bUp && !bDown)
            {
                fallingTest = false;
                stopping = true;

                if (left)
                {
                    stopping = false;
                    fallingTest = false;
                }
            }

            if (bRight && !bLeft && !bUp && !bDown)
            {
                fallingTest = false;
                stopping = true;

                if (right)
                {
                    stopping = false;
                    fallingTest = false;
                }
            }

            if (bUp)
            {
                ground = true;
                fallingTest = true;
                stopping = false;

                if (moving)
                {
                    walking = true;
                }

                if (bLeft && bUp)
                {
                    stopping = true;

                    if (left)
                    {
                        stopping = false;
                    }
                }

                if (bRight)
                {
                    stopping = true;

                    if (right)
                    {
                        stopping = false;
                    }
                }
            }

            if (bDown && !bRight && !bLeft && !bUp)
            {
                stopping = true;
                fallingTest = false;

                if (moving)
                {
                    walking = true;
                }
            }
        }

        if (!(tileCollision.Any(c => collisionRect.Intersects(c))))
        {
            collision = false;
            fallingTest = false;
            stopping = false;

            ground = false;

            if (moving)
            {
                walking = true;
            }
        }
    }
}

So I basically need a line of code that counts the colliderboxes that the player collides with at the moment of collision. I tried doing this by adding 1 to the variable collisionBoxes but this results in doing +1 each frame (because this collision method is called in Update)

I also use rect2 for visual overlapping of the player collision box and the tile collision box, but when the player touches more than one tile, then the rect2 only shows on one tile. This is because I use the foreach but I tried using a list to store the overlapping rectangles in but it didn't work.

One more question, should I use all these booleans? Because I don't know how to handle them if more than one block touches the player (all the tiles are checking for the booleans, resulting in bugs).

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

I would make the change to deal with the collision itself outside the collision loop. Let each gameobject itself handle the collision result. Also if the object has been updated because a collision occurred, the collision rectangle might have been updated as well. Your current code is very foc

public void HandleCollisions(PlayerObj p, List<Tiles> tiles)
{
    foreach(Tile t in tiles)
    {
        if(p.CollisionRectangle.Intersects(t.CollisionRectangle))
        {
            p.HandleCollision(t);
            t.HandleCollision(p);
        }
    }
}

The player:

public void HandleCollision(Tile t)
{
    //Handle the collision. 
    //Move the player out of collision position (stop falling etc.) 
    //Update the collision rectangle.
}

Since you update the player after each collision, it will only handle collisions that are relevant. So if for example your player is falling down and is halfway two tiles, the collision with the first tile will move the player on top of the floor. The second collision will not happen.

Now the tile:

public void HandleCollision(PlayerObj p)
{
   // perhaps this tile is a lava tile?
   if(this.Type = Tiletype.Lava)
      p.DoDamage(10);
   // perhaps this is a breakable tile?
   if(this.Type = Tiletype.Breakable)
      this.Collapse();
}

In this example you can have side effects for each tile as well. This saves you from adding another bunch of tests/booleans elsewhere after the collisions.

\$\endgroup\$
4
  • \$\begingroup\$ Thank you, I will try this as soon as possible! But are the HandleCollision methods implemented in different classes, like a Player and Tile class ? (I have these classes) \$\endgroup\$
    – Jelle
    Commented Nov 29, 2015 at 21:15
  • \$\begingroup\$ The player and tile classes have the handlecollision methods. \$\endgroup\$
    – Felsir
    Commented Nov 29, 2015 at 21:29
  • \$\begingroup\$ Do I still need booleans to "move the player out of collision position"? Because I don't know how to do it without booleans (for example when there is a block next to you and under you). \$\endgroup\$
    – Jelle
    Commented Nov 30, 2015 at 16:22
  • \$\begingroup\$ No you wouldn't. In your example (next to you, under you) first the tile next to you would be resolved- the player character will be pushed out the tile. So position and collision rectangle is updated. Now the for loop continues, the tile below triggers a collision and the player is pushed upwards out of that collision. This is how collisions are resolved in order. \$\endgroup\$
    – Felsir
    Commented Nov 30, 2015 at 17:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .