2024-12-09 04:37:40 +00:00
|
|
|
structure Player =
|
|
|
|
|
struct
|
2024-12-15 09:10:19 +00:00
|
|
|
open GameType
|
2024-12-09 04:37:40 +00:00
|
|
|
|
|
|
|
|
(* width/height *)
|
|
|
|
|
val size = 35
|
2024-12-13 22:48:34 +00:00
|
|
|
val realSize = 35.0
|
2024-12-09 04:37:40 +00:00
|
|
|
|
|
|
|
|
val moveBy = 5
|
2024-12-19 03:58:37 +00:00
|
|
|
|
2024-12-13 22:48:34 +00:00
|
|
|
val jumpLimit = 150
|
2024-12-14 18:11:59 +00:00
|
|
|
val floatLimit = 3
|
2024-12-19 07:53:31 +00:00
|
|
|
val recoilLimit = 15
|
2024-12-20 07:55:10 +00:00
|
|
|
val attackLimit = 55
|
2024-12-09 04:37:40 +00:00
|
|
|
|
2024-12-20 17:41:21 +00:00
|
|
|
fun mkPlayer
|
|
|
|
|
( health, xAxis, yAxis, x, y
|
|
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing
|
|
|
|
|
) =
|
2024-12-14 21:05:51 +00:00
|
|
|
{ yAxis = yAxis
|
|
|
|
|
, xAxis = xAxis
|
2024-12-19 04:09:03 +00:00
|
|
|
, recoil = recoil
|
2024-12-20 07:38:41 +00:00
|
|
|
, attacked = attacked
|
2024-12-20 17:41:21 +00:00
|
|
|
, facing = facing
|
2024-12-14 21:05:51 +00:00
|
|
|
, health = health
|
|
|
|
|
, x = x
|
|
|
|
|
, y = y
|
|
|
|
|
, jumpPressed = jumpPressed
|
|
|
|
|
}
|
2024-12-09 04:37:40 +00:00
|
|
|
|
2024-12-20 17:41:21 +00:00
|
|
|
fun checkWalls
|
|
|
|
|
( yAxis, xAxis, x, y, health
|
|
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, lst, game: game_type
|
|
|
|
|
) =
|
2024-12-09 04:37:40 +00:00
|
|
|
let
|
2024-12-13 22:48:34 +00:00
|
|
|
open QuadTree
|
|
|
|
|
in
|
|
|
|
|
case lst of
|
|
|
|
|
(QUERY_ON_LEFT_SIDE, wallID) :: tl =>
|
|
|
|
|
let
|
2024-12-15 09:10:19 +00:00
|
|
|
val {walls, ...} = game
|
|
|
|
|
val {x = wallX, width = wallWidth, ...} =
|
|
|
|
|
Vector.sub (walls, wallID - 1)
|
|
|
|
|
|
2024-12-13 22:48:34 +00:00
|
|
|
val newX = wallX + wallWidth
|
|
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
checkWalls
|
|
|
|
|
( yAxis, xAxis, newX, y, health, jumpPressed
|
2024-12-20 17:41:21 +00:00
|
|
|
, recoil, attacked, facing, tl, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-13 22:48:34 +00:00
|
|
|
end
|
|
|
|
|
| (QUERY_ON_RIGHT_SIDE, wallID) :: tl =>
|
|
|
|
|
let
|
2024-12-15 09:10:19 +00:00
|
|
|
val {walls, ...} = game
|
|
|
|
|
val {x = wallX, width = wallWidth, ...} =
|
|
|
|
|
Vector.sub (walls, wallID - 1)
|
|
|
|
|
|
2024-12-13 22:48:34 +00:00
|
|
|
val newX = wallX - size
|
|
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
checkWalls
|
|
|
|
|
( yAxis, xAxis, newX, y, health, jumpPressed
|
2024-12-20 17:41:21 +00:00
|
|
|
, recoil, attacked, facing, tl, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-13 22:48:34 +00:00
|
|
|
end
|
|
|
|
|
| (QUERY_ON_BOTTOM_SIDE, wallID) :: tl =>
|
|
|
|
|
let
|
2024-12-15 09:10:19 +00:00
|
|
|
val {walls, ...} = game
|
|
|
|
|
val {y = wallY, ...} = Vector.sub (walls, wallID - 1)
|
|
|
|
|
|
2024-12-13 22:48:34 +00:00
|
|
|
val newY = wallY - size
|
|
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
checkWalls
|
|
|
|
|
( ON_GROUND, xAxis, x, newY, health, jumpPressed
|
2024-12-20 17:41:21 +00:00
|
|
|
, recoil, attacked, facing, tl, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-13 22:48:34 +00:00
|
|
|
end
|
|
|
|
|
| (QUERY_ON_TOP_SIDE, wallID) :: tl =>
|
2024-12-20 07:38:41 +00:00
|
|
|
checkWalls
|
|
|
|
|
( yAxis, xAxis, x, y, health, jumpPressed
|
2024-12-20 17:41:21 +00:00
|
|
|
, recoil, attacked, facing, tl, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-17 22:45:58 +00:00
|
|
|
| [] =>
|
2024-12-20 17:41:21 +00:00
|
|
|
mkPlayer
|
|
|
|
|
( health, xAxis, yAxis, x, y
|
|
|
|
|
, jumpPressed, recoil, attacked, facing
|
|
|
|
|
)
|
2024-12-17 22:45:58 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
fun helpCheckPlatforms
|
|
|
|
|
( yAxis, xAxis, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing
|
2024-12-19 03:58:37 +00:00
|
|
|
, platList, wallList, game
|
2024-12-17 22:45:58 +00:00
|
|
|
) =
|
|
|
|
|
let
|
|
|
|
|
open QuadTree
|
|
|
|
|
in
|
|
|
|
|
case platList of
|
|
|
|
|
platID :: tl =>
|
|
|
|
|
(case yAxis of
|
|
|
|
|
DROP_BELOW_PLATFORM =>
|
2024-12-18 03:30:21 +00:00
|
|
|
(* pass through, allowing player to drop below the platform *)
|
|
|
|
|
helpCheckPlatforms
|
2024-12-20 07:38:41 +00:00
|
|
|
( yAxis, xAxis, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing
|
2024-12-20 07:38:41 +00:00
|
|
|
, tl, wallList, game
|
|
|
|
|
)
|
2024-12-18 03:30:21 +00:00
|
|
|
| JUMPING _ =>
|
|
|
|
|
(* pass through, allowing player to jump above the platform *)
|
2024-12-17 22:45:58 +00:00
|
|
|
helpCheckPlatforms
|
2024-12-20 07:38:41 +00:00
|
|
|
( yAxis, xAxis, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing
|
2024-12-20 07:38:41 +00:00
|
|
|
, tl, wallList, game
|
|
|
|
|
)
|
2024-12-17 22:45:58 +00:00
|
|
|
| _ =>
|
2024-12-17 23:49:40 +00:00
|
|
|
let
|
2024-12-18 03:30:21 +00:00
|
|
|
(* default case:
|
|
|
|
|
* player will land on platform and stay on the ground there. *)
|
|
|
|
|
|
2024-12-17 23:49:40 +00:00
|
|
|
val {platforms, ...} = game
|
|
|
|
|
val {y = platY, ...} = Vector.sub (platforms, platID - 1)
|
|
|
|
|
|
|
|
|
|
val newY = platY - size
|
|
|
|
|
in
|
|
|
|
|
helpCheckPlatforms
|
2024-12-20 07:38:41 +00:00
|
|
|
( ON_GROUND, xAxis, x, newY, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing
|
2024-12-20 07:38:41 +00:00
|
|
|
, tl, wallList, game
|
|
|
|
|
)
|
2024-12-17 23:49:40 +00:00
|
|
|
end)
|
2024-12-17 22:45:58 +00:00
|
|
|
| [] =>
|
2024-12-20 07:38:41 +00:00
|
|
|
checkWalls
|
|
|
|
|
( yAxis, xAxis, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing
|
2024-12-20 07:38:41 +00:00
|
|
|
, wallList, game
|
|
|
|
|
)
|
2024-12-17 22:45:58 +00:00
|
|
|
end
|
|
|
|
|
|
2024-12-19 07:53:31 +00:00
|
|
|
fun checkEnemies
|
2024-12-20 17:41:21 +00:00
|
|
|
( yAxis, xAxis, x, y, health, jumpPressed, recoil, attacked, facing
|
2024-12-19 07:53:31 +00:00
|
|
|
, enemyCollisions, platCollisions, wallCollisions, game
|
|
|
|
|
) =
|
|
|
|
|
case enemyCollisions of
|
|
|
|
|
id :: tl =>
|
|
|
|
|
let
|
|
|
|
|
val newRecoil =
|
|
|
|
|
(* check if collision is closer to left side of enemy or right
|
|
|
|
|
* and then chose appropriate direction to recoil in *)
|
|
|
|
|
let
|
|
|
|
|
val pFinishX = x + size
|
|
|
|
|
val pHalfW = size div 2
|
|
|
|
|
val pCentreX = x + pHalfW
|
|
|
|
|
|
|
|
|
|
val {x = ex, y = ey, ...} = Vector.sub (#enemies game, id - 1)
|
|
|
|
|
val eFinishX = ex + Enemy.size
|
|
|
|
|
val eHalfW = Enemy.size div 2
|
|
|
|
|
val eCentreX = ex + eHalfW
|
|
|
|
|
in
|
|
|
|
|
if eCentreX < pCentreX then
|
|
|
|
|
RECOIL_RIGHT 0
|
|
|
|
|
else
|
|
|
|
|
RECOIL_LEFT 0
|
|
|
|
|
end
|
2024-12-20 07:38:41 +00:00
|
|
|
|
2024-12-20 17:41:21 +00:00
|
|
|
val facing =
|
|
|
|
|
case newRecoil of
|
|
|
|
|
RECOIL_LEFT _ => FACING_RIGHT
|
|
|
|
|
| RECOIL_RIGHT _ => FACING_LEFT
|
|
|
|
|
| NO_RECOIL => facing
|
|
|
|
|
|
2024-12-20 07:38:41 +00:00
|
|
|
val attacked = ATTACKED 0
|
2024-12-19 07:53:31 +00:00
|
|
|
in
|
|
|
|
|
checkEnemies
|
2024-12-20 07:38:41 +00:00
|
|
|
( FALLING, STAY_STILL, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, newRecoil, ATTACKED 0, facing
|
2024-12-19 07:53:31 +00:00
|
|
|
, tl, platCollisions, wallCollisions, game
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
| [] =>
|
|
|
|
|
helpCheckPlatforms
|
2024-12-20 07:38:41 +00:00
|
|
|
( yAxis, xAxis, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing
|
2024-12-19 07:53:31 +00:00
|
|
|
, platCollisions, wallCollisions, game
|
|
|
|
|
)
|
|
|
|
|
|
2024-12-20 07:38:41 +00:00
|
|
|
fun checkCollisions
|
|
|
|
|
( yAxis, xAxis, x, y, health
|
|
|
|
|
, jumpPressed, recoil
|
2024-12-20 17:41:21 +00:00
|
|
|
, attacked, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
) =
|
2024-12-17 22:45:58 +00:00
|
|
|
let
|
2024-12-19 07:53:31 +00:00
|
|
|
val {wallTree, platformTree, enemyTree, ...} = game
|
|
|
|
|
|
|
|
|
|
(* control flow is: check enemies -> check platforms -> check walls
|
|
|
|
|
* but this is not visible in this function as everything is implemented
|
|
|
|
|
* by tail call.
|
|
|
|
|
* So, when one function hits the end of its collision list,
|
|
|
|
|
* it calls the next function at its tail. *)
|
|
|
|
|
|
2024-12-17 22:45:58 +00:00
|
|
|
val platCollisions = QuadTree.getCollisionsBelow
|
2024-12-18 03:30:21 +00:00
|
|
|
(x, y, size, size, 0, 0, 1920, 1080, 0, platformTree)
|
2024-12-17 22:45:58 +00:00
|
|
|
|
|
|
|
|
val wallCollisions = QuadTree.getCollisionSides
|
2024-12-18 03:30:21 +00:00
|
|
|
(x, y, size, size, 0, 0, 1920, 1080, 0, wallTree)
|
2024-12-17 22:45:58 +00:00
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
(* skip enemy collisions if player is in attacked state
|
|
|
|
|
* because games often offer a short cooldown period
|
|
|
|
|
* where player can walk through enemies without receiving damage
|
|
|
|
|
* in which case enemy collisions don't count
|
|
|
|
|
* *)
|
|
|
|
|
case attacked of
|
|
|
|
|
NOT_ATTACKED =>
|
2024-12-19 07:53:31 +00:00
|
|
|
let
|
|
|
|
|
val enemyCollisions = QuadTree.getCollisions
|
|
|
|
|
(x, y, size, size, 0, 0, 1920, 1080, 0, enemyTree)
|
|
|
|
|
in
|
|
|
|
|
checkEnemies
|
2024-12-20 07:38:41 +00:00
|
|
|
( yAxis, xAxis, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing
|
2024-12-19 07:53:31 +00:00
|
|
|
, enemyCollisions, platCollisions, wallCollisions, game
|
|
|
|
|
)
|
|
|
|
|
end
|
2024-12-20 07:38:41 +00:00
|
|
|
| ATTACKED amt =>
|
|
|
|
|
if amt = attackLimit then
|
|
|
|
|
(* if we hit limit, exit ATTACKED phase
|
|
|
|
|
* and react to enemy collisions again
|
|
|
|
|
* *)
|
|
|
|
|
let
|
|
|
|
|
val enemyCollisions = QuadTree.getCollisions
|
|
|
|
|
(x, y, size, size, 0, 0, 1920, 1080, 0, enemyTree)
|
|
|
|
|
in
|
|
|
|
|
checkEnemies
|
|
|
|
|
( yAxis, xAxis, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, NOT_ATTACKED, facing
|
2024-12-20 07:38:41 +00:00
|
|
|
, enemyCollisions, platCollisions, wallCollisions, game
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
let
|
|
|
|
|
val amt = amt + 1
|
|
|
|
|
val attacked = ATTACKED amt
|
|
|
|
|
in
|
|
|
|
|
helpCheckPlatforms
|
|
|
|
|
( yAxis, xAxis, x, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing
|
2024-12-20 07:38:41 +00:00
|
|
|
, platCollisions, wallCollisions, game
|
|
|
|
|
)
|
|
|
|
|
end
|
2024-12-13 22:48:34 +00:00
|
|
|
end
|
2024-12-09 04:37:40 +00:00
|
|
|
|
2024-12-20 17:41:21 +00:00
|
|
|
fun helpMove
|
|
|
|
|
( x, y, xAxis, yAxis, health
|
|
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
|
|
|
|
) =
|
2024-12-13 22:48:34 +00:00
|
|
|
let
|
|
|
|
|
(* check against wall quad tree *)
|
|
|
|
|
val desiredX =
|
2024-12-09 04:37:40 +00:00
|
|
|
case xAxis of
|
2024-12-13 22:48:34 +00:00
|
|
|
STAY_STILL => x
|
|
|
|
|
| MOVE_LEFT => x - moveBy
|
|
|
|
|
| MOVE_RIGHT => x + moveBy
|
2024-12-09 04:37:40 +00:00
|
|
|
in
|
|
|
|
|
case yAxis of
|
2024-12-13 22:48:34 +00:00
|
|
|
ON_GROUND =>
|
2024-12-19 07:53:31 +00:00
|
|
|
checkCollisions
|
2024-12-20 07:38:41 +00:00
|
|
|
( yAxis, xAxis, desiredX, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-14 18:02:57 +00:00
|
|
|
| FLOATING floated =>
|
|
|
|
|
let
|
|
|
|
|
val yAxis =
|
|
|
|
|
if floated = floatLimit then FALLING else FLOATING (floated + 1)
|
|
|
|
|
in
|
2024-12-19 07:53:31 +00:00
|
|
|
checkCollisions
|
2024-12-20 17:41:21 +00:00
|
|
|
( yAxis, xAxis, desiredX, y, health
|
|
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
|
|
|
|
)
|
2024-12-14 18:02:57 +00:00
|
|
|
end
|
2024-12-13 22:48:34 +00:00
|
|
|
| FALLING =>
|
|
|
|
|
let
|
|
|
|
|
val desiredY = y + moveBy
|
|
|
|
|
in
|
2024-12-19 07:53:31 +00:00
|
|
|
checkCollisions
|
2024-12-20 07:38:41 +00:00
|
|
|
( yAxis, xAxis, desiredX, desiredY, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-17 22:45:58 +00:00
|
|
|
end
|
|
|
|
|
| DROP_BELOW_PLATFORM =>
|
|
|
|
|
let
|
|
|
|
|
val desiredY = y + moveBy
|
|
|
|
|
in
|
2024-12-19 07:53:31 +00:00
|
|
|
checkCollisions
|
2024-12-20 07:38:41 +00:00
|
|
|
( yAxis, xAxis, desiredX, desiredY, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-13 22:48:34 +00:00
|
|
|
end
|
|
|
|
|
| JUMPING jumped =>
|
|
|
|
|
if jumped + moveBy > jumpLimit then
|
|
|
|
|
(* if we are above the jump limit, trigger a fall *)
|
2024-12-09 04:37:40 +00:00
|
|
|
let
|
2024-12-17 22:45:58 +00:00
|
|
|
val newYAxis = FLOATING 0
|
2024-12-09 04:37:40 +00:00
|
|
|
in
|
2024-12-19 07:53:31 +00:00
|
|
|
checkCollisions
|
2024-12-20 07:38:41 +00:00
|
|
|
( newYAxis, xAxis, desiredX, y, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-09 04:37:40 +00:00
|
|
|
end
|
|
|
|
|
else
|
2024-12-13 22:48:34 +00:00
|
|
|
(* jump *)
|
|
|
|
|
let
|
|
|
|
|
val newJumped = jumped + moveBy
|
2024-12-17 22:45:58 +00:00
|
|
|
val newYAxis = JUMPING newJumped
|
2024-12-13 22:48:34 +00:00
|
|
|
val desiredY = y - moveBy
|
|
|
|
|
in
|
2024-12-19 07:53:31 +00:00
|
|
|
checkCollisions
|
2024-12-19 03:58:37 +00:00
|
|
|
( newYAxis, xAxis, desiredX, desiredY
|
2024-12-20 17:41:21 +00:00
|
|
|
, health, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
2024-12-19 03:58:37 +00:00
|
|
|
)
|
2024-12-13 22:48:34 +00:00
|
|
|
end
|
2024-12-09 04:37:40 +00:00
|
|
|
end
|
2024-12-14 07:59:43 +00:00
|
|
|
|
|
|
|
|
fun getXAxis (lh, rh) =
|
|
|
|
|
case (lh, rh) of
|
|
|
|
|
(false, false) => STAY_STILL
|
|
|
|
|
| (false, true) => MOVE_RIGHT
|
|
|
|
|
| (true, false) => MOVE_LEFT
|
|
|
|
|
| (true, true) => STAY_STILL
|
|
|
|
|
|
2024-12-20 17:41:21 +00:00
|
|
|
fun getFacing (facing, xAxis) =
|
|
|
|
|
case xAxis of
|
|
|
|
|
STAY_STILL => facing
|
|
|
|
|
| MOVE_LEFT => FACING_LEFT
|
|
|
|
|
| MOVE_RIGHT => FACING_RIGHT
|
|
|
|
|
|
2024-12-14 18:02:57 +00:00
|
|
|
(* 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. *)
|
2024-12-14 21:05:51 +00:00
|
|
|
fun onJumpPressed (prevAxis, jumpPressed) =
|
2024-12-14 18:02:57 +00:00
|
|
|
case prevAxis of
|
2024-12-19 08:10:34 +00:00
|
|
|
ON_GROUND =>
|
|
|
|
|
if jumpPressed then
|
|
|
|
|
(* apply gravity *)
|
|
|
|
|
FALLING
|
|
|
|
|
else
|
|
|
|
|
JUMPING 0
|
2024-12-14 18:02:57 +00:00
|
|
|
| _ => prevAxis
|
|
|
|
|
|
2024-12-19 04:09:03 +00:00
|
|
|
fun handleInput (game: game_type, input, recoil) =
|
2024-12-14 07:59:43 +00:00
|
|
|
let
|
2024-12-20 17:41:21 +00:00
|
|
|
val {x, y, yAxis, health, jumpPressed, attacked, facing, ...} = #player game
|
2024-12-14 21:05:51 +00:00
|
|
|
val {leftHeld, rightHeld, upHeld, downHeld} = input
|
2024-12-15 09:10:19 +00:00
|
|
|
|
2024-12-14 07:59:43 +00:00
|
|
|
val xAxis = getXAxis (leftHeld, rightHeld)
|
2024-12-20 17:41:21 +00:00
|
|
|
val facing = getFacing (facing, xAxis)
|
2024-12-14 07:59:43 +00:00
|
|
|
in
|
2024-12-14 21:05:51 +00:00
|
|
|
case (upHeld, downHeld) of
|
|
|
|
|
(false, false) =>
|
|
|
|
|
let
|
|
|
|
|
val yAxis = defaultYAxis yAxis
|
|
|
|
|
val jumpPressed = false
|
|
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
helpMove
|
|
|
|
|
( x, y, xAxis, yAxis, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-14 21:05:51 +00:00
|
|
|
end
|
|
|
|
|
| (true, true) =>
|
2024-12-20 07:38:41 +00:00
|
|
|
let
|
|
|
|
|
val yAxis = defaultYAxis yAxis
|
|
|
|
|
in
|
|
|
|
|
helpMove
|
|
|
|
|
( x, y, xAxis, yAxis, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-14 21:05:51 +00:00
|
|
|
end
|
|
|
|
|
| (true, false) =>
|
|
|
|
|
let
|
|
|
|
|
val yAxis = onJumpPressed (yAxis, jumpPressed)
|
|
|
|
|
val jumpPressed = true
|
|
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
helpMove
|
|
|
|
|
( x, y, xAxis, yAxis, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-14 21:05:51 +00:00
|
|
|
end
|
|
|
|
|
| (false, true) =>
|
2024-12-18 03:30:21 +00:00
|
|
|
let
|
|
|
|
|
val jumpPressed = false
|
|
|
|
|
val yAxis = DROP_BELOW_PLATFORM
|
|
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
helpMove
|
|
|
|
|
(x, y, xAxis, yAxis, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-14 21:05:51 +00:00
|
|
|
end
|
2024-12-14 07:59:43 +00:00
|
|
|
end
|
2024-12-15 09:10:19 +00:00
|
|
|
|
2024-12-19 03:58:37 +00:00
|
|
|
fun move (game: game_type, input) =
|
|
|
|
|
let
|
|
|
|
|
val player = #player game
|
2024-12-19 04:09:03 +00:00
|
|
|
val recoil = #recoil player
|
2024-12-19 03:58:37 +00:00
|
|
|
in
|
2024-12-19 04:09:03 +00:00
|
|
|
case recoil of
|
|
|
|
|
NO_RECOIL => handleInput (game, input, recoil)
|
|
|
|
|
| RECOIL_LEFT recoiled =>
|
2024-12-19 03:58:37 +00:00
|
|
|
(* if player is recoiling, don't accept or adjust any input.
|
|
|
|
|
* However, if player has reached the recoil limit, exit the recoil
|
|
|
|
|
* state and accept input.
|
|
|
|
|
* *)
|
|
|
|
|
if recoiled = recoilLimit then
|
2024-12-19 04:09:03 +00:00
|
|
|
handleInput (game, input, NO_RECOIL)
|
2024-12-19 03:58:37 +00:00
|
|
|
else
|
|
|
|
|
let
|
2024-12-20 17:41:21 +00:00
|
|
|
val {x, y, health, attacked, facing, xAxis, ...} = player
|
2024-12-19 04:09:03 +00:00
|
|
|
(* difference between RECOIL_LEFT and RECOIL_RIGHT
|
|
|
|
|
* is the direction player moves back in *)
|
2024-12-19 03:58:37 +00:00
|
|
|
val x = x - 5
|
2024-12-19 04:09:03 +00:00
|
|
|
|
|
|
|
|
val xAxis = STAY_STILL
|
|
|
|
|
val yAxis = FALLING
|
|
|
|
|
val jumpPressed = false
|
|
|
|
|
val recoiled = recoiled + 1
|
|
|
|
|
val recoil = RECOIL_LEFT recoiled
|
2024-12-20 17:41:21 +00:00
|
|
|
val facing = getFacing (facing, xAxis)
|
2024-12-19 04:09:03 +00:00
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
helpMove
|
|
|
|
|
( x, y, xAxis, yAxis, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-19 04:09:03 +00:00
|
|
|
end
|
|
|
|
|
| RECOIL_RIGHT recoiled =>
|
|
|
|
|
if recoiled = recoilLimit then
|
|
|
|
|
handleInput (game, input, NO_RECOIL)
|
|
|
|
|
else
|
|
|
|
|
let
|
2024-12-20 17:41:21 +00:00
|
|
|
val {x, y, health, attacked, facing, xAxis, ...} = player
|
2024-12-19 04:09:03 +00:00
|
|
|
val x = x + 5
|
|
|
|
|
|
2024-12-19 03:58:37 +00:00
|
|
|
val xAxis = STAY_STILL
|
|
|
|
|
val yAxis = FALLING
|
|
|
|
|
val jumpPressed = false
|
|
|
|
|
val recoiled = recoiled + 1
|
2024-12-19 04:09:03 +00:00
|
|
|
val recoil = RECOIL_RIGHT recoiled
|
2024-12-20 17:41:21 +00:00
|
|
|
val facing = getFacing (facing, xAxis)
|
2024-12-19 03:58:37 +00:00
|
|
|
in
|
2024-12-20 07:38:41 +00:00
|
|
|
helpMove
|
|
|
|
|
( x, y, xAxis, yAxis, health
|
2024-12-20 17:41:21 +00:00
|
|
|
, jumpPressed, recoil, attacked
|
|
|
|
|
, facing, game
|
2024-12-20 07:38:41 +00:00
|
|
|
)
|
2024-12-19 03:58:37 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2024-12-16 00:58:59 +00:00
|
|
|
(* block is placeholder asset *)
|
2024-12-20 07:55:10 +00:00
|
|
|
fun helpGetDrawVec (x, y, size, width, height, attacked) =
|
|
|
|
|
case attacked of
|
|
|
|
|
NOT_ATTACKED =>
|
|
|
|
|
Block.lerp (x, y, size, size, width, height, 0.5, 0.5, 0.5)
|
|
|
|
|
| ATTACKED amt =>
|
|
|
|
|
if amt mod 5 = 0 then
|
|
|
|
|
Block.lerp (x, y, size, size, width, height, 0.9, 0.9, 0.9)
|
|
|
|
|
else
|
|
|
|
|
Block.lerp (x, y, size, size, width, height, 0.5, 0.5, 0.5)
|
|
|
|
|
|
|
|
|
|
fun getDrawVec ({x, y, attacked, ...}: player, width, height) =
|
2024-12-17 09:16:22 +00:00
|
|
|
let
|
|
|
|
|
val wratio = width / 1920.0
|
|
|
|
|
val hratio = height / 1080.0
|
|
|
|
|
in
|
|
|
|
|
if wratio < hratio then
|
|
|
|
|
let
|
|
|
|
|
val scale = 1080.0 * wratio
|
|
|
|
|
val yOffset =
|
|
|
|
|
if height > scale then (height - scale) / 2.0
|
|
|
|
|
else if height < scale then (scale - height) / 2.0
|
|
|
|
|
else 0.0
|
|
|
|
|
|
|
|
|
|
val x = Real32.fromInt x * wratio
|
|
|
|
|
val y = Real32.fromInt y * wratio + yOffset
|
|
|
|
|
|
|
|
|
|
val realSize = realSize * wratio
|
|
|
|
|
in
|
2024-12-20 07:55:10 +00:00
|
|
|
helpGetDrawVec (x, y, realSize, width, height, attacked)
|
2024-12-17 09:16:22 +00:00
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
let
|
|
|
|
|
val scale = 1920.0 * hratio
|
|
|
|
|
val xOffset =
|
|
|
|
|
if width > scale then (width - scale) / 2.0
|
|
|
|
|
else if width < scale then (scale - width) / 2.0
|
|
|
|
|
else 0.0
|
|
|
|
|
|
|
|
|
|
val x = Real32.fromInt x * hratio + xOffset
|
|
|
|
|
val y = Real32.fromInt y * hratio
|
|
|
|
|
|
|
|
|
|
val realSize = realSize * hratio
|
|
|
|
|
in
|
2024-12-20 07:55:10 +00:00
|
|
|
helpGetDrawVec (x, y, realSize, width, height, attacked)
|
2024-12-17 09:16:22 +00:00
|
|
|
end
|
|
|
|
|
end
|
2024-12-09 04:37:40 +00:00
|
|
|
end
|