Files
sml-projects/fcore/level/player/player-vec.sml
2025-08-30 00:55:58 +01:00

253 lines
9.0 KiB
Standard ML

structure PlayerVec =
struct
open EntityType
open PlayerType
val walkRightFrames =
#[ PlayerWalkRight1.lerp
, PlayerWalkRight2.lerp
, PlayerWalkRight3.lerp
, PlayerWalkRight4.lerp
, PlayerWalkRight5.lerp
, PlayerWalkRight6.lerp
, PlayerWalkRight7.lerp
, PlayerWalkRight8.lerp
]
val walkLeftFrames =
#[ PlayerWalkLeft1.lerp
, PlayerWalkLeft2.lerp
, PlayerWalkLeft3.lerp
, PlayerWalkLeft4.lerp
, PlayerWalkLeft5.lerp
, PlayerWalkLeft6.lerp
, PlayerWalkLeft7.lerp
, PlayerWalkLeft8.lerp
]
val attackLeftProjectiles =
#[ PlayerAttackLeftProjectile1.lerp
, PlayerAttackLeftProjectile2.lerp
, PlayerAttackLeftProjectile3.lerp
, PlayerAttackLeftProjectile4.lerp
, PlayerAttackLeftProjectile5.lerp
, PlayerAttackLeftProjectile6.lerp
, PlayerAttackLeftProjectile7.lerp
, PlayerAttackLeftProjectile8.lerp
, PlayerAttackLeftProjectile9.lerp
, PlayerAttackLeftProjectile10.lerp
, PlayerAttackLeftProjectile11.lerp
, PlayerAttackLeftProjectile12.lerp
, PlayerAttackLeftProjectile13.lerp
, PlayerAttackLeftProjectile14.lerp
, PlayerAttackLeftProjectile15.lerp
, PlayerAttackLeftProjectile16.lerp
, PlayerAttackLeftProjectile17.lerp
, PlayerAttackLeftProjectile18.lerp
, PlayerAttackLeftProjectile19.lerp
, PlayerAttackLeftProjectile20.lerp
, PlayerAttackLeftProjectile21.lerp
, PlayerAttackLeftProjectile22.lerp
, PlayerAttackLeftProjectile23.lerp
, PlayerAttackLeftProjectile24.lerp
, PlayerAttackLeftProjectile25.lerp
]
val attackRightProjectiles =
#[ PlayerAttackRightProjectile1.lerp
, PlayerAttackRightProjectile2.lerp
, PlayerAttackRightProjectile3.lerp
, PlayerAttackRightProjectile4.lerp
, PlayerAttackRightProjectile5.lerp
, PlayerAttackRightProjectile6.lerp
, PlayerAttackRightProjectile7.lerp
, PlayerAttackRightProjectile8.lerp
, PlayerAttackRightProjectile9.lerp
, PlayerAttackRightProjectile10.lerp
, PlayerAttackRightProjectile11.lerp
, PlayerAttackRightProjectile12.lerp
, PlayerAttackRightProjectile13.lerp
, PlayerAttackRightProjectile14.lerp
, PlayerAttackRightProjectile15.lerp
, PlayerAttackRightProjectile16.lerp
, PlayerAttackRightProjectile17.lerp
, PlayerAttackRightProjectile18.lerp
, PlayerAttackRightProjectile19.lerp
, PlayerAttackRightProjectile20.lerp
, PlayerAttackRightProjectile21.lerp
, PlayerAttackRightProjectile22.lerp
, PlayerAttackRightProjectile23.lerp
, PlayerAttackRightProjectile24.lerp
, PlayerAttackRightProjectile25.lerp
]
fun getIdle (player, rx, ry, ww, wh) =
case #facing player of
FACING_RIGHT => PlayerStandingRight.lerp (rx, ry, 3.0, ww, wh)
| FACING_LEFT => PlayerStandingLeft.lerp (rx, ry, 3.0, ww, wh)
fun getWalk (rx, ry, ww, wh, walkFrames, animTimer) =
let
val frame = (animTimer div 4) mod Vector.length walkFrames
val func = Vector.sub (walkFrames, Int.max (frame, 0))
in
func (rx, ry, 3.0, ww, wh)
end
fun getWhenOnGround (player, rx, ry, ww, wh) =
case #xAxis player of
MOVE_RIGHT => getWalk (rx, ry, ww, wh, walkRightFrames, #animTimer player)
| MOVE_LEFT => getWalk (rx, ry, ww, wh, walkLeftFrames, #animTimer player)
| STAY_STILL => getIdle (player, rx, ry, ww, wh)
fun getWhenJumpingRight (player, amt, rx, ry, ww, wh) =
if amt < 3 then PlayerJumpRight1.lerp (rx, ry, 3.0, ww, wh)
else if amt < 6 then PlayerJumpRight2.lerp (rx, ry, 3.0, ww, wh)
else if amt < 9 then PlayerJumpRight3.lerp (rx, ry, 3.0, ww, wh)
else if amt < 12 then PlayerJumpRight4.lerp (rx, ry, 3.0, ww, wh)
else PlayerJumpRight5.lerp (rx, ry, 3.0, ww, wh)
fun getWhenJumpingLeft (player, amt, rx, ry, ww, wh) =
if amt < 3 then PlayerJumpLeft1.lerp (rx, ry, 3.0, ww, wh)
else if amt < 6 then PlayerJumpLeft2.lerp (rx, ry, 3.0, ww, wh)
else if amt < 9 then PlayerJumpLeft3.lerp (rx, ry, 3.0, ww, wh)
else if amt < 12 then PlayerJumpLeft4.lerp (rx, ry, 3.0, ww, wh)
else PlayerJumpLeft5.lerp (rx, ry, 3.0, ww, wh)
fun getWhenJumping (player, amt, rx, ry, ww, wh) =
case #facing player of
FACING_RIGHT => getWhenJumpingRight (player, amt, rx, ry, ww, wh)
| FACING_LEFT => getWhenJumpingLeft (player, amt, rx, ry, ww, wh)
fun getWhenFloating (player, rx, ry, ww, wh) =
case #facing player of
FACING_RIGHT => PlayerJumpRight5.lerp (rx, ry, 3.0, ww, wh)
| FACING_LEFT => PlayerJumpLeft5.lerp (rx, ry, 3.0, ww, wh)
fun getWhenFalling (player, rx, ry, ww, wh) =
case #facing player of
FACING_RIGHT => PlayerFallRight.lerp (rx, ry, 3.0, ww, wh)
| FACING_LEFT => PlayerFallLeft.lerp (rx, ry, 3.0, ww, wh)
fun getWhenDropping (player, rx, ry, ww, wh) =
let
val animTimer = #animTimer player
in
if animTimer < 15 then
getWhenJumping (player, animTimer, rx, ry, ww, wh)
else
case #facing player of
FACING_RIGHT => PlayerFallRight.lerp (rx, ry, 3.0, ww, wh)
| FACING_LEFT => PlayerFallLeft.lerp (rx, ry, 3.0, ww, wh)
end
fun getWhenNotAttacked (player, rx, ry, ww, wh) =
case #yAxis player of
ON_GROUND => getWhenOnGround (player, rx, ry, ww, wh)
| JUMPING amt => getWhenJumping (player, amt, rx, ry, ww, wh)
| FLOATING _ => getWhenFloating (player, rx, ry, ww, wh)
| FALLING => getWhenFalling (player, rx, ry, ww, wh)
| DROP_BELOW_PLATFORM => getWhenDropping (player, rx, ry, ww, wh)
fun getWhenAttacked (player, amt, rx, ry, ww, wh) =
case #facing player of
FACING_RIGHT =>
(* todo: hurt sprite/animation if amt mod 5 = 0 then *)
PlayerStandingRight.lerp (rx, ry, 3.0, ww, wh)
| FACING_LEFT =>
(* todo: hurt sprite/animation if amt mod 5 = 0 then *)
PlayerStandingLeft.lerp (rx, ry, 3.0, ww, wh)
fun helpGet
( player: player
, x
, y
, xOffset
, yOffset
, ratio
, rx
, ry
, windowWidth
, windowHeight
) =
case #mainAttack player of
MAIN_ATTACKING {animTimer = amt, ...} =>
(case #facing player of
FACING_RIGHT =>
let
val playerVec = PlayerAttackStandRight.lerp
(rx, ry, 3.0, windowWidth, windowHeight)
(* adding playerWidth to x so that projectile starts from
* the rightmost pixel of the player *)
val projX = x + Constants.playerWidth
val projY = y + Constants.projectileOffsetY
val projX = (Real32.fromInt projX + xOffset) * ratio
val projY = (Real32.fromInt projY + yOffset) * ratio
val func = Vector.sub (attackRightProjectiles, amt)
val projectilesVec = func
(projX, projY, 3.0, windowWidth, windowHeight)
in
Vector.concat [playerVec, projectilesVec]
end
| FACING_LEFT =>
let
val playerVec = PlayerAttackStandLeft.lerp
(rx, ry, 3.0, windowWidth, windowHeight)
(* subtracting projectileWidth from x it looks like
* the projectile starts from player's leftmost side this way. *)
val projX = x - Constants.projectileWidth
val projY = y + Constants.projectileOffsetY
val projX = (Real32.fromInt projX + xOffset) * ratio
val projY = (Real32.fromInt projY + yOffset) * ratio
val func = Vector.sub (attackLeftProjectiles, amt)
val projectilesVec = func
(projX, projY, 3.0, windowWidth, windowHeight)
in
Vector.concat [playerVec, projectilesVec]
end)
| _ =>
case #attacked player of
NOT_ATTACKED =>
getWhenNotAttacked (player, rx, ry, windowWidth, windowHeight)
| ATTACKED amt =>
getWhenAttacked (player, amt, rx, ry, windowWidth, windowHeight)
fun get (player: player, width, height) =
let
val {x, y, attacked, facing, ...} = player
val wratio = width / Constants.worldWidthReal
val hratio = height / Constants.worldHeightReal
in
if wratio < hratio then
let
val scale = Constants.worldHeightReal * wratio
val yOffset =
if height > scale then (height - scale) / 2.0
else if height < scale then (scale - height) / 2.0
else 0.0
val rx = Real32.fromInt x * wratio
val ry = Real32.fromInt y * wratio + yOffset
in
helpGet (player, x, y, 0.0, yOffset, wratio, rx, ry, width, height)
end
else
let
val scale = Constants.worldWidthReal * hratio
val xOffset =
if width > scale then (width - scale) / 2.0
else if width < scale then (scale - width) / 2.0
else 0.0
val rx = Real32.fromInt x * hratio + xOffset
val ry = Real32.fromInt y * hratio
in
helpGet (player, x, y, xOffset, 0.0, hratio, rx, ry, width, height)
end
end
end