Add new assets and implement minimap functionality

- Added new image assets for game over screens: `game_over_dead_bg.png`, `game_over_victory_bg.png`, and their respective Aseprite files.
- Introduced a new `Minimap` class to manage torch placement and rendering on the minimap.
- Implemented methods for adding and removing torches, updating the grid area, and drawing the minimap based on the current state of the game.
- Enhanced the minimap display with color coding for walls, empty spaces, and torches.
This commit is contained in:
2026-04-03 02:51:11 +01:00
parent b325b35c88
commit 222b28d196
24 changed files with 209 additions and 32 deletions
+7 -2
View File
@@ -5,6 +5,8 @@ class HealthBar
@max_health = max_health
@health = max_health
@heart_image = Gosu::Image.new("assets/images/heart.png", retro: true)
$bus.on(:blast) do |x, y, radius, damage, safety|
next if safety == :safe
@@ -21,6 +23,7 @@ class HealthBar
@health -= amount
if @health <= 0
@health = 0
$is_dead = true
$bus.emit(:change_scene, GameOver)
end
end
@@ -32,10 +35,12 @@ class HealthBar
def draw
# Draw the background of the health bar (red)
Gosu.draw_rect(30, 10, 100, 10, Gosu::Color::RED)
Gosu.draw_rect(SCREEN_SIZE[0] - 100 - 10, 180, 100, 10, Gosu::Color::RED)
# Draw the foreground of the health bar (green) based on current health
health_width = (health.to_f / max_health) * 100
Gosu.draw_rect(30, 10, health_width, 10, Gosu::Color::GREEN)
Gosu.draw_rect(SCREEN_SIZE[0] - 100 - 10, 180, health_width, 10, Gosu::Color::GREEN)
@heart_image.draw(SCREEN_SIZE[0] - 100 - 20, 173, 1, 1.5, 1.5)
end
end
+17
View File
@@ -1,6 +1,7 @@
require_relative "inventory"
require_relative "health"
require_relative "logs"
require_relative "minimap"
class HUDLayer
def initialize
@@ -9,6 +10,9 @@ class HUDLayer
@inventory = Inventory.new
@health = HealthBar.new(100)
@logs = GameLogger.new
@minimap = Minimap.new
@direction_sprite = Gosu::Image.new("assets/images/direction.png", retro: true)
$bus.on(:enemy_attack) do |damage|
@health.take_damage(damage)
@@ -26,6 +30,19 @@ class HUDLayer
@health.draw
@logs.draw
player_x, player_y = $bus.get(:player_position) || [0, 0]
tile_x = ((player_x - 90) / 120).round
tile_y = ((player_y - 90) / 120).round
center_x = tile_x * 2 + 1
center_y = tile_y * 2 + 1
@minimap.draw(center_x, center_y)
if $bus.get(:radar_triangulation?, player_x, player_y)
exit_x, exit_y = $bus.get(:exit_room_coords) || [0, 0]
angle_to_exit = Math.atan2(exit_y - tile_x, exit_x - tile_y) * 180 / Math::PI
@direction_sprite.draw_rot(SCREEN_SIZE[0] / 2, SCREEN_SIZE[1] / 2, Float::INFINITY, angle_to_exit, 0.5, 0.5, 5, 5)
end
@hud_fg.draw(0, 0, Float::INFINITY)
end
+92
View File
@@ -0,0 +1,92 @@
class Minimap
CELL_SIZE = 3 # pixels per minimap cell
RADIUS = 10 # cells around torch to update
# Please ignore my overuse of that stupid ruby conditional assignment operator
def initialize
@torches = []
@grid_cache = {}
$bus.on(:torch_placed) do |gx, gy|
add_torch(gx, gy)
end
$bus.on(:torch_removed) do |gx, gy|
remove_torch(gx, gy)
end
end
def add_torch(x, y)
x, y = x * 2 + 1, y * 2 + 1 # convert from room coords to grid coords
@torches << [x, y]
update_grid_area(x, y)
end
def remove_torch(x, y)
x, y = x * 2 + 1, y * 2 + 1
@torches.delete([x, y])
update_grid_area(x, y)
end
# Update only cells in 10-cell box around given gx,gy
def update_grid_area(cx, cy)
(cx-RADIUS..cx+RADIUS).each do |gx|
(cy-RADIUS..cy+RADIUS).each do |gy|
if @torches.any? { |tx, ty| (gx - tx).abs <= RADIUS && (gy - ty).abs <= RADIUS }
@grid_cache[[gx, gy]] = if @torches.include?([gx, gy])
:torch
elsif $bus.get(:maze_wall?, gx, gy)
:wall
else
:empty
end
else
@grid_cache.delete([gx, gy])
end
end
end
end
def draw(center_x, center_y)
half_size = 25 # 40 cells → 20 each side
map_max = $bus.get(:maze_size).map { |s| s * 2 - 1 } || 0
offset_x = SCREEN_SIZE[0] - CELL_SIZE * (half_size * 2 + 1) - 10
offset_y = 10
size_in_cells = 2 * half_size + 1
width = size_in_cells * CELL_SIZE
height = size_in_cells * CELL_SIZE
# border
Gosu.draw_rect(offset_x - 3, offset_y - 3, width + 6, height + 6, Gosu::Color.new(0xFFa9b2a2), Float::INFINITY)
(-half_size..half_size).each do |dx|
(-half_size..half_size).each do |dy|
gx = center_x + dx
gy = center_y + dy
type = if gx < 0 || gy < 0 || gx > map_max[0] || gy > map_max[1]
:wall
else
@grid_cache[[gx, gy]] || :unrevealed
end
color = case type
when :wall then Gosu::Color.new(0xFF28353e)
when :empty then Gosu::Color.new(0xFFd6dad3)
when :torch then Gosu::Color.new(0xFFfbb954)
else Gosu::Color.new(0xFF576069)
end
color = Gosu::Color::RED if gx == center_x && gy == center_y
x = (dx + half_size) * CELL_SIZE + offset_x
y = (dy + half_size) * CELL_SIZE + offset_y
Gosu.draw_rect(x, y, CELL_SIZE, CELL_SIZE, color, Float::INFINITY)
end
end
end
end