Collisions working almost perfectly

So i managed to get collisions working on my game… almost. The thing is for some reason, i don’t know why, the game is only getting the rectangles collision in one object. For example: i have 5 trees in my map but the collision work only with one tree.

The second thing is: I can’t figure out how to make my character stop moving. I know the collisions are working because i made the sprite change it’s frame on collision, but i didn’t figured it out how to make the player stop moving in that direction and being able to go back, for example. Can anyone help shine a light in these aspects?

Here’s my player class:

    class Player
{
    private Vector2 position = new Vector2(880, 410);
    private int speed = 150;
    private int speedRun = 200;
    private Dir direction = Dir.Down;
    private bool isMoving = false;
    private KeyboardState kStateOld = Keyboard.GetState();
    public bool dead = false;
    public Rectangle playerLimits;

    public SpriteAnimation anim;
    public SpriteAnimation[] animationsPlayer = new SpriteAnimation[8];

    public Vector2 Position
    {
        get { return position; }
        set { position = value; }
    }

    public void setX(float newX)
    {
        position.X = newX;
    }

    public void setY(float newY)
    {
        position.Y = newY;
    }

    public void Update(GameTime gameTime)
    {
        float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
        KeyboardState kState = Keyboard.GetState();

        isMoving = false;

        /*            if(isMoving && dead == false)
                    {

                    }*/
        if (kState.IsKeyDown(Keys.Right))
        {
            direction = Dir.Right;
            position.X += speed * dt;
            isMoving = true;
        }

        if (kState.IsKeyDown(Keys.Left))
        {
            direction = Dir.Left;
            position.X -= speed * dt;
            isMoving = true;
        }

        if (kState.IsKeyDown(Keys.Up))
        {
            direction = Dir.Up;
            position.Y -= speed * dt;
            isMoving = true;
        }

        if (kState.IsKeyDown(Keys.Down))
        {
            direction = Dir.Down;
            position.Y += speed * dt;
            isMoving = true;
        }

        playerLimits = new Rectangle((int)position.X,(int)position.Y,32,32);
        playerLimits.X = (int)position.X;
        playerLimits.Y = (int)position.Y;

        anim = animationsPlayer[(int)direction];
        anim.Position = new Vector2(position.X - 16, position.Y -16);
        kStateOld = kState;

        if (isMoving)
        {
            anim.Update(gameTime);
        }

        else
        {
            anim.setFrame(2);
        }
    }
}

My collision detection is in my mapa.cs file:

public bool CollideWithPlayer(int index, Rectangle position)
{
    Rectangle limites = objects[index].Limites;

    for (int i = 0 ; i <= GetListLenght(); i++)
    {
        if (limites.Intersects(position))
        {
            return true;
        }
    }
    return false;
}

And i call it in my update method in my Game1.cs:

            if (mapa.CollideWithPlayer(mapa.GetListLenght(), player.playerLimits))
        {
            player.anim.setFrame(2);
        }

Hey @Ozzy,

based on your code you could do the following for collision based movement of your player:

  • Make Dir direction public
  • Add bools for locking the directions. (e.g. LockDirUp)
  • Check the direction in the collision detection:
if (mapa.CollideWithPlayer(mapa.GetListLenght(), player.playerLimits))
{
    if (player.direction == Dir.Up) player.LockDirUp = true;
    player.anim.setFrame(2);
}
  • Check for locked directions in your player update:
if (!LockDirUp && kState.IsKeyDown(Keys.Up))
{
    direction = Dir.Up;
    position.Y -= speed * dt;
    isMoving = true;
}
  • This locks the player movement on collision. But remember that you need to unlock his movement possibilities as soon as it is possible to move into a previously locked direction again.

Hope this helps a little bit.

1 Like

Hey, thanks for your help! I understand your logic but for some reason it doesn’t work, my if statement doesn’t check for the direction correctly i think.

                if (player.direction == Dir.Up) { player.lockDirUp = true; player.anim.setFrame(2); }
            if (player.direction == Dir.Down) { player.lockDirDown = true; player.anim.setFrame(2); }
            if (player.direction == Dir.Right) { player.lockDirRight = true; player.anim.setFrame(2); }
            if (player.direction == Dir.Left) { player.lockDirLeft = true; player.anim.setFrame(2); }

