Jumping adds verticality to character movement.
A jump action gives a character an initial upwards velocity. The vertical velocity is added to the player’s movement vector and then decremented by gravity each game tick. Eventually the velocity will turn negative and the character will go from moving upwards to downwards, resulting in a parabolic motion.
We set a grounded flag on each character to indicate whether they are grounded or airborne. When a character begins jumping their grounded state is set to false.
Depending on whether a character is grounded or not will change the character’s movement logic when it comes to snapping. If a character starts grounded, moves laterally, and ends up in the air, we will want to check if they can snap downwards so that they stick to slopes or stairs. When not grounded, such as when jumping or falling, we skip any downwards snapping checks so as to not cut short any vertical trajectories.
What happens if a character intersects a surface while airborne? Here we make a distinction based on whether the character is moving upwards or downwards. If there is an intersection while the character is moving downwards, we snap the character up to the surface and set their grounded state to true. If, however, the character is moving upwards, we do not snap the character up. This avoids popping the character up through the surface and zeroing out any upward velocity. It also allows for one-way platforms.
One-way platforms are those which allow characters to pass through when moving upwards. While our airborne snapping strategy already supports one-way platforms, there is one more case we’d like to consider. When a character intersects a one-way platform at the apex of their jump, the character will snap to the platform on the next tick. This is not what we want. Instead we’d like to only snap to the platform if the character was previously above the platform.
We add this condition to our existing snapping criteria. If a character is moving downwards and intersects a surface, we only consider the triangles that were previously below the character to snap up to. We compute the closest point on each triangle to the previous character position. We compute the dot product of the direction vector formed by the closest point to the character and world up. If the result is greater than zero, we know that the character was previously above this triangle. We consider only these triangles for snapping up.