Player only landing on the last platform added.

Hi! So here’s the problem. I have a list of platforms, and a list of players. When I, the first and only player added, jump onto the last added platform, it lands perfectly. Right? Then, if I jump on ANY of the previous platforms before the last one, it just slowly sinks through, but the fourth(last) platform is landed on perfectly, for some reason(I can confirm it’s the last platform by adding only two platforms and testing the second and first).

Here’s the important source code:

protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        playerSprite = Content.Load<Texture2D>("sprite");
        platformSprite = Content.Load<Texture2D>("platform");
        Platforms.Add(new platform(platformSprite, new Vector2(30, 400)));
        Platforms.Add(new platform(platformSprite, new Vector2(350, 300)));
        Platforms.Add(new platform(platformSprite, new Vector2(700, 350)));
        Platforms.Add(new platform(platformSprite, new Vector2(900, 350)));
    }




protected override void Update(GameTime gameTime)
    {
      if (Players.Count < 1)
        {
            player player = new player(playerSprite, "Jimmy", 1, 1, font);
            Players.Add(player);
         }
   foreach(player player in Players)
        {
            player.Update(gameTime);

            foreach (platform platform in Platforms)
            {
                platform.Update(gameTime);
                if (player.hitbox.Intersects(platform.hitbox))
                {
                    player.Velocity.Y = 0f;
                    player.hasJumped = false;
                }
                else
                {
                    player.hasJumped = true;
                }
               
            }
        }





static class RectangleHelper
{
const int penetrationMargin = 5;
public static bool isOnTop(this Rectangle r1, Rectangle r2)
{
    return (r1.Bottom >= r2.Top - penetrationMargin &&
        r1.Bottom <= r2.Top + (r2.Height/2) &&
        r1.Right >= r2.Left + 5 &&
        r1.Left <= r2.Right - 5);
}

}

Here’s the code for player.cs:

if (k.IsKeyDown(Keys.W) && hasJumped == false)
        {
            Position.Y -= 10f;
            Velocity.Y = -5f;
            hasJumped = true;
        }
        if (hasJumped == true)
        {
            float i = 1;
            Velocity.Y += 0.15f * i;
        }
        if (hasJumped == false) 
        {
            Velocity.Y = 0f;
        }

And platform.cs:

           hitbox = new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height); //it's a Rectangle

So yeah, I don’t know what’s wrong. Any solutions? Thanks for reading! And I got this code from: https://www.youtube.com/watch?v=TlHSNjeND9s

If you need any more context or more source code, let me know, please and thank you.

How does it go if player.Update(gameTime) appears after the foreach platform block?

Um what do you mean? It’s not after it, it’s before it.

foreach (platform platform in Platforms)
{
    platform.Update(gameTime);
    if (player.hitbox.Intersects(platform.hitbox))
    {
        player.Velocity.Y = 0f;
        player.hasJumped = false;
    }
    else
    {
        player.hasJumped = true;
    }
   
}

Think about what happens if the player collides with the first platform, but not the second one. The first iteration of the for loop will do

player.Velocity.Y = 0f;
player.hasJumped = false;

The second one will do

player.hasJumped = true;

So the end result will be that Velocity.Y of player will be 0 and hasJumped will be true. On the next player.Update

if (hasJumped == true)
{
    float i = 1;
    Velocity.Y += 0.15f * i;
}

(and I’m guessing it will add that velocity to the position of the player in Update too)
will be executed because hasJumped is set to true the previous update. This will move your player down a bit. Then the same thing will happen again and again until your player fell completely through the platform. If you debug the code it shouldn’t be too hard to figure out yourself. If you don’t have overlapping platforms the easiest solution would be to break when the player intersects with a platform

if (player.hitbox.Intersects(platform.hitbox))
{
    player.Velocity.Y = 0f;
    player.hasJumped = false;
    break;
}

You don’t use RectangleHelper.isOnTop() anywhere, so not sure why that was included.

I would try changing this to

if (player.hitbox.Intersects(platform.hitbox))
{
    player.Velocity.Y = 0.0f;
    player.hasJumped = false;
    // Make sure the player is on top of the platform
    player.Position.Y = platform.hitbox.Top;
}
else
{
    player.hasJumped = true;
}

This will ensure the player is always on top of the platform, regardless of drift or inaccuracies in position calculation.

Yep, I quickly checked out the video and you can see this problem there as well.

Thank you, this worked for me. Thanks to everyone else too who tried helping. :slight_smile: good night.