It’s like this, but the player keeps moving easily. If i do player.lockDirUp = true outside of the if statement, it works. But the problem is that this way i can’t lock the right direction only.

Couldn’t find out yet also why is the collision only working with one object and not all the spawned objects from my Objects class

Try do place some breakpoints on code which doesn’t work as expected, so we can see what is going on.

For example:

if (player.direction == Dir.Up) //breakpoint here
{ 
    player.lockDirUp = true; 
    player.anim.setFrame(2); 
} 

Then move your player up to collide with something.

Also check if all collidables are in the list. Probably this one Rectangle limites = objects[index].Limites; Place a breakpoint there an take a look at the list.

Are you using MonoGame.Extended and Tiled?

I’m not using Monogame.Extended nor Tiled, didn’t knew of those until now hehe just regular monogame!

Also i didn’t knew about visual studio “breakpoint” feature, i think i lack a little visual studio knowledge but i think this will help me a lot, thanks for bringing it out!

1 Like

Oh, good that I have asked, hehe.

Yeah, you will see that breakpoints are very important when developing stuff like this. Knowing how to debug your project is a big need and you should do it very frequently. At least it will make everything alot easier.

1 Like

The thing is my direction when i’m running with the player have another name and i was able to see it thanks to the breakpoint:

So after the changes the collision worked well. I did it like this:

                if (player.direction == Dir.Up || player.direction == Dir.UpRun) { player.lockDirUp = true; player.anim.setFrame(2); }
            if (player.direction == Dir.Down || player.direction == Dir.DownRun) { player.lockDirDown = true; player.anim.setFrame(2); }
            if (player.direction == Dir.Right || player.direction == Dir.RightRun) { player.lockDirRight = true; player.anim.setFrame(2); }
            if (player.direction == Dir.Left || player.direction == Dir.LeftRun) { player.lockDirLeft = true; player.anim.setFrame(2); }

And to reset it to default, i just did this in my Player class:

            if (!lockDirRight && kState.IsKeyDown(Keys.Right))
        {
            direction = Dir.Right;
            position.X += speed * dt;
            isMoving = true;
            lockDirLeft = false;
            lockDirDown = false;
            lockDirUp = false;
        }

        if (!lockDirLeft && kState.IsKeyDown(Keys.Left))
        {
            direction = Dir.Left;
            position.X -= speed * dt;
            isMoving = true;
            lockDirDown = false;
            lockDirRight = false;
            lockDirUp = false;
        }

        if (!lockDirUp && kState.IsKeyDown(Keys.Up))
        {
            direction = Dir.Up;
            position.Y -= speed * dt;
            isMoving = true;
            lockDirLeft = false;
            lockDirDown = false;
            lockDirRight = false;
        }

        if (!lockDirDown && kState.IsKeyDown(Keys.Down))
        {
            direction = Dir.Down;
            position.Y += speed * dt;
            isMoving = true;
            lockDirLeft = false;
            lockDirRight = false;
            lockDirUp = false;
        }

This way i’m reseting the directions lock to false everytime i’m moving, except for the direction i’m moving at the time.

Have to figure out now about the collision working in only one object, gonna find out how to see the list details in the visual studio debugger, so thanks a lot for the help!

1 Like

See my post here for my explanation of how to do simple 2D axis-aligned bounding box collisions. AABB means rectangles represent hitboxes, and the rectangles don’t rotate.

Edit: I should clarify, my post is about responding to collision after detecting it. Detecting AABB collision is as simple as rectangle.Intersects(otherRectangle);

Thank you! I’m gonna read it, i appreciate your help!

Thank you for your link, i have to study your code a bit to get a full understandment of it, but it seems very flexible! I choose to make my own collision detection working nice, which is far from perfect, but i’m trying to make it a little better studying other codes (like yours). Just wanted to say thanks again as i’m here studying your code, thank you and thanks to @BlizzCrafter once again!

2 Likes