Search code examples
xnatile

XNA Falling through tiles after jumping


I discovered a lot of new info since I posted this question so I have completely rewritten it:

I have run into some problems while implementing gravity and jumping in my tile-based game. Sometimes when my character lands between tiles after a jump, the characters falls through them.

The problem certainly is not that my speed is too high since my max speed is the same as my tile-size. Also, the problem does not occur after every time the character jumps. I can often make a jump, get to max velocity, and still land well. But sometimes the character just falls through.

My level exists of layers of tiles. Each layer has it's own collision-type. So every tile in the same layer, follows the same rules for collision. In my current set-up all layers use per-pixel collision.

This is how I update the player coordinates http://pastebin.com/qVc6gv6T

This is the class where I calculate my collissions. http://pastebin.com/7GqrFih6

In the update I just do:

    controls.Update(player); 
    physicsEngine.HandleCollissions(levelManager, player);

I imagine that the problem could be because the player gets moved to another tile after collission. Collides with the other tile. But that doesn't count since the other tile already has been checked for collision? Or could it be because I use foreach instead of for-loops?


Solution

  • You say the error occurs after jumping. So, your character falls toward a tile (has some positive velocity.Y) and hits it. The collision code executes the // the player comes FROM ABOVE and collides with the tile block. You run a loop that sets player velocity to zero and moves the player out of collision. This loops calls a function using a term tile as an argument. I assume you loop through a set of tiles in order to collide with more than a single square. Am I right?

    If I am, then the problem occurs after that first collision and correction. Now your player has a velocity.Y of 0, but they are colliding with a new tile. So in spite of your comment about the meaning of your else block, you may have more position changes happening:

    if (player.Velocity.Y > 0) 
    else // if (moveVector.Y < 0) // what you commented
    
    else // if (moveVector.Y <= 0) // what your else really means
    

    Now sometimes (only when you have slightly mis-alligned per-pixel collisions) you have course corrections happening the the wrong direction. That would produce a fall-through effect. You could try setting a break point in the // the player comes FROM UNDER and collides with the tile block, and then running the program in a scenario that shouldn't cause player.WorldPositionY += 1; to happen. If it happens when it wasn't supposed to, then you have your culprit.

    I am doing a lot of speculation here. I think you should post more code so that we can know for sure. But perhaps a paste bin would be appropriate place for it.