Tile Collisions, Slopes & You
One of the first things I wanted to tackle on the game was the tile collision system. In Take Arms, we used a polygon based collision system powered by a heavily modified Box2D collision engine. The platforming used raycasts shot downward to find the ground and pull you down, while SAT was run to push your polygon out of the ground. We used a strange half-diamond shape polygon for the hitbox so it wouldn’t collide with slopes. This system worked OK, but it came with a lot of overhead.
Since this next game is going to be pixel based, I decided to go a more old school approach. First, I made a TileCollisionType enum that describes a tiles collision properties. For instance, a tile can be Empty, Solid, GroundHalfSolid, Ground45Left, etc. You then need to make a tile sheet with each of those variations in the same order as your enum. When you load up your game, load the texture into memory and parse each of the tiles out into a bool[,] collision mask with the bool specifying if the pixel is filled. When you want to check a pixel in-game, figure out what type of tile it’s in, then consult a Dictionary<TileCollisionType, bool[,]> for the collision mask itself. The associated bool[,] will tell you if that point, when translated to the local tile coords, is a hit or not.
Normal Solid tile collisions are easy enough to handle: use a hotspot on the bottom of the player, and if it is colliding with a tile mask then set the player on the ground. If not, they’re falling. The difficulty always comes with the slopes though! There’s a few key things I did to make this method work smoothly:
- Separate your horizontal movement collision checks from the vertical. In the image above, the green lines designate the points to check for walls when you’re moving left or right.
- The red point below the players feet is the ground “hotspot”. For slopes, you either need to push the player up out of the slope when walking upwards, or pull him down constantly onto it when walking downwards. The former is easy to correct, just search upwards from your hotspot until you find an open position. For moving down slopes, check if you’re still in the walking state, and if your hotspot is in a slope tile. If so, loop downwards til you find the first hit, and then correct player’s position as usual.
- You don’t want your “wall check” raycasts (green lines in above picture) interfering with your slopes. The first secret is to completely ignore sloped tiles when doing those checks. That will fix getting stuck on them most of the time, but there’s still the case where a Solid tile sitting beside a slope catches your raycast. The trick here is to pre-process the tile map, and flag those Solid tiles to not be checked for horizontal movement in that direction. These tiles are marked on the image with the yellow arrows.
- Lastly, check your head for collisions with the yellow dot.
You’ll obviously need some extra checks for when you’re walking off cliffs or other situations, but it should be relatively trivial once you get the basics working. If you have any questions or suggestions, please let me know!