Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have difficulties with the rectangle collision. My character can go through the right side and through the bottom of each platform rectangle. I guess their is a mathematical problem with the collision, but I don't know what is wrong.

What should I change? I want to do a little platformer, something like the old Mario games.

Backgrounds.LevelTilesList is a list of type RectangleF. Every tile in the level is saved in this list.

Vector2 Player_Gravity = new Vector2(0, 4.5f);
Vector2 Player_Movement = new Vector2();
Vector2 Player_Size = new Vector2(29, 80);
System.Drawing.RectangleF Player_RectF = new System.Drawing.RectangleF(100, 100, 29, 80);
System.Drawing.RectangleF Player_NewRect;
bool collisionTop, collisionBottom, collisionRight, collisionLeft;

    protected override void Update(GameTime gameTime)
        KeyboardState currentkeyState = Keyboard.GetState();

        if (currentkeyState.IsKeyDown(Keys.Left))
            Player_Movement.X -= 5;
        if (currentkeyState.IsKeyDown(Keys.Right))
            Player_Movement.X += 5;
        if (currentkeyState.IsKeyDown(Keys.Up))
            Player_Movement.Y -= 10;
        if (currentkeyState.IsKeyDown(Keys.Down))
            Player_Movement.Y += 10;

        Player_Movement += Player_Gravity;
        // Calculate new position
        Player_NewRect = Player_RectF;
        Player_NewRect.X += Player_Movement.X;
        Player_NewRect.Y += Player_Movement.Y;

        // check for collision
        for (int j = 0; j <= Backgrounds.LevelTilesList.Count - 1; j++)
            if (Player_NewRect.IntersectsWith(Backgrounds.LevelTilesList[j]))
                float halfBoxWidth = Backgrounds.LevelTilesList[j].Width * 0.5f;
                float halfBoxHeight = Backgrounds.LevelTilesList[j].Height * 0.5f;
                float halfBoxPlayerWidth = Player_NewRect.Width * 0.5f;
                float halfBoxPlayerHeight = Player_NewRect.Height * 0.5f;

                Vector2 posDiff = new Vector2((int)((Backgrounds.LevelTilesList[j].X + halfBoxWidth) - (Player_NewRect.X + halfBoxPlayerWidth)), (int)((Backgrounds.LevelTilesList[j].Y + halfBoxHeight) - (Player_NewRect.Y + halfBoxPlayerHeight)));
                float maxDiffX = halfBoxWidth + halfBoxPlayerWidth;
                float maxDiffY = halfBoxHeight + halfBoxPlayerHeight;

                collisionTop = posDiff.Y < -halfBoxHeight &&
                                        posDiff.Y > (maxDiffY) * -1
                                        !collisionRight && !collisionLeft;

                collisionBottom = posDiff.Y > halfBoxHeight &&
                                        posDiff.Y < maxDiffY
                                        !collisionRight && !collisionLeft;

                collisionLeft = posDiff.X < -halfBoxWidth &&
                                    posDiff.X > maxDiffX * -1 &&
                                    !collisionBottom && !collisionTop;

                collisionRight = posDiff.X > halfBoxWidth &&
                                        posDiff.X < maxDiffX &&
                                        !collisionBottom && !collisionTop;

                if (collisionTop || collisionBottom)
                    Player_Movement.Y *= -0.5f;
                if (collisionLeft || collisionRight)
                    Player_Movement.X *= -0.5f;

                // Adjust the position
                if (collisionBottom)
                    Player_NewRect.Y -= Player_NewRect.Bottom - Backgrounds.LevelTilesList[j].Top;

                if (collisionTop)
                    Player_NewRect.Y += Player_NewRect.Top - Backgrounds.LevelTilesList[j].Bottom;

                if (collisionLeft)
                    Player_NewRect.X += Player_NewRect.Left - Backgrounds.LevelTilesList[j].Right;

                if (collisionRight)
                    Player_NewRect.X -= Player_NewRect.Right - Backgrounds.LevelTilesList[j].Left;

        Player_RectF = Player_NewRect;
        Player_Movement = new Vector2(0, 0);  
share|improve this question

closed as too localized by Anko, bummzack, msell, Josh Petrie, Byte56 May 9 '13 at 13:30

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

Your question has a lot of code. For better help sooner, post a SSCCE. – Doorknob May 1 '13 at 18:44
Probably related:… – Chaosed0 May 1 '13 at 20:42
up vote 1 down vote accepted

Just to be clear: Per the convention of System.Drawing.RectangleF, rect.Top is a smaller value than rect.Bottom and so "up" is negative y.

Let's consider the case where the intersecting tile's center is above new player rect's center:

posDiff.y is negative.

collisionTop is true.

new player rect's Top is above tile's Bottom, otherwise there'd be no intersection

So, this expression is negative:

Player_NewRect.Top - Backgrounds.LevelTilesList[j].Bottom

So, this code block moves the player up, further into the tile, which is wrong.

if (collisionTop)
    Player_NewRect.Y += Player_NewRect.Top - Backgrounds.LevelTilesList[j].Bottom;

So try flipping the sign on that last line of code. Also, step through the code in the debugger to see if everything I described is correct.

share|improve this answer

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