Refactor input handling: replace hardcoded key inputs with configurable key bindings for character movement, inventory navigation, and actions; enhance settings scene with key rebind functionality and add credits scene.
This commit is contained in:
@@ -1 +1,2 @@
|
||||
*.old.*
|
||||
config.json
|
||||
@@ -0,0 +1,44 @@
|
||||
class Credits < Scene
|
||||
def initialize
|
||||
super
|
||||
@font = Gosu::Font.new(32, name: "assets/fonts/tn.ttf")
|
||||
@small_font = Gosu::Font.new(20, name: "assets/fonts/tn.ttf")
|
||||
end
|
||||
|
||||
def update(_dt)
|
||||
# nothing needed
|
||||
end
|
||||
|
||||
def draw
|
||||
Gosu.draw_rect(0, 0, *SCREEN_SIZE, Gosu::Color.new(0xFF131313))
|
||||
|
||||
# title (centered)
|
||||
title = "Credits"
|
||||
tx = (720 - @font.text_width(title)) / 2
|
||||
@font.draw_text(title, tx, 80, 1, 1, 1, Gosu::Color::YELLOW)
|
||||
|
||||
# main content
|
||||
# this is kinda useless and i could just hardcode the positions, or even the image itself but yeah
|
||||
lines = [
|
||||
"Developer: Syed Daanish",
|
||||
"Artist: Syed Daanish"
|
||||
]
|
||||
|
||||
lines.each_with_index do |line, i|
|
||||
x = (720 - @small_font.text_width(line)) / 2
|
||||
y = 180 + i * 40
|
||||
@small_font.draw_text(line, x, y, 1, 1, 1, Gosu::Color::WHITE)
|
||||
end
|
||||
|
||||
# hint at bottom
|
||||
hint = "Press ESC to return"
|
||||
hx = (720 - @small_font.text_width(hint)) / 2
|
||||
@small_font.draw_text(hint, hx, 420, 1, 1, 1, Gosu::Color::GRAY)
|
||||
end
|
||||
|
||||
def button_down(id, _pos)
|
||||
if id == Gosu::KB_ESCAPE || id == Gosu::KB_RETURN
|
||||
$bus.emit(:change_scene, Menu)
|
||||
end
|
||||
end
|
||||
end
|
||||
+4
-4
@@ -76,10 +76,10 @@ class Character
|
||||
dx = 0.0
|
||||
dy = 0.0
|
||||
|
||||
dx -= 1 if Gosu.button_down?(Gosu::KB_A)
|
||||
dx += 1 if Gosu.button_down?(Gosu::KB_D)
|
||||
dy -= 1 if Gosu.button_down?(Gosu::KB_W)
|
||||
dy += 1 if Gosu.button_down?(Gosu::KB_S)
|
||||
dx -= 1 if Gosu.button_down?($bus.get(:settings, :leftward))
|
||||
dx += 1 if Gosu.button_down?($bus.get(:settings, :rightward))
|
||||
dy -= 1 if Gosu.button_down?($bus.get(:settings, :forward))
|
||||
dy += 1 if Gosu.button_down?($bus.get(:settings, :backward))
|
||||
|
||||
moving = dx != 0 || dy != 0
|
||||
|
||||
|
||||
+3
-3
@@ -35,12 +35,12 @@ class HealthBar
|
||||
|
||||
def draw
|
||||
# Draw the background of the health bar (red)
|
||||
Gosu.draw_rect(SCREEN_SIZE[0] - 100 - 10, 180, 100, 10, Gosu::Color::RED)
|
||||
Gosu.draw_rect(SCREEN_SIZE[0] - 100 - 10, 180, 100, 10, Gosu::Color::RED, Float::INFINITY)
|
||||
|
||||
# Draw the foreground of the health bar (green) based on current health
|
||||
health_width = (health.to_f / max_health) * 100
|
||||
Gosu.draw_rect(SCREEN_SIZE[0] - 100 - 10, 180, health_width, 10, Gosu::Color::GREEN)
|
||||
Gosu.draw_rect(SCREEN_SIZE[0] - 100 - 10, 180, health_width, 10, Gosu::Color::GREEN, Float::INFINITY)
|
||||
|
||||
@heart_image.draw(SCREEN_SIZE[0] - 100 - 20, 173, 1, 1.5, 1.5)
|
||||
@heart_image.draw(SCREEN_SIZE[0] - 100 - 20, 173, Float::INFINITY, 1.5, 1.5)
|
||||
end
|
||||
end
|
||||
@@ -94,19 +94,19 @@ class Inventory
|
||||
when Gosu::KB_1 then @inventory_selected = :occams_razor
|
||||
when Gosu::KB_2 then @inventory_selected = :quantum_bow
|
||||
when Gosu::KB_3 then @inventory_selected = :blade_of_recursion
|
||||
when Gosu::KB_DOWN
|
||||
when $bus.get(:settings, :"inventory down")
|
||||
row, col = find_slot(@inventory_selected)
|
||||
@inventory_selected = @grid[(row + 1) % @grid.size][col][0]
|
||||
when Gosu::KB_UP
|
||||
when $bus.get(:settings, :"inventory up")
|
||||
row, col = find_slot(@inventory_selected)
|
||||
@inventory_selected = @grid[(row - 1) % @grid.size][col][0]
|
||||
when Gosu::KB_LEFT
|
||||
when $bus.get(:settings, :"inventory left")
|
||||
row, col = find_slot(@inventory_selected)
|
||||
@inventory_selected = @grid[row][(col - 1) % @grid[row].size][0]
|
||||
when Gosu::KB_RIGHT
|
||||
when $bus.get(:settings, :"inventory right")
|
||||
row, col = find_slot(@inventory_selected)
|
||||
@inventory_selected = @grid[row][(col + 1) % @grid[row].size][0]
|
||||
when Gosu::KB_RETURN
|
||||
when $bus.get(:settings, :craft)
|
||||
craft(@inventory_selected, ctrl: Gosu.button_down?(Gosu::KB_RIGHT_CONTROL) || Gosu.button_down?(Gosu::KB_LEFT_CONTROL))
|
||||
else
|
||||
return false
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ class Prop
|
||||
end
|
||||
|
||||
def update(dt)
|
||||
return unless Gosu.button_down?(Gosu::MS_LEFT) || Gosu.button_down?(Gosu::KB_X)
|
||||
return unless Gosu.button_down?(Gosu::MS_LEFT) || Gosu.button_down?($bus.get(:settings, :break))
|
||||
|
||||
player_x, player_y = $bus.get(:player_position) || [0, 0]
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ class PropsHandler
|
||||
@grid.delete([prop.x, prop.y])
|
||||
end
|
||||
end
|
||||
if Gosu.button_down?(Gosu::KB_P) # place selected if it is a placeable item
|
||||
if Gosu.button_down?($bus.get(:settings, :place))
|
||||
selected_item = $bus.get(:selected_item)
|
||||
if selected_item == :torch
|
||||
player_x, player_y = $bus.get(:player_position) || [0, 0]
|
||||
|
||||
+3
-3
@@ -27,7 +27,7 @@ class Game < Scene
|
||||
|
||||
@camera = [0, 0]
|
||||
|
||||
$bus.emit(:log, "Welcome to the Mist! Use WASD to move, SPACE or left-click to attack with your equipped weapon, and ESC to return to the menu.")
|
||||
$bus.emit(:log, "Welcome to the Mist!")
|
||||
|
||||
$bus.on(:player_move) do |pos|
|
||||
@camera = pos
|
||||
@@ -55,7 +55,7 @@ class Game < Scene
|
||||
@enemies.draw
|
||||
@props.draw
|
||||
@traps.draw
|
||||
$bus.emit(:shade) if $bus.get(:settings, :fog)
|
||||
$bus.emit(:shade)
|
||||
@hud.draw
|
||||
@weapons.draw
|
||||
draw_debug! if $bus.get(:settings, :debug)
|
||||
@@ -98,7 +98,7 @@ class Game < Scene
|
||||
def button_down(id, pos)
|
||||
# Pressing ESC returns to the menu, this is bad but I don't have time to make a proper pause menu,
|
||||
# as the game has no persistent state outside of the current scene, just returning to the menu resets everything
|
||||
return $bus.emit(:change_scene, Menu.new) if id == Gosu::KB_ESCAPE
|
||||
return $bus.emit(:change_scene, Menu) if id == Gosu::KB_ESCAPE
|
||||
|
||||
return if @hud.button_down(id, pos)
|
||||
return if @props.button_down(id, pos)
|
||||
|
||||
@@ -27,7 +27,7 @@ class WeaponHandler
|
||||
|
||||
weapon = @weapons[selected_item]
|
||||
if $bus.get(:count, selected_item) > 0
|
||||
if id == Gosu::KB_SPACE
|
||||
if id == $bus.get(:settings, :attack)
|
||||
player_x, player_y = $bus.get(:player_position)
|
||||
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
||||
mouse_x, mouse_y = $bus.get(:mouse_pos) || [0, 0]
|
||||
|
||||
@@ -2,6 +2,7 @@ class Menu < Scene
|
||||
OPTIONS = {
|
||||
"Start" => -> { $bus.emit(:change_scene, Game) },
|
||||
"Settings" => -> { $bus.emit(:change_scene, Settings) },
|
||||
"Credits" => -> { $bus.emit(:change_scene, Credits) },
|
||||
"Quit" => -> { $bus.emit(:quit_game) }
|
||||
}.freeze
|
||||
|
||||
|
||||
@@ -5,28 +5,55 @@ N, S, W, E = 1, 2, 4, 8
|
||||
|
||||
# Config module to hold global settings that can be toggled in the settings scene, and accessed anywhere else in the code via the event bus
|
||||
module Config
|
||||
@config = {
|
||||
debug: ARGV.include?("--debug"),
|
||||
fog: true,
|
||||
torches_lightup: true,
|
||||
@debug = false
|
||||
|
||||
@keybinds = {
|
||||
forward: Gosu::KB_W,
|
||||
backward: Gosu::KB_S,
|
||||
leftward: Gosu::KB_A,
|
||||
rightward: Gosu::KB_D,
|
||||
break: Gosu::KB_X,
|
||||
attack: Gosu::KB_SPACE,
|
||||
place: Gosu::KB_P,
|
||||
"inventory up": Gosu::KB_UP,
|
||||
"inventory down": Gosu::KB_DOWN,
|
||||
"inventory right": Gosu::KB_RIGHT,
|
||||
"inventory left": Gosu::KB_LEFT,
|
||||
craft: Gosu::KB_RETURN,
|
||||
}
|
||||
|
||||
if File.exist?("config.json")
|
||||
data = JSON.parse(File.read("config.json"))
|
||||
@config.merge!(data.transform_keys(&:to_sym))
|
||||
@debug = data["debug"] || false
|
||||
@keybinds.merge!(data["keybinds"]&.transform_keys(&:to_sym) || {})
|
||||
end
|
||||
|
||||
$bus.on(:settings, :master) { |k| @config[k] }
|
||||
$bus.on(:settings, :master) { |k| k == :debug ? @debug : @keybinds[k] }
|
||||
|
||||
module_function
|
||||
|
||||
def toggle(key)
|
||||
@config[key] = !@config[key]
|
||||
def bindings
|
||||
@keybinds
|
||||
end
|
||||
|
||||
def debug
|
||||
@debug
|
||||
end
|
||||
|
||||
def debug=(value)
|
||||
@debug = value
|
||||
end
|
||||
|
||||
def set_key(action, key)
|
||||
@keybinds[action] = key
|
||||
end
|
||||
|
||||
def persist!
|
||||
File.open("config.json", "w") do |f|
|
||||
f.write(JSON.pretty_generate(@config))
|
||||
f.write(JSON.pretty_generate({
|
||||
keybinds: @keybinds,
|
||||
debug: @debug
|
||||
}))
|
||||
end
|
||||
end
|
||||
end
|
||||
+65
-4
@@ -1,15 +1,76 @@
|
||||
class Settings < Scene
|
||||
def initialize
|
||||
super
|
||||
@font = Gosu::Font.new(24)
|
||||
@font_title = Gosu::Font.new(28, name: "assets/fonts/tn.ttf")
|
||||
@font = Gosu::Font.new(20, name: "assets/fonts/tn.ttf")
|
||||
@selected = 0
|
||||
@waiting_for_key = nil
|
||||
end
|
||||
|
||||
def draw
|
||||
Gosu.draw_rect(0, 0, SCREEN_SIZE[0], SCREEN_SIZE[1], Gosu::Color::BLACK)
|
||||
@font.draw_text("Settings Scene - Press ESC to return to Menu", 50, 50, 1, 1, 1, Gosu::Color::WHITE)
|
||||
Gosu.draw_rect(0, 0, *SCREEN_SIZE, Gosu::Color.new(0xFF131313))
|
||||
|
||||
title = "Settings"
|
||||
@font_title.draw_text(title, center_x(title), 40, 1, 1, 1, Gosu::Color::YELLOW)
|
||||
|
||||
debug_option = "Debug Mode".ljust(15) + " : " + "#{Config.debug ? 'ON' : 'OFF'}".rjust(12)
|
||||
debug_option = "> #{debug_option} <" if @selected == 0
|
||||
@font.draw_text(debug_option, center_x(debug_option), 90, 1, 1, 1, @selected == 0 ? Gosu::Color::YELLOW : Gosu::Color::WHITE)
|
||||
|
||||
Config.bindings.each_with_index do |opt, i|
|
||||
y = 120 + i * 25
|
||||
selected = (i == @selected - 1)
|
||||
|
||||
text = "#{opt[0].to_s.ljust(15)} : #{Gosu.button_name(opt[1]).rjust(12)}"
|
||||
text = "> #{text} <" if selected
|
||||
|
||||
color = selected ? Gosu::Color::YELLOW : Gosu::Color::WHITE
|
||||
@font.draw_text(text, center_x(text), y, 1, 1, 1, color)
|
||||
end
|
||||
|
||||
if @waiting_for_key
|
||||
msg = "Press a key... (ESC to cancel)"
|
||||
@font.draw_text(msg, center_x(msg), 430, 1, 1, 1, Gosu::Color::GRAY)
|
||||
else
|
||||
hint = "Enter: Select | ESC: Back"
|
||||
@font.draw_text(hint, center_x(hint), 430, 1, 1, 1, Gosu::Color::GRAY)
|
||||
end
|
||||
end
|
||||
|
||||
def button_down(id, _pos)
|
||||
$bus.emit(:change_scene, Menu) if id == Gosu::KB_ESCAPE
|
||||
# waiting for keybind input
|
||||
if @waiting_for_key
|
||||
if [Gosu::KB_ESCAPE].include?(id)
|
||||
@waiting_for_key = nil
|
||||
return
|
||||
end
|
||||
Config.set_key(@waiting_for_key, id)
|
||||
Config.persist!
|
||||
@waiting_for_key = nil
|
||||
return
|
||||
end
|
||||
|
||||
case id
|
||||
when Gosu::KB_UP
|
||||
@selected = (@selected - 1) % (Config.bindings.size + 1)
|
||||
when Gosu::KB_DOWN
|
||||
@selected = (@selected + 1) % (Config.bindings.size + 1)
|
||||
when Gosu::KB_RETURN
|
||||
if @selected == 0
|
||||
Config.debug = !Config.debug
|
||||
Config.persist!
|
||||
else
|
||||
@waiting_for_key = Config.bindings.keys[@selected]
|
||||
end
|
||||
when Gosu::KB_ESCAPE
|
||||
Config.persist!
|
||||
$bus.emit(:change_scene, Menu)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def center_x(text)
|
||||
(SCREEN_SIZE[0] - @font.text_width(text)) / 2
|
||||
end
|
||||
end
|
||||
@@ -1,11 +1,13 @@
|
||||
require 'opengl'
|
||||
require 'glu'
|
||||
require 'gosu'
|
||||
require 'json'
|
||||
|
||||
require_relative 'settings/configuration'
|
||||
require_relative 'utils/utils'
|
||||
require_relative 'utils/scene'
|
||||
require_relative 'settings/scene'
|
||||
require_relative 'credits/scene'
|
||||
require_relative 'menu/scene'
|
||||
require_relative 'game_over/scene'
|
||||
require_relative 'game/scene'
|
||||
@@ -68,13 +70,11 @@ class Window < Gosu::Window
|
||||
|
||||
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
||||
torch_lights = []
|
||||
# Only calculate torch lights if the setting is enabled, to save performance
|
||||
if $bus.get(:settings, :torches_lightup)
|
||||
torches = $bus.get(:nearby_torches,
|
||||
[cam_x - SCREEN_SIZE[0], cam_y - SCREEN_SIZE[1], SCREEN_SIZE[0] * 4, SCREEN_SIZE[1] * 4]
|
||||
) || []
|
||||
torch_lights = torches.map { |t| [t[0] - cam_x, SCREEN_SIZE[1] - (t[1] - cam_y)] }.flatten
|
||||
end
|
||||
|
||||
torches = $bus.get(:nearby_torches,
|
||||
[cam_x - SCREEN_SIZE[0], cam_y - SCREEN_SIZE[1], SCREEN_SIZE[0] * 4, SCREEN_SIZE[1] * 4]
|
||||
) || []
|
||||
torch_lights = torches.map { |t| [t[0] - cam_x, SCREEN_SIZE[1] - (t[1] - cam_y)] }.flatten
|
||||
|
||||
lorentz_field = $bus.get(:lorentz_field) || 0.0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user