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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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] }
|
||||
|
||||
|
||||
+4
-3
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user