From 045200bf9fa14deb3e99d56008b6fa1cf0c3f910 Mon Sep 17 00:00:00 2001 From: Daanish Date: Sat, 28 Mar 2026 18:09:58 +0000 Subject: [PATCH] Props are now collectible; Props logic refractor; maze coordinates cleanup --- game/character.rb | 2 +- game/enemy/handler.rb | 2 +- game/props/base.rb | 80 ++++++++++++++++++++++++++----------------- game/props/chest.rb | 13 +++++++ game/props/handler.rb | 28 ++++++++++++--- game/props/radar.rb | 13 +++++++ game/props/torch.rb | 13 +++++++ game/scene.rb | 6 ++-- game/state.rb | 4 +++ utils/maze.rb | 2 +- 10 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 game/props/chest.rb create mode 100644 game/props/radar.rb create mode 100644 game/props/torch.rb diff --git a/game/character.rb b/game/character.rb index fa45a87..bb9034b 100644 --- a/game/character.rb +++ b/game/character.rb @@ -10,7 +10,7 @@ class Character start_room_coords = $bus.get(:start_room_coords) if start_room_coords - @world_x, @world_y = [(start_room_coords[0] + 2) * 60 + 30, (start_room_coords[1] + 2) * 60 + 30] + @world_x, @world_y = [(start_room_coords[0] * 2 + 3) * 60 + 30, (start_room_coords[1] * 2 + 3) * 60 + 30] end # Load the full sheet as tiles diff --git a/game/enemy/handler.rb b/game/enemy/handler.rb index 277f0a6..13f211a 100644 --- a/game/enemy/handler.rb +++ b/game/enemy/handler.rb @@ -14,7 +14,7 @@ class EnemyHandler # 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] + 4) * 60 + 30, (start_room_coords[1] + 4) * 60 + 30) + @enemies << Enemy.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 1 + 4) * 60 + 30) end end diff --git a/game/props/base.rb b/game/props/base.rb index cf1f9cb..2359c24 100644 --- a/game/props/base.rb +++ b/game/props/base.rb @@ -1,4 +1,5 @@ class Prop + DESTRUCTION_SPEED = 50.0 SIZE = [25, 15] # The base class for all props in the game. Props are things that can be interacted with, but do not move (unlike characters). @@ -12,19 +13,50 @@ class Prop @y = y @frames_count = 0 @spritesheet = nil + @health = 100 end def collides?(rect) - return true if intersects?(self.rect, rect) + return true if intersects?(self.collision_rect, rect) false end - def rect + def collision_rect [@x * 120 + 90 - SIZE[0] / 2, @y * 120 + 90 - SIZE[1], *SIZE] end - def update - # For now, placeables don't have any behavior + def rect + [@x * 120 + 90 - 20, @y * 120 + 90 - 20, 40, 40] + end + + def resources + {} + end + + def update(dt) + return unless Gosu.button_down?(Gosu::MS_LEFT) + + player_x, player_y = $bus.get(:player_position) || [0, 0] + + tile_x, tile_y = [(player_x - 90) / 120, (player_y - 90) / 120].map(&:round) + + return unless tile_x == @x && tile_y == @y + + mouse_x, mouse_y = $bus.get(:mouse_pos) + cam_x, cam_y = $bus.get(:camera_pos) + world_mouse_x = mouse_x + cam_x + world_mouse_y = mouse_y + cam_y + + return unless intersects?([world_mouse_x, world_mouse_y, 1, 1], self.rect) + + @health -= DESTRUCTION_SPEED * dt + if @health <= 0 + resources.each do |type, amount| + $bus.emit(:obtain, type, amount) + end + return true + end + false end def draw @@ -39,36 +71,22 @@ class Prop @spritesheet[frame_index].draw(screen_x - 20, screen_y - 20, screen_y, 2, 2) + if @health < 100 + percent = 1.0 - @health / 100.0 + w, h = SIZE + + bar_width = w * percent + bar_height = 3 + + bar_x = screen_x - w / 2 + bar_y = screen_y + h + 5 + + Gosu.draw_rect(bar_x, bar_y, bar_width, bar_height, Gosu::Color::RED, screen_y + 1) + end + return unless DEBUG # collision box centered on same point Gosu.draw_rect(screen_x - SIZE[0] / 2, screen_y - SIZE[1], *SIZE, Gosu::Color.new(0x88ff0000), Float::INFINITY) end -end - -class Radar < Prop - def initialize(x, y) - super(x, y) - @frames_count = 4 - @spritesheet = Gosu::Image.load_tiles("assets/images/radar.png", 20, 20, retro: true) - end -end - -class Torch < Prop - def initialize(x, y) - super(x, y) - @frames_count = 4 - @spritesheet = Gosu::Image.load_tiles("assets/images/torch.png", 20, 20, retro: true) - end -end - -class Chest < Prop - def initialize(x, y) - super(x, y) - @wood = rand(0..64) - @metal = rand(0..16) - @science = rand(0..4) - @frames_count = 1 - @spritesheet = Gosu::Image.load_tiles("assets/images/chest.png", 20, 20, retro: true) - end end \ No newline at end of file diff --git a/game/props/chest.rb b/game/props/chest.rb new file mode 100644 index 0000000..45b1f7e --- /dev/null +++ b/game/props/chest.rb @@ -0,0 +1,13 @@ +require_relative "base" + +class Chest < Prop + def initialize(x, y) + super(x, y) + @frames_count = 1 + @spritesheet = Gosu::Image.load_tiles("assets/images/chest.png", 20, 20, retro: true) + end + + def resources + { wood: rand(0..64), metal: rand(0..16), science: rand(0..4) } + end +end \ No newline at end of file diff --git a/game/props/handler.rb b/game/props/handler.rb index 918426d..c649b47 100644 --- a/game/props/handler.rb +++ b/game/props/handler.rb @@ -1,4 +1,6 @@ -require_relative "base" +require_relative "radar" +require_relative "torch" +require_relative "chest" class PropsHandler attr_reader :props @@ -25,7 +27,7 @@ class PropsHandler def spawn_chests! world_size = $bus.get(:maze_size) || [0, 0] - cell_size = 10 + cell_size = 8 (0...world_size[0]).step(cell_size) do |cx| (0...world_size[1]).step(cell_size) do |cy| @@ -46,6 +48,18 @@ class PropsHandler @grid[[x, y]] = chest end end + + # Add one in the start room for players to have something to interact with right away + start_room_x, start_room_y = $bus.get(:start_room_coords) || [0, 0] + x, y = [ + [start_room_x, start_room_y], + [start_room_x + 2, start_room_y], + [start_room_x, start_room_y + 2], + [start_room_x + 2, start_room_y + 2] + ].sample + chest = Chest.new(x, y) + @props << chest + @grid[[x, y]] = chest end def nearby_props(rect) @@ -75,8 +89,14 @@ class PropsHandler @grid[key] = prop end - def update - @props.each(&:update) + def update(dt) + cam = $bus.get(:camera_pos) || [0, 0] + nearby_props([*cam, *SCREEN_SIZE]).each do |prop| + if prop.update(dt) + @props.delete(prop) + @grid.delete([prop.x, prop.y]) + end + end end def draw diff --git a/game/props/radar.rb b/game/props/radar.rb new file mode 100644 index 0000000..b24fc63 --- /dev/null +++ b/game/props/radar.rb @@ -0,0 +1,13 @@ +require_relative "base" + +class Radar < Prop + def initialize(x, y) + super(x, y) + @frames_count = 4 + @spritesheet = Gosu::Image.load_tiles("assets/images/radar.png", 20, 20, retro: true) + end + + def resources + { wood: rand(0..2), metal: rand(0..8), science: rand(0..2) } + end +end \ No newline at end of file diff --git a/game/props/torch.rb b/game/props/torch.rb new file mode 100644 index 0000000..1efe853 --- /dev/null +++ b/game/props/torch.rb @@ -0,0 +1,13 @@ +require_relative "base" + +class Torch < Prop + def initialize(x, y) + super(x, y) + @frames_count = 4 + @spritesheet = Gosu::Image.load_tiles("assets/images/torch.png", 20, 20, retro: true) + end + + def resources + { wood: rand(0..8) } + end +end \ No newline at end of file diff --git a/game/scene.rb b/game/scene.rb index 1f56ae4..bbe690b 100644 --- a/game/scene.rb +++ b/game/scene.rb @@ -139,7 +139,7 @@ class Game < Scene (0...tiles_x).each do |i| sx = i * tile_size - offset_x sy = j * tile_size - offset_y - @floor_image.draw(sx, sy, -1000, 3, 3) + @floor_image.draw(sx, sy, -Float::INFINITY, 3, 3) end end end @@ -147,10 +147,10 @@ class Game < Scene def update(dt) @character.update(dt) @enemies.update(dt) - @props.update + @props.update(dt) end - def button_down(id, _pos) + def button_down(id, pos) return $bus.emit(:change_scene, Menu.new) if id == Gosu::KB_ESCAPE end end \ No newline at end of file diff --git a/game/state.rb b/game/state.rb index 042c841..efba277 100644 --- a/game/state.rb +++ b/game/state.rb @@ -34,5 +34,9 @@ class State @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 fa95c30..12bf6e5 100644 --- a/utils/maze.rb +++ b/utils/maze.rb @@ -16,7 +16,7 @@ class MazeData return if standalone $bus.on(:start_room_coords) do - next @start_room ? [@start_room[0] * 2 + 1, @start_room[1] * 2 + 1] : nil + next @start_room end $bus.on(:room?) do |gx, gy|