forked from zapashcanon/pellest
better keyboard handling
This commit is contained in:
parent
b0d466ac08
commit
2945e7d478
@ -101,21 +101,82 @@ let send_action state action =
|
||||
Log.debug "sending action %a to server@\n" State.pp_action action;
|
||||
Ws_client.send (Network.Action_msg action)
|
||||
|
||||
let keydown_handler ev =
|
||||
module Kb : sig
|
||||
(* this keeps an ordered sequence of unique values,
|
||||
it's the responsability of the caller to make sure
|
||||
the same element is not added twice ! *)
|
||||
|
||||
type t = string
|
||||
|
||||
val add : t -> unit
|
||||
|
||||
val rm : t -> unit
|
||||
|
||||
val get_last : unit -> t option
|
||||
end = struct
|
||||
type t = string
|
||||
|
||||
let last = ref []
|
||||
|
||||
let add k = last := k :: !last
|
||||
|
||||
let rm k = last := List.filter (( <> ) k) !last
|
||||
|
||||
let get_last () = match !last with [] -> None | key :: _keys -> Some key
|
||||
end
|
||||
|
||||
let keypress_handler =
|
||||
(* be careful to add in the correct array ! *)
|
||||
let codes = Hashtbl.create 512 in
|
||||
Array.iter
|
||||
(fun code -> Hashtbl.add codes code ())
|
||||
[| "ArrowDown"
|
||||
; "ArrowLeft"
|
||||
; "ArrowRight"
|
||||
; "ArrowUp"
|
||||
; "KeyA"
|
||||
; "KeyD"
|
||||
; "KeyS"
|
||||
; "KeyW"
|
||||
|];
|
||||
let keys = Hashtbl.create 512 in
|
||||
Array.iter (fun key -> Hashtbl.add keys key ()) [| "m" |];
|
||||
(* TODO: I'm not sure the Hashtbl business is worth it.
|
||||
Before, we were matching on values instead of calling Hashtbl.mem.
|
||||
It should be better with Hashtbl but it wasn't benchmarked. *)
|
||||
fun ~down ->
|
||||
let f = if down then Kb.add else Kb.rm in
|
||||
fun ev ->
|
||||
let ev = Ev.as_type ev in
|
||||
(* repeat is true if and only if an event as already been sent since the key has been pressed
|
||||
in this case, it's already in the sequence so we just skip it, we know it'll eventually be
|
||||
released on keydown before it can appears again *)
|
||||
if not @@ Ev.Keyboard.repeat ev then
|
||||
let code = Ev.Keyboard.code ev |> Jstr.to_string in
|
||||
if Hashtbl.mem codes code then f code
|
||||
else
|
||||
let key = Ev.Keyboard.key ev |> Jstr.to_string in
|
||||
if Hashtbl.mem keys key then f key
|
||||
|
||||
let apply_last_key () =
|
||||
let open State in
|
||||
let ev = Ev.as_type ev in
|
||||
let act =
|
||||
match Ev.Keyboard.code ev |> Jstr.to_string with
|
||||
| "KeyW" | "ArrowUp" -> Move Up
|
||||
| "KeyA" | "ArrowLeft" -> Move Left
|
||||
| "KeyS" | "ArrowDown" -> Move Down
|
||||
| "KeyD" | "ArrowRight" -> Move Right
|
||||
| _code -> (
|
||||
match Ev.Keyboard.key ev |> Jstr.to_string with
|
||||
| "m" -> Meditate
|
||||
| _key -> Do_nothing )
|
||||
in
|
||||
Queue.add act input_queue
|
||||
Kb.get_last ()
|
||||
|> Option.iter (fun code_or_key ->
|
||||
let act =
|
||||
(* when you add something here, don't forget to add the corresponding case in `keypress_handler` *)
|
||||
match code_or_key with
|
||||
| "KeyW" | "ArrowUp" -> Move Up
|
||||
| "KeyA" | "ArrowLeft" -> Move Left
|
||||
| "KeyS" | "ArrowDown" -> Move Down
|
||||
| "KeyD" | "ArrowRight" -> Move Right
|
||||
| "m" -> Meditate
|
||||
| _ ->
|
||||
(* if this happen, it means we're adding
|
||||
bad values in `keypress_handler`
|
||||
and that should be fixed *)
|
||||
assert false
|
||||
in
|
||||
Queue.add act input_queue )
|
||||
|
||||
let render state =
|
||||
draw_canvas state;
|
||||
@ -131,6 +192,7 @@ let rec game_loop state last_auto_update timestamp =
|
||||
let last_auto_update =
|
||||
if should_auto_update then timestamp else last_auto_update
|
||||
in
|
||||
apply_last_key ();
|
||||
let state =
|
||||
(* apply queue of actions *)
|
||||
let state = Queue.fold State.perform_action state to_apply_queue in
|
||||
@ -167,7 +229,14 @@ let () =
|
||||
|
||||
(* bind keys *)
|
||||
let _e : Ev.listener =
|
||||
Ev.listen Ev.keydown keydown_handler (Window.as_target G.window)
|
||||
Ev.listen Ev.keydown
|
||||
(keypress_handler ~down:true)
|
||||
(Window.as_target G.window)
|
||||
in
|
||||
let _e : Ev.listener =
|
||||
Ev.listen Ev.keyup
|
||||
(keypress_handler ~down:false)
|
||||
(Window.as_target G.window)
|
||||
in
|
||||
|
||||
(* bind buttons *)
|
||||
|
Loading…
x
Reference in New Issue
Block a user