Files
sml-projects/game-sml/fcore/options/options-update.sml
Humza Shahid da8790f0b6 Add 'game-sml/' from commit '113c3e67abe635f714f972a1e2ab0e4b24ff10f4'
git-subtree-dir: game-sml
git-subtree-mainline: aa5357714d
git-subtree-split: 113c3e67ab
2026-04-24 00:38:14 +01:00

378 lines
11 KiB
Standard ML

signature MAKE_UPDATE_SELECTED_KEY =
sig
val updateKeys: CoreKey.key_code * CoreKey.user_key -> CoreKey.user_key
val default: OptionsType.options_type * CoreKey.user_key -> GameType.game_type
val deselect: OptionsType.options_type * CoreKey.user_key
-> GameType.game_type
end
functor MakeUpdateSelectedKey(Fn: MAKE_UPDATE_SELECTED_KEY) =
struct
fun setNewKeys (options, tempKeys, userKeys, time) =
let
val {focus, lastUpPress, lastDownPress, ...} = options
val options =
{ focus = focus
, lastUpPress = time
, lastDownPress = time
, isSelected = false
, tempKeys = tempKeys
}
in
{mode = GameType.OPTIONS options, userKeys = userKeys, saveKeys = false}
end
fun onSelected (options, input: FrameInputType.t, userKeys, time) =
case #newKeys input of
key :: tl =>
(* change key *)
if key = CoreKey.KEY_ESCAPE orelse CoreKey.containsEscape (userKeys, tl) then
(* deslect as that is the function of the escape key *)
Fn.deselect (options, userKeys)
(* what if new key collides with existing key? todo *)
else
let val tempKeys = Fn.updateKeys (key, #tempKeys options)
in setNewKeys (options, tempKeys, userKeys, time)
end
| [] => Fn.default (options, userKeys)
end
structure OptionsUpdate =
struct
open OptionsType
fun default (options: OptionsType.options_type, userKeys) =
let
val {focus, isSelected, tempKeys, ...} = options
(* `default` function is called when no keys are pressed
* so set up pressed/down pressed both to 0
* as neither is being pressed. *)
val options =
{ focus = focus
, lastUpPress = Time.zeroTime
, lastDownPress = Time.zeroTime
, isSelected = isSelected
, tempKeys = tempKeys
}
in
{mode = GameType.OPTIONS options, userKeys = userKeys, saveKeys = false}
end
fun moveFocusUp (options: OptionsType.options_type, newFocus, userKeys, time) =
let
(* only opening Time for time comparison and adding; no impurities here *)
open Time
val {focus, isSelected, lastUpPress, tempKeys, ...} = options
(* only switch to newFocus if it is time for key delay to be triggered.
* We set lastDownPress to 0 because up is currently being pressed instead
* so we don't want to a key delay for down. *)
val options =
if lastUpPress + Constants.keyDelay <= time then
{ focus = newFocus
, lastUpPress = time
, lastDownPress = Time.zeroTime
, isSelected = isSelected
, tempKeys = tempKeys
}
else
{ focus = focus
, lastUpPress = lastUpPress
, lastDownPress = Time.zeroTime
, isSelected = isSelected
, tempKeys = tempKeys
}
in
{mode = GameType.OPTIONS options, userKeys = userKeys, saveKeys = false}
end
fun moveFocusDown
(options: OptionsType.options_type, newFocus, userKeys, time) =
let
(* only opening Time for time comparison and adding; no impurities here *)
open Time
val {focus, isSelected, lastDownPress, tempKeys, ...} = options
val options =
if lastDownPress + Constants.keyDelay <= time then
{ focus = newFocus
, lastUpPress = Time.zeroTime
, lastDownPress = time
, isSelected = isSelected
, tempKeys = tempKeys
}
else
{ focus = focus
, lastUpPress = Time.zeroTime
, lastDownPress = lastDownPress
, isSelected = isSelected
, tempKeys = tempKeys
}
in
{mode = GameType.OPTIONS options, userKeys = userKeys, saveKeys = false}
end
fun select (options: OptionsType.options_type, userKeys) =
let
val {focus, lastUpPress, lastDownPress, tempKeys, ...} = options
val options =
{ focus = focus
, lastUpPress = lastUpPress
, lastDownPress = lastDownPress
, isSelected = true
, tempKeys = tempKeys
}
in
{mode = GameType.OPTIONS options, userKeys = userKeys, saveKeys = false}
end
fun deselect (options: OptionsType.options_type, userKeys) =
let
val {focus, lastUpPress, lastDownPress, tempKeys, ...} = options
val options =
{ focus = focus
, lastUpPress = lastUpPress
, lastDownPress = lastDownPress
, isSelected = false
, tempKeys = tempKeys
}
in
{mode = GameType.OPTIONS options, userKeys = userKeys, saveKeys = false}
end
fun withLeftKeys (newLeft, userKeys: CoreKey.user_key) =
let
val {right, up, down, jump, attack, escape, ...} = userKeys
in
{ left = newLeft
, right = right
, up = up
, down = down
, jump = jump
, attack = attack
, escape = escape
}
end
fun withRightKeys (newRight, userKeys: CoreKey.user_key) =
let
val {left, up, down, jump, attack, escape, ...} = userKeys
in
{ left = left
, right = newRight
, up = up
, down = down
, jump = jump
, attack = attack
, escape = escape
}
end
fun withUpKeys (newUp, userKeys: CoreKey.user_key) =
let
val {left, right, down, jump, attack, escape, ...} = userKeys
in
{ left = left
, right = right
, up = newUp
, down = down
, jump = jump
, attack = attack
, escape = escape
}
end
fun withDownKeys (newDown, userKeys: CoreKey.user_key) =
let
val {left, right, up, jump, attack, escape, ...} = userKeys
in
{ left = left
, right = right
, up = up
, down = newDown
, jump = jump
, attack = attack
, escape = escape
}
end
fun withJumpKeys (newJump, userKeys: CoreKey.user_key) =
let
val {left, right, up, down, attack, escape, ...} = userKeys
in
{ left = left
, right = right
, up = up
, down = down
, jump = newJump
, attack = attack
, escape = escape
}
end
fun withAttackKeys (newAttack, userKeys: CoreKey.user_key) =
let
val {left, right, up, down, jump, escape, ...} = userKeys
in
{ left = left
, right = right
, up = up
, down = down
, jump = jump
, attack = newAttack
, escape = escape
}
end
structure UpdateLeftKey =
MakeUpdateSelectedKey
(struct
val updateKeys = withLeftKeys
val default = default
val deselect = deselect
end)
structure UpdateRightKey =
MakeUpdateSelectedKey
(struct
val updateKeys = withRightKeys
val default = default
val deselect = deselect
end)
structure UpdateUpKey =
MakeUpdateSelectedKey
(struct
val updateKeys = withUpKeys
val default = default
val deselect = deselect
end)
structure UpdateDownKey =
MakeUpdateSelectedKey
(struct
val updateKeys = withDownKeys
val default = default
val deselect = deselect
end)
structure UpdateJumpKey =
MakeUpdateSelectedKey
(struct
val updateKeys = withJumpKeys
val default = default
val deselect = deselect
end)
structure UpdateAttackKey =
MakeUpdateSelectedKey
(struct
val updateKeys = withAttackKeys
val default = default
val deselect = deselect
end)
fun saveAndGoToTitle options =
let
val userKeys = #tempKeys options
in
{ mode = GameType.TITLE TitleType.initial
, userKeys = userKeys
, saveKeys = true
}
end
fun cancelAndGoToTitle userKeys =
{ mode = GameType.TITLE TitleType.initial
, userKeys = userKeys
, saveKeys = false
}
fun update (options, input: FrameInputType.t, userKeys, time) =
case #focus options of
LEFT_KEY =>
if #isSelected options then
UpdateLeftKey.onSelected (options, input, userKeys, time)
else if CoreKey.containsAttack (userKeys, #newKeys input) then
select (options, userKeys)
else if #upHeld input then
moveFocusUp (options, CANCEL_BUTTON, userKeys, time)
else if #downHeld input then
moveFocusDown (options, RIGHT_KEY, userKeys, time)
else
default (options, userKeys)
| RIGHT_KEY =>
if #isSelected options then
UpdateRightKey.onSelected (options, input, userKeys, time)
else if CoreKey.containsAttack (userKeys, #newKeys input) then
select (options, userKeys)
else if #upHeld input then
moveFocusUp (options, LEFT_KEY, userKeys, time)
else if #downHeld input then
moveFocusDown (options, UP_KEY, userKeys, time)
else
default (options, userKeys)
| UP_KEY =>
if #isSelected options then
UpdateUpKey.onSelected (options, input, userKeys, time)
else if CoreKey.containsAttack (userKeys, #newKeys input) then
select (options, userKeys)
else if #upHeld input then
moveFocusUp (options, RIGHT_KEY, userKeys, time)
else if #downHeld input then
moveFocusDown (options, DOWN_KEY, userKeys, time)
else
default (options, userKeys)
| DOWN_KEY =>
if #isSelected options then
UpdateDownKey.onSelected (options, input, userKeys, time)
else if CoreKey.containsAttack (userKeys, #newKeys input) then
select (options, userKeys)
else if #upHeld input then
moveFocusUp (options, UP_KEY, userKeys, time)
else if #downHeld input then
moveFocusDown (options, JUMP_KEY, userKeys, time)
else
default (options, userKeys)
| JUMP_KEY =>
if #isSelected options then
UpdateJumpKey.onSelected (options, input, userKeys, time)
else if CoreKey.containsAttack (userKeys, #newKeys input) then
select (options, userKeys)
else if #upHeld input then
moveFocusUp (options, DOWN_KEY, userKeys, time)
else if #downHeld input then
moveFocusDown (options, ATTACK_KEY, userKeys, time)
else
default (options, userKeys)
| ATTACK_KEY =>
if #isSelected options then
UpdateAttackKey.onSelected (options, input, userKeys, time)
else if CoreKey.containsAttack (userKeys, #newKeys input) then
select (options, userKeys)
else if #upHeld input then
moveFocusUp (options, JUMP_KEY, userKeys, time)
else if #downHeld input then
moveFocusDown (options, SAVE_BUTTON, userKeys, time)
else
default (options, userKeys)
| SAVE_BUTTON =>
if CoreKey.containsAttack (userKeys, #newKeys input) then
saveAndGoToTitle options
else if #upHeld input then
moveFocusUp (options, ATTACK_KEY, userKeys, time)
else if #downHeld input then
moveFocusDown (options, CANCEL_BUTTON, userKeys, time)
else
default (options, userKeys)
| CANCEL_BUTTON =>
if CoreKey.containsAttack (userKeys, #newKeys input) then
cancelAndGoToTitle userKeys
else if #upHeld input then
moveFocusUp (options, SAVE_BUTTON, userKeys, time)
else if #downHeld input then
moveFocusDown (options, LEFT_KEY, userKeys, time)
else
default (options, userKeys)
end