Player Moves Into the Tile on Collision

Hello, I’ve been trying to fix collision detection for quite a few days but I can’t figure it out. The player moves into the tile and stops instead of stopping right on the tile.
newww

I’ve seen that the higher the player jumps the further the player moves into the tile and stops.

Thank you for your attention.

I was about to answer in your other thread about the collision issue, but I’ll just answer here instead.

You’ll have to provide your whole collision-checking- and collision-resolving code. Don’t leave any code out. Me, or somebody else on this forum, shouldn’t have to guess what the code does because some code are missing etc.

If there’s a lot of code, in multiple files, you might want to upload the project to github or similar.

Looks like you are detecting collisions alright. Now the problem is to resolve the collision (e.g. move the object so that it doesn’t collide). That’s often the difficult part.

I’ve uploaded the code on github

Ok, so it looks like there is something wrong with the collision detection after all…

This test left >= right checks if the left side of the tile is to the right of the right side of the tile (or touching) which will never be true. What you actually want to test is something else.

Fixing this issue will not prevent the player from going inside the tile but it will fix another bug that prevented the player from falling down on the right side of the tile.

Oh, it jumps to the right too now, thanks!

What’s wrong with the collision tho, why is the player moving into the tile?

Because the collision is not detected until the player has moved into the tile and that’s when you stop the downward motion.

How do i detect collision exactly when it touches the tile? Doesn’t SDL_HasIntersection() do that for us?

The SDL_HasIntersection function indeed tells if there was an actually intersection/collision between the two passed in SDL_Rect’s, but it doesn’t manipulate the two SDL_Rect’s in any way, like moving them apart etc.

So you have two choices here:

  1. Manually calculate how much the two SDL_Rect’s intersect/collide and move the player out of the tile that amount.
  2. Use a built-in SDL function to give you the intersection-amount. There’s a function called SDL_IntersectRect that will do just that.
    This function, just like SDL_HasIntersection, won’t manipulate the passed in SDL_Rect’s either, but it will tell you if there was an intersection/a collision and also give you the amount that the two SDL_Rect’s intersect/collide.
    The third argument in the function takes a pointer to an SDL_Rect that will receive the intersection amount.

Code example:

SDL_Rect intersection = {0, 0, 0, 0};
if(SDL_IntersectRect(&tileRect, &playerRect, &intersection) == SDL_TRUE)
{
	// Collision occurred, move the player out in the correct direction

	// If the player moves to the right
	if(rightK)
		playerPosition -= intersection.w;

	// If the player moves to the left
	else if(leftK)
		playerPosition += intersection.w;
}
1 Like

SDL_HasIntersection doesn’t know anything about the context. It just takes the two rectangles that you pass to it and checks whether they overlap or not.

The problem is that games are not updated contiguously. Instead they are updated in steps. In one frame the player might be a distance away from the tile only to end up inside the tile on the next update. This is something that you’ll have to deal with.

Personally I find collision handling to be one of the more difficult parts in making a game. It really requires some deep thinking, at least for me.

It was a long time since I did a platform game, so I might be overlooking something, but what I think you should do is move the player outside the tile when you detect a collision. For example if you detect that the player is colliding with a tile from above then you could place the player on top of the tile by doing: player.y = tile.y - player.h; (untested pseudocode!) assuming coordinates refer to the top-left corner.

The really tricky part is to decide in which direction to move the player…

1:
If the player can only collide from the top (and move through the tile from below) then I guess you just have to compare the previous position of the player and see if it it was above (or check if the y-velocity is positive).

2:
If the player can collide with the tiles from all four sides, but with no tiles next to each other, then you might be able to get away with just looking at which side is closest or which direction the player is moving in to decide which direction to move the player.

3:
If the tiles can be right next to each other then it becomes a bit more tricky, but if the tiles are never smaller than the player (meaning the player will never overlap more than four tiles) then you can use a trick. Instead of checking collisions against the whole player rectangle you can instead check each corner of the player’s rectangle against all tiles.

  • If the two left corners collide then move the player to the right.
  • If the two right corners collide then move the player to the left.
  • If the two bottom corners collide then move the player up.
  • If the two top corners collide then move the player down.

If only one corner collides then you can use closest side or direction as I mentioned in (2).

I have done something like this in the past but I’m unsure about the details. It’s very much possible that I have overlooked something or made a mistake. If you decide to do something like this you will have to make sure you understand (don’t just copy) and think about the details so that they make sense.

1 Like

Thank you for your help Daniel1985 and Peter87! The player doesn’t sink into the tile anymore. I will try to come up with collision from all sides for the tile. For now player can stand on tile only if he’s falling from above.