add FLOATING case to player's y_axis type, so user hovers briefly after jumping, before gravity is applied (this is normal game physics)

This commit is contained in:
2024-12-14 18:02:57 +00:00
parent cea269689e
commit 62a6a831ed
2 changed files with 52 additions and 16 deletions

4
fcore/game-type.sml Normal file
View File

@@ -0,0 +1,4 @@
structure GameTyoe =
struct
end

View File

@@ -1,6 +1,6 @@
structure Player = structure Player =
struct struct
datatype y_axis = ON_GROUND | FALLING | JUMPING of int datatype y_axis = ON_GROUND | FALLING | JUMPING of int | FLOATING of int
datatype x_axis = MOVE_LEFT | STAY_STILL | MOVE_RIGHT datatype x_axis = MOVE_LEFT | STAY_STILL | MOVE_RIGHT
(* width/height *) (* width/height *)
@@ -9,6 +9,7 @@ struct
val moveBy = 5 val moveBy = 5
val jumpLimit = 150 val jumpLimit = 150
val floatLimit = 5
type t = {yAxis: y_axis, xAxis: x_axis, health: int, x: int, y: int} type t = {yAxis: y_axis, xAxis: x_axis, health: int, x: int, y: int}
@@ -71,6 +72,16 @@ struct
in in
checkWalls (yAxis, xAxis, desiredX, y, health, collisions) checkWalls (yAxis, xAxis, desiredX, y, health, collisions)
end end
| FLOATING floated =>
let
val collisions = QuadTree.getCollisionSides
(desiredX, y, size, size, 0, 0, 1920, 1080, 0, Wall.tree)
val yAxis =
if floated = floatLimit then FALLING else FLOATING (floated + 1)
in
checkWalls (yAxis, xAxis, desiredX, y, health, collisions)
end
| FALLING => | FALLING =>
let let
val desiredY = y + moveBy val desiredY = y + moveBy
@@ -86,7 +97,7 @@ struct
val collisions = QuadTree.getCollisionSides val collisions = QuadTree.getCollisionSides
(desiredX, y, size, size, 0, 0, 1920, 1080, 0, Wall.tree) (desiredX, y, size, size, 0, 0, 1920, 1080, 0, Wall.tree)
in in
checkWalls (FALLING, xAxis, desiredX, y, health, collisions) checkWalls (FLOATING 0, xAxis, desiredX, y, health, collisions)
end end
else else
(* jump *) (* jump *)
@@ -109,23 +120,44 @@ struct
| (true, false) => MOVE_LEFT | (true, false) => MOVE_LEFT
| (true, true) => STAY_STILL | (true, true) => STAY_STILL
fun getYAxis (uh, dh, yAxis) = (* function returns default yAxis when neither up/down are pressed
* or both are pressed.
*
* In the case where the user was previously jumping,
* we enter the floating stage, because it's normal for games
* to have a very brief floating/gliding period before applying gravity.
*
* In the case where the user was previously floating, we want the player to
* keep floating at this point (another function will apply gravity if we
* floated enough).
*
* In every other case, we return the FALLING variant,
* which has the same effect as returning the ON_GROUND variant,
* except that it means gravity is applied if we walk off a platform.
* *)
fun defaultYAxis prevAxis =
case prevAxis of
JUMPING _ => FLOATING 0
| FLOATING _ => prevAxis
| _ => FALLING
(* We want to prevent a double jump
* or jumping while the player is falling
* so we only switch to the JUMPING case if the player
* is on the ground. *)
fun onJumpPressed prevAxis =
case prevAxis of
ON_GROUND => JUMPING 0
| _ => prevAxis
fun getYAxis (uh, dh, prevAxis) =
case (uh, dh) of case (uh, dh) of
(false, false) => (false, false) => defaultYAxis prevAxis
(* default yAxis of FALLING does two things: | (true, true) => defaultYAxis prevAxis
* 1. When player walks off platform, gravity is applied. | (true, false) => onJumpPressed prevAxis
* 2. When player presses up for a short period of time,
* the player makes a shorter jump rather than jumping longer.
* *)
FALLING
| (true, true) => FALLING
| (true, false) =>
(case yAxis of
ON_GROUND => JUMPING 0
| _ => yAxis)
| (false, true) => | (false, true) =>
(* todo: should move down if on platform *) (* todo: should move down if on platform *)
yAxis prevAxis
fun move fun move
({x, y, yAxis, health, ...}: t, {leftHeld, rightHeld, upHeld, downHeld}) = ({x, y, yAxis, health, ...}: t, {leftHeld, rightHeld, upHeld, downHeld}) =