I spent most of today getting sloped surfaces and moving platforms working with the new movement and collision code.
The first approach I tried was to extend my existing collision detection code to automatically figure out how to move up and down a slope. I spent a few hours struggling with this, coming up with lots of implementations that were almost right, but they all ended up having nasty edge cases or needing stupid hacks to work correctly. Even worse, they complicated the normal motion and collision detection code in ways I didn’t like (though one cute side effect was that the player character began naturally sliding down slopes when he stood still… heh.)
So after some prodding from a couple people on IRC, I tried to solve this problem a different way. I changed the representation of my level geometry to distinguish between different types of polygons – LevelGeometry objects became LevelTriangles and LevelRectangles. Then I did a bit of work to enable a LevelTriangle to automatically figure out which of its sides is the sloped one. Once I had those two things, it was straightforward to change the movement code:
- Every frame, check to see if the player is standing on a piece of geometry.
- If the player is standing on a piece of geometry, call its ComputeStandingY method and pass in the player’s new position (the player’s current position plus his current velocity) and width. The method will return a new Y coordinate for the player.
- Apply the new Y coordinate to the player’s current position.
- Perform motion and collision detection as usual. The previous ComputeStandingY call already took into account the player’s intended velocity and selected an appropriate Y coordinate for him, so he won’t intersect with the surface he’s walking on.
Once I figured out how to do this, it actually was really simple to code and worked just about right. There were a couple key details, though:
- You need to make sure to take into account the width of the player. The right math for this on a sloped surface turned out to be something like: (playerWidth / slopeWidth) * (slopeMaximumY – slopeMinimumY). That knocks the player up just enough so that his left and right edges don’t intersect with the slope, so that motion is smooth and it still looks more or less like he’s standing on the surface.
- The order of these operations matters a little bit. If you do the slope correction after doing motion and collision detection, you get glitchy movement because the player will intersect with the slope and then get moved up onto it, repeatedly.
- Determining exactly where the player is standing can be a little tough. I’m using my normal collision detection code to do it and just offsetting the player’s Y by a couple pixels to see what’s below him. It more or less works, but I don’t think it’s the correct solution.
Much simpler than the previous solution I had, for sure, and it looks a bit nicer too since a lot of the glitchiness is gone.
Once I had this solution in place, moving platforms were really easy. Moving platforms are level geometry just like anything else, so they can have their own implementation of ComputeStandingY that ensures the player is standing right on top of them while he’s riding them. The only other missing detail is making the player automatically move along with the platform while he’s riding it. That turned out to be simple; you just add a step at the end of the existing algorithm:
- …
- Perform motion and collision detection as usual. The previous ComputeStandingY call already took into account the player’s intended velocity and selected an appropriate Y coordinate for him, so he won’t intersect with the surface he’s walking on.
- If the surface the player is standing on is moving, add the surface’s velocity to the player’s current position.
Note that we do this after doing motion and collision detection – this is important for vertical platforms. If you do it before, the collision detection will sometimes prevent the player from moving with the platform, and he’ll get stuck. Also note that this has the downside of allowing a platform to push the player through a solid wall or other obstacle; I don’t consider this a problem for my implementation, and there are ways you could solve it.




