From 045a6f4e2052ef1f39a245f389a2662b852357c4 Mon Sep 17 00:00:00 2001 From: Gordon Pedersen Date: Mon, 27 Mar 2023 10:28:26 +1100 Subject: [PATCH] refactoring input and also rearranging folders --- app/{ => classes}/sound_instance.rb | 0 app/{ => classes}/sprite_instance.rb | 0 app/input.rb | 110 --------------------------- app/keybindings.rb | 48 ++++++++++++ app/main.rb | 17 +++-- app/menu.rb | 2 +- app/scenes/gameplay.rb | 2 +- app/scenes/paused.rb | 2 +- app/scenes/settings.rb | 2 +- app/tick.rb | 4 +- app/util/input.rb | 109 ++++++++++++++++++++++++++ app/{ => util}/music.rb | 0 app/{ => util}/sound.rb | 0 app/{ => util}/sprite.rb | 0 app/{ => util}/util.rb | 0 15 files changed, 173 insertions(+), 123 deletions(-) rename app/{ => classes}/sound_instance.rb (100%) rename app/{ => classes}/sprite_instance.rb (100%) delete mode 100644 app/input.rb create mode 100644 app/keybindings.rb create mode 100644 app/util/input.rb rename app/{ => util}/music.rb (100%) rename app/{ => util}/sound.rb (100%) rename app/{ => util}/sprite.rb (100%) rename app/{ => util}/util.rb (100%) diff --git a/app/sound_instance.rb b/app/classes/sound_instance.rb similarity index 100% rename from app/sound_instance.rb rename to app/classes/sound_instance.rb diff --git a/app/sprite_instance.rb b/app/classes/sprite_instance.rb similarity index 100% rename from app/sprite_instance.rb rename to app/classes/sprite_instance.rb diff --git a/app/input.rb b/app/input.rb deleted file mode 100644 index c4135a9..0000000 --- a/app/input.rb +++ /dev/null @@ -1,110 +0,0 @@ -# efficient input helpers that all take `args.inputs` - -PRIMARY_KEYS = [:j, :z, :space] -def primary_down?(inputs) - PRIMARY_KEYS.any? { |k| inputs.keyboard.key_down.send(k) } || - inputs.controller_one.key_down&.a -end -def primary_down_or_held?(inputs) - primary_down?(inputs) || - PRIMARY_KEYS.any? { |k| inputs.keyboard.key_held.send(k) } || - (inputs.controller_one.connected && - inputs.controller_one.key_held.a) -end - -SECONDARY_KEYS = [:k, :x, :backspace] -def secondary_down?(inputs) - SECONDARY_KEYS.any? { |k| inputs.keyboard.key_down.send(k) } || - (inputs.controller_one.connected && - inputs.controller_one.key_down.b) -end -def secondary_down_or_held?(inputs) - secondary_down?(inputs) || - SECONDARY_KEYS.any? { |k| inputs.keyboard.key_held.send(k) } || - (inputs.controller_one.connected && - inputs.controller_one.key_held.b) -end - -PAUSE_KEYS= [:escape, :p] -def pause_down?(inputs) - PAUSE_KEYS.any? { |k| inputs.keyboard.key_down.send(k) } || - inputs.controller_one.key_down&.start -end - -# check for arrow keys, WASD, gamepad, and swipe up -def up?(args) - args.inputs.up || args.state.swipe.up -end - -# check for arrow keys, WASD, gamepad, and swipe down -def down?(args) - args.inputs.down || args.state.swipe.down -end - -# check for arrow keys, WASD, gamepad, and swipe left -def left?(args) - args.inputs.left || args.state.swipe.left -end - -# check for arrow keys, WASD, gamepad, and swipe right -def right?(args) - args.inputs.right || args.state.swipe.right -end - -# called by the main #tick method to keep track of swipes, you likely don't -# need to call this yourself -# -# to check for swipes outside of the directional methods above, use it like -# this: -# -# if args.state.swipe.up -# # do the thing -# end -# -def track_swipe(args) - return unless mobile? - - reset_swipe(args) if args.state.swipe.nil? || args.state.swipe.stop_tick - swipe = args.state.swipe - - if args.inputs.mouse.down - swipe.merge!({ - start_tick: args.state.tick_count, - start_x: args.inputs.mouse.x, - start_y: args.inputs.mouse.y, - }) - end - - if swipe.start_tick && swipe.start_x && swipe.start_y - p1 = [swipe.start_x, swipe.start_y] - p2 = [args.inputs.mouse.x, args.inputs.mouse.y] - dist = args.geometry.distance(p1, p2) - - if dist > 50 # min distance threshold - swipe.merge!({ - stop_x: p2[0], - stop_y: p2[1], - }) - - angle = args.geometry.angle_from(p1, p2) - swipe.angle = angle - swipe.dist = dist - swipe.stop_tick = args.state.tick_count - - if angle > 315 || swipe.angle < 45 - swipe.left = true - elsif angle >= 45 && angle <= 135 - swipe.down = true - elsif angle > 135 && angle < 225 - swipe.right = true - elsif angle >= 225 && angle <= 315 - swipe.up = true - end - end - end -end - -# reset the currently tracked swipe -def reset_swipe(args) - args.state.swipe = { up: false, down: false, right: false, left: false } -end diff --git a/app/keybindings.rb b/app/keybindings.rb new file mode 100644 index 0000000..36ff611 --- /dev/null +++ b/app/keybindings.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +# Set the default input / key bindings here +module Input + class << self + PRIMARY_KEYS = [:j, :z, :space] + SECONDARY_KEYS = [:k, :x, :backspace] + PAUSE_KEYS = [:escape, :p] + BINDINGS = { + primary: { + keyboard: %i[j z space], + controller_one: %i[a] + }, + secondary: { + keyboard: %i[k x backspace], + controller_one: %i[b] + }, + pause: { + keyboard: %i[escape p], + controller_one: %i[start] + }, + rotate_left: { + keyboard: %i[q j z space], + controller_one: %i[a l1] + }, + rotate_right: { + keyboard: %i[e x backspace], + controller_one: %i[b l2] + }, + up: { + keyboard: %i[w up], + controller_one: %i[up] + }, + down: { + keyboard: %i[s down], + controller_one: %i[down] + }, + left: { + keyboard: %i[a left], + controller_one: %i[left] + }, + right: { + keyboard: %i[d right], + controller_one: %i[right] + } + } + end +end diff --git a/app/main.rb b/app/main.rb index 1d2110d..5e2cff8 100644 --- a/app/main.rb +++ b/app/main.rb @@ -4,20 +4,23 @@ require 'lib/coalesce.rb' # then, some basic classes required for lists of assets -require 'app/sprite_instance.rb' -require 'app/sound_instance.rb' +require 'app/classes/sprite_instance.rb' +require 'app/classes/sound_instance.rb' # then, asset lists require 'sprites/_list.rb' require 'sounds/_list.rb' require 'music/_list.rb' +# then, default keybindings +require 'app/keybindings.rb' + # then, utility classes -require 'app/input.rb' -require 'app/sprite.rb' -require 'app/util.rb' -require 'app/sound.rb' -require 'app/music.rb' +require 'app/util/sprite.rb' +require 'app/util/sound.rb' +require 'app/util/music.rb' +require 'app/util/util.rb' +require 'app/util/input.rb' require 'app/constants.rb' require 'app/menu.rb' diff --git a/app/menu.rb b/app/menu.rb index 144cfdf..1a60961 100644 --- a/app/menu.rb +++ b/app/menu.rb @@ -93,7 +93,7 @@ module Menu end end - if primary_down?(args.inputs) + if Input.pressed?(args, :primary) Sound.play(args, :select) options[menu_state.current_option_i][:on_select].call(args) end diff --git a/app/scenes/gameplay.rb b/app/scenes/gameplay.rb index 626050a..49b408b 100644 --- a/app/scenes/gameplay.rb +++ b/app/scenes/gameplay.rb @@ -13,7 +13,7 @@ module Scene end # auto-pause & input-based pause - if !args.state.has_focus || pause_down?(args) + if !args.state.has_focus || Input.pressed?(args, :pause) return pause(args) end diff --git a/app/scenes/paused.rb b/app/scenes/paused.rb index a61d646..3eedb62 100644 --- a/app/scenes/paused.rb +++ b/app/scenes/paused.rb @@ -30,7 +30,7 @@ module Scene Music.pause(args) unless Music.stopped(args) - if secondary_down?(args.inputs) + if Input.pressed?(args, :secondary) Sound.play(args, :select) options.find { |o| o[:key] == :resume }[:on_select].call(args) diff --git a/app/scenes/settings.rb b/app/scenes/settings.rb index 6351ad3..a84d9d4 100644 --- a/app/scenes/settings.rb +++ b/app/scenes/settings.rb @@ -49,7 +49,7 @@ module Scene Menu.tick(args, :settings, options) - if secondary_down?(args.inputs) + if Input.pressed?(args, :secondary) Sound.play(args, :select) options.find { |o| o[:key] == :back }[:on_select].call(args) end diff --git a/app/tick.rb b/app/tick.rb index ac7f880..44a112f 100644 --- a/app/tick.rb +++ b/app/tick.rb @@ -1,6 +1,6 @@ # Code that only gets run once on game start def init(args) - reset_swipe(args) + Input.reset_swipe(args) GameSetting.load_settings(args) end @@ -13,7 +13,7 @@ def tick(args) args.state.has_focus ||= true Scene.push(args, :main_menu, reset: true) if !args.state.scene - track_swipe(args) if mobile? + Input.track_swipe(args) if mobile? Scene.send("tick_#{args.state.scene}", args) diff --git a/app/util/input.rb b/app/util/input.rb new file mode 100644 index 0000000..23be744 --- /dev/null +++ b/app/util/input.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +# Module for managing inputs. +module Input + class << self + + def input_interaction?(args, input, interaction) + BINDINGS[input].any? do |source, bindings| + bindings.any? do |k| + args.inputs.send(source).send(interaction).send(k) + end + end + end + + def pressed?(args, input) + input_interaction?(args, input, :key_down) + end + + def held?(args, input) + input_interaction?(args, input, :key_held) + end + + def released?(args, input) + input_interaction?(args, input, :key_up) + end + + def pressed_or_held?(args, input) + pressed?(args, input) || held?(args, input) + end + + # check for arrow keys, WASD, gamepad, and swipe up + def up?(args) + args.inputs.up || args.state.swipe.up + end + + # check for arrow keys, WASD, gamepad, and swipe down + def down?(args) + args.inputs.down || args.state.swipe.down + end + + # check for arrow keys, WASD, gamepad, and swipe left + def left?(args) + args.inputs.left || args.state.swipe.left + end + + # check for arrow keys, WASD, gamepad, and swipe right + def right?(args) + args.inputs.right || args.state.swipe.right + end + + # called by the main #tick method to keep track of swipes, you likely don't + # need to call this yourself + # + # to check for swipes outside of the directional methods above, use it like + # this: + # + # if args.state.swipe.up + # # do the thing + # end + # + def track_swipe(args) + return unless mobile? + + reset_swipe(args) if args.state.swipe.nil? || args.state.swipe.stop_tick + swipe = args.state.swipe + + if args.inputs.mouse.down + swipe.merge!({ + start_tick: args.state.tick_count, + start_x: args.inputs.mouse.x, + start_y: args.inputs.mouse.y, + }) + end + + if swipe.start_tick && swipe.start_x && swipe.start_y + p1 = [swipe.start_x, swipe.start_y] + p2 = [args.inputs.mouse.x, args.inputs.mouse.y] + dist = args.geometry.distance(p1, p2) + + if dist > 50 # min distance threshold + swipe.merge!({ + stop_x: p2[0], + stop_y: p2[1], + }) + + angle = args.geometry.angle_from(p1, p2) + swipe.angle = angle + swipe.dist = dist + swipe.stop_tick = args.state.tick_count + + if angle > 315 || swipe.angle < 45 + swipe.left = true + elsif angle >= 45 && angle <= 135 + swipe.down = true + elsif angle > 135 && angle < 225 + swipe.right = true + elsif angle >= 225 && angle <= 315 + swipe.up = true + end + end + end + end + + # reset the currently tracked swipe + def reset_swipe(args) + args.state.swipe = { up: false, down: false, right: false, left: false } + end + end +end diff --git a/app/music.rb b/app/util/music.rb similarity index 100% rename from app/music.rb rename to app/util/music.rb diff --git a/app/sound.rb b/app/util/sound.rb similarity index 100% rename from app/sound.rb rename to app/util/sound.rb diff --git a/app/sprite.rb b/app/util/sprite.rb similarity index 100% rename from app/sprite.rb rename to app/util/sprite.rb diff --git a/app/util.rb b/app/util/util.rb similarity index 100% rename from app/util.rb rename to app/util/util.rb