From f54679de612eed99b3b033086e9c9d8b51a70d18 Mon Sep 17 00:00:00 2001 From: Daanish Date: Sat, 28 Mar 2026 20:46:32 +0000 Subject: [PATCH] Refactor game state and HUD: - Removed the State class as it was no longer needed. - Updated the MazeData class to improve output formatting. - Added new assets for HUD background and foreground. - Implemented Inventory class to manage crafting and item selection. - Created HUDLayer class to handle drawing the HUD and inventory interactions. --- assets/images/hud.aseprite | Bin 0 -> 2550 bytes assets/images/hud.png | Bin 0 -> 4170 bytes assets/images/hud_fg.aseprite | Bin 0 -> 2513 bytes assets/images/hud_fg.png | Bin 0 -> 5026 bytes assets/images/inventory.aseprite | Bin 3417 -> 0 bytes assets/images/inventory.png | Bin 6678 -> 0 bytes game/enemy/handler.rb | 8 +- game/hud.rb | 9 -- game/hud/inventory.rb | 167 +++++++++++++++++++++++++++++++ game/hud/layer.rb | 21 ++++ game/maze.rb | 1 - game/scene.rb | 7 +- game/state.rb | 42 -------- utils/maze.rb | 2 +- 14 files changed, 197 insertions(+), 60 deletions(-) create mode 100644 assets/images/hud.aseprite create mode 100644 assets/images/hud.png create mode 100644 assets/images/hud_fg.aseprite create mode 100644 assets/images/hud_fg.png delete mode 100644 assets/images/inventory.aseprite delete mode 100644 assets/images/inventory.png delete mode 100644 game/hud.rb create mode 100644 game/hud/inventory.rb create mode 100644 game/hud/layer.rb delete mode 100644 game/state.rb diff --git a/assets/images/hud.aseprite b/assets/images/hud.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..35df33b70ac13906463fdd1c76bec95b75982e04 GIT binary patch literal 2550 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
    `4wug(2^>WTcab@h4A z%d2d+-{z_R9-rqM`+sYE{lY1tdGk)cQ-4wo`N*S>WB_w1Lw zUspYwao47N*X!E+MfD%W>jJzqpYE^!b1?4R{oD!npBl?s-#*XCFsB&Y)>*Ny@m*-zL)h# zv^fLAGH?P|Fq8L7`2Vl67o&EHj7_xJ1d`6KJ}$9-0l12wEljZub*r4 z=UGSFTiNaW_v3Q#{QF=3F8-hQT3P*j$op6AQoEvl36+jsYTEhB^3nOnKAtQp|@mDi+n>o*-U28Y+z z@<6^f4ZZJh-)>jv*NrXU)IakTW2~3v^m%_8J~J{zaLeIs86CK`D!=06p{4Ds_o=^r z{;#=O`~O`ghKxo~LB~?{+gS_LY^=RoJ@NXxJyj82n&;!{&ixei0k`j%7~FjGRrF@Id%LP*yfmMpd2ZY9T^~13pMU%H>wDdM%AQ|! zetzA$zUcdp4aaseFgR}nCDeg$Pa<3ZkEo?nJ{<}6U;pdcn#S$#*LS7$cPqbM`1$qR{5!UGYYO!k4g`RcxdJGy4-#U-)>qPT zdkS7AYA&_;c;)iyeWuwD*6u#ObV|@W`yJaq-PdJk5W4}Xverx6SO46(ci+3cC$h`q zY)k6)epWB<=g*$Q&0rt`&WWTqi)p7LXYH>xas8O89j~f4)uH-@s9K+BMF-k`Ny@g} Uwb_*NY&uAjr>mdKI;Vst0P-~fd;kCd literal 0 HcmV?d00001 diff --git a/assets/images/hud_fg.aseprite b/assets/images/hud_fg.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..e015cb2d8e59dfea9d5eb662aa2041647552b0dc GIT binary patch literal 2513 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 literal 0 HcmV?d00001 diff --git a/assets/images/inventory.aseprite b/assets/images/inventory.aseprite deleted file mode 100644 index 29efdf3438df93cdc9f26cdd045407862a33ae66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3417 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 diff --git a/assets/images/inventory.png b/assets/images/inventory.png deleted file mode 100644 index dec661506d40933aa315a18dc71db32efec0ec66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6678 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 V@Av!sVl)65?CI*~vd$@?2>_AhGE@Kn diff --git a/game/enemy/handler.rb b/game/enemy/handler.rb index 13f211a..ac5a956 100644 --- a/game/enemy/handler.rb +++ b/game/enemy/handler.rb @@ -12,10 +12,10 @@ class EnemyHandler def spawn! # For now, just spawn a single enemy at a fixed location - start_room_coords = $bus.get(:start_room_coords) - if @enemies.empty? - @enemies << Enemy.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 1 + 4) * 60 + 30) - end + #start_room_coords = $bus.get(:start_room_coords) + #if @enemies.empty? + # @enemies << Enemy.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 1 + 4) * 60 + 30) + #end end def draw diff --git a/game/hud.rb b/game/hud.rb deleted file mode 100644 index 9624fef..0000000 --- a/game/hud.rb +++ /dev/null @@ -1,9 +0,0 @@ -class HUD - def initialize - @inventory_bg = Gosu::Image.new("assets/images/inventory.png", retro: true) - end - - def draw - @inventory_bg.draw(0, 0, Float::INFINITY) - end -end \ No newline at end of file diff --git a/game/hud/inventory.rb b/game/hud/inventory.rb new file mode 100644 index 0000000..cbe4d68 --- /dev/null +++ b/game/hud/inventory.rb @@ -0,0 +1,167 @@ +class Inventory + OFFSET = [27, 34] + COLS = 3 + ROW_HEIGHT = 48 + COL_WIDTH = 40 + + CRAFT_RECIPES = { + lorentz_field: { wood: 16, metal: 8, science: 2 }, + torch: { wood: 8 }, + radar: { wood: 2, metal: 8, science: 2 }, + landmine: { wood: 16, metal: 8 }, + shrodingers_mine: { wood: 16, metal: 8, science: 1 }, + event_horizon: { metal: 16, science: 2 }, + occams_razor: { wood: 2, metal: 1 }, + quantum_bow: { wood: 32, metal: 16, science: 8 }, + blade_of_recursion: { wood: 32, metal: 8, science: 4 } + }.freeze + + def initialize + items = [ + :wood, :metal, :science, + :lorentz_field, :torch, :radar, + :landmine, :shrodingers_mine, :event_horizon, + :occams_razor, :quantum_bow, :blade_of_recursion + ] + + @grid = items.each_slice(COLS).map do |slice| + slice.map do |type| + [type, initial_amount_max(type)] + end + end + + @inventory_selected = :wood + @font = Gosu::Font.new(8, name: "assets/fonts/tn.ttf") + + $bus.on(:obtain) do |type, amount| + row, col = find_slot(type) + next unless row + @grid[row][col][1][0] += amount + @grid[row][col][1][0] = @grid[row][col][1][1] if @grid[row][col][1][0] > @grid[row][col][1][1] + end + end + + # Draw the inventory + def draw + x_start, y_start = OFFSET + y = y_start + + @grid.each do |row| + x = x_start + row.each do |type, (amount, max)| + # Background highlighting + if type == @inventory_selected + Gosu.draw_rect(x + 2, y + 2, 32, 32, Gosu::Color.new(255 * 0.7, 249, 208, 64), Float::INFINITY) + elsif amount == max + Gosu.draw_rect(x + 2, y + 2, 32, 32, Gosu::Color.new(255 * 0.7, 128, 239, 128), Float::INFINITY) + end + + # Empty overlay + Gosu.draw_rect(x + 2, y + 2, 32, 32, Gosu::Color.new(255 * 0.6, 0, 0, 0), Float::INFINITY) if amount == 0 + + # Amount text + @font.draw_text("#{amount.to_s.rjust(3)}/#{max.to_s.ljust(3)}", x, y + 37, Float::INFINITY, 1, 1, Gosu::Color::WHITE) + x += COL_WIDTH + end + y += ROW_HEIGHT + end + end + + # Handle input + def button_down(id, pos) + case id + when Gosu::MS_LEFT, Gosu::MS_RIGHT + mouse_click(*pos, id) + 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_C + row, col = find_slot(@inventory_selected) + @inventory_selected = @grid[(row + 1) % @grid.size][col][0] + when Gosu::KB_V + row, col = find_slot(@inventory_selected) + @inventory_selected = @grid[row][(col + 1) % @grid[row].size][0] + end + end + + # Mouse click detection + def mouse_click(mx, my, id) + x_start, y_start = OFFSET + row_idx = ((my - y_start) / ROW_HEIGHT).floor + col_idx = ((mx - x_start) / COL_WIDTH).floor + + return if row_idx < 0 || row_idx >= @grid.size + return if col_idx < 0 || col_idx >= @grid[row_idx].size + + type, (amount, max) = @grid[row_idx][col_idx] + + if id == Gosu::MS_LEFT + @inventory_selected = type + elsif id == Gosu::MS_RIGHT + if DEBUG && [:wood, :metal, :science].include?(type) + @grid[row_idx][col_idx][1][0] = max + else + craft(type, ctrl: Gosu.button_down?(Gosu::KB_RIGHT_CONTROL) || Gosu.button_down?(Gosu::KB_LEFT_CONTROL)) + end + end + end + + private + + def craft(type, ctrl: false) + return unless CRAFT_RECIPES.key?(type) + + recipe = CRAFT_RECIPES[type] + + # How many we can craft + possible_counts = recipe.map { |res, req| grid_value(res) / req } + max_possible = possible_counts.min + return if max_possible == 0 + + craft_amount = ctrl ? max_possible : 1 + + # Subtract resources + recipe.each do |res, req| + row, col = find_slot(res) + @grid[row][col][1][0] -= req * craft_amount + end + + # Add crafted item + row, col = find_slot(type) + @grid[row][col][1][0] += craft_amount + # Clamp to max + @grid[row][col][1][0] = @grid[row][col][1][1] if @grid[row][col][1][0] > @grid[row][col][1][1] + end + + # Helper to get amount of resource + def grid_value(type) + row, col = find_slot(type) + return 0 unless row + @grid[row][col][1][0] + end + + # Initial amount/max mapping + def initial_amount_max(type) + case type + when :wood, :metal then [0, 64] + when :science then [0, 32] + when :lorentz_field then [0, 4] + when :torch then [0, 8] + when :radar then [0, 4] + when :landmine, :shrodingers_mine then [0, 8] + when :event_horizon then [0, 4] + when :occams_razor, :quantum_bow, :blade_of_recursion then [0, 1] + else [0, 0] + end + end + + # Find slot in grid for a type + def find_slot(type) + @grid.each_with_index do |row, r| + row.each_with_index do |(t, _), c| + return [r, c] if t == type + end + end + nil + end +end \ No newline at end of file diff --git a/game/hud/layer.rb b/game/hud/layer.rb new file mode 100644 index 0000000..16e1342 --- /dev/null +++ b/game/hud/layer.rb @@ -0,0 +1,21 @@ +require_relative "inventory" + +class HUDLayer + def initialize + @hud_bg = Gosu::Image.new("assets/images/hud.png", retro: true) + @hud_fg = Gosu::Image.new("assets/images/hud_fg.png", retro: true) + @inventory = Inventory.new + end + + def draw + @hud_bg.draw(0, 0, Float::INFINITY) + + @inventory.draw + + @hud_fg.draw(0, 0, Float::INFINITY) + end + + def button_down(id, pos) + @inventory.button_down(id, pos) + end +end \ No newline at end of file diff --git a/game/maze.rb b/game/maze.rb index 51ea6f4..661f643 100644 --- a/game/maze.rb +++ b/game/maze.rb @@ -4,7 +4,6 @@ class Maze def initialize @maze = MazeData.new(80, 80) @spritesheet = Gosu::Image.load_tiles("assets/images/walls.png", 20, 40, retro: true) - puts @spritesheet.size $bus.on(:maze_size) { [80, 80] } diff --git a/game/scene.rb b/game/scene.rb index bbe690b..6d8a307 100644 --- a/game/scene.rb +++ b/game/scene.rb @@ -1,6 +1,5 @@ -require_relative 'state' require_relative 'maze' -require_relative 'hud' +require_relative 'hud/layer' require_relative 'props/handler' require_relative 'enemy/handler' require_relative 'character' @@ -19,7 +18,7 @@ class Game < Scene @enemies = EnemyHandler.new @props = PropsHandler.new - @hud = HUD.new + @hud = HUDLayer.new @camera = [0, 0] @@ -152,5 +151,7 @@ class Game < Scene def button_down(id, pos) return $bus.emit(:change_scene, Menu.new) if id == Gosu::KB_ESCAPE + + @hud.button_down(id, pos) end end \ No newline at end of file diff --git a/game/state.rb b/game/state.rb deleted file mode 100644 index efba277..0000000 --- a/game/state.rb +++ /dev/null @@ -1,42 +0,0 @@ -class State - # This class holds state information - # for example the player inventory / items - # also their health, stealth, and memory bars - # it can handle mouse input for inventory management and item usage - # it can also handle keyboard input for quick item usage - - def initialize - @inventory = { - # basic resources - :wood => 0, - :metal => 0, - :science => 0, - - # nuetrals - :torch => 0, - :radar => 0, - - # placeable weapons - :landmine => 0, - :shrodingers_mine => 0, - :event_horizon => 0, - - # attack weapons - :occams_razor => 0, - :quantum_bow => 0, - :blade_of_recursion => 0, - - # utility weapon - :lorentz_field => 0 - } - @inventory_selected = :wood - @upgrades = [] - @health = 100 - @stealth = 100 - @memory = 256 - - $bus.on(:obtain) do |type, amount| - @inventory[type] += amount if @inventory.key?(type) - end - end -end \ No newline at end of file diff --git a/utils/maze.rb b/utils/maze.rb index 12bf6e5..c1182e9 100644 --- a/utils/maze.rb +++ b/utils/maze.rb @@ -160,7 +160,7 @@ class MazeData (0...self.width).each do |x| print wall_chars[wall_type(x, y)] end - puts + print "\n" end end