简体   繁体   中英

C# Monogame: “floating” sprite after jumping

I'm currently working on a 2d platformer using Monogame. I can draw a sprite, I can draw a character and level, I can move the character and jump, but when I jump, my character "floats" above the level block in stead of landing on it. The left and right collisions work fine, the character is stopped when it should be stopped, but when jumping it doesn't land properly. I have the following code:

To check if the player wants to jump, a check is performed to see if the up arrow is pressed.

if(state.IsKeyDown(Keys.Up) && hasJumped == false)
{
    jumping = true;
}

After the check for the keypress is done, there's a check to see if the jumping variable is true

if (jumping == true)
{
    jump();
} else if (falling == true && topOfBlock == false)
{
    fall();
}
else
{
    hasJumped = false;
    verticalMovement = 14;
}

Basically jumping checks whether you want to jump, falling checks if the character is falling, topOfBlock checks if the character is on top of a block, hasJumped checks whether a jump is currently in progress (so no double jump is possible) and verticalMovement is the amount of pixels the character jumps/falls per tick.

The jump() and fall() method look as follows:

private void jump()
{
    if (verticalMovement >= 0)
    {
        position.Y -= verticalMovement;
        verticalMovement--;
    } else
    {
        jumping = false;
        hasJumped = true;
        falling = true;
    }
}

public void fall()
{
    position.Y += verticalMovement;
    verticalMovement++;
}

The code speaks for itself I think. Basically if the character is no longer moving up, falling is set to true , which triggers the fall() method, as long as the character isn't on top of a block.

Finally the character's collision rectangle is updated to the new position of the character.

colRect = new Rectangle((int)position.X, (int)position.Y, 64, 48);

Where position.X and position.Y are the character's X and Y position, and 64 and 48 are the sprite's width and height.

To check whether the collision rectangle intersects with the collision rectangle of a block I have the following code

private void checkCollision()
{
    bool topCol = false;
    for (int x = 0; x < blockTileArray.GetLength(0); x++)
    {
        for (int y = 0; y < blockTileArray.GetLength(1); y++)
        {
            if (blockTileArray[x, y] != null)
            {
                if (hero.colRect.Intersects(blockTileArray[x, y].topWall))
                {
                    topCol = true;
                }

            }
        }
    }

    if(topCol == true)
    {
        hero.topOfBlock = true;
    } else
    {
        hero.topOfBlock = false;
    }       
}

topCol is a bool that checks whether there's a collision with the top of the block or not. The loops check for every block in the array whether the character intersects with it's topWall or not. If so, it sets topCol to true. After the loop it it checks whether topCol is true or not. If it is, it says hero.topOfBlock to true , which means the character shouldn't fall. If it's false , it sets hero.topOfBlock to false , which would trigger the fall() method in the Hero class, as long as jumping is false as well.

Lastly, the topWall collision rectangle is created as follows:

topWall = new Rectangle((int)position.X, (int)position.Y - size, size, 1);

position.X and position.Y are the X and Y positions, size is the width and height of the block (both are 30 as it's a square), the 1 is to make it just 1 pixel high.

Now as I said, the problem is that the character floats after jumping. The starting y position is 402 pixels (with the first block's topWall.Y being 420, meaning the character stands on top of the block when the game loads), after jumping it should go back to 402. However; after jumping once, it goes to 374, then 373, then 387, 386, ..., 374, 373, back to 387 again and so on. I have no idea what's causing the problem. I've tried multiple things, like tinkering with the collision rectangles of both the block and character but nothing seems to work. When I remove the - size from (int)position.Y - size in topWall = new Rectangle() (which I thought would be the problem), the character falls through the block, so that doesn't fix it either.

Just to make a bit clearer what I mean, here are two pictures:

When the game loads

After jumping once

You say

"After the loop it it checks whether topCol is true or not. If it is, it says hero.topOfBlock to true, which means the character shouldn't fall."

which corresponds to your if-then conditionals at the top; you don't mention setting the character's Y-coordinate to the top of the tile. I'm not sure if that would cause your issue, it depends on when you call checkCollision, but it's probably part of the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM