Refactor props handling and inventory logic; add ghost prop preview
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -12,10 +12,10 @@ class EnemyHandler
|
|||||||
|
|
||||||
def spawn!
|
def spawn!
|
||||||
# For now, just spawn a single enemy at a fixed location
|
# For now, just spawn a single enemy at a fixed location
|
||||||
#start_room_coords = $bus.get(:start_room_coords)
|
start_room_coords = $bus.get(:start_room_coords)
|
||||||
#if @enemies.empty?
|
if @enemies.empty?
|
||||||
# @enemies << Enemy.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 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
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw
|
def draw
|
||||||
|
|||||||
+39
-5
@@ -3,6 +3,7 @@ class Inventory
|
|||||||
COLS = 3
|
COLS = 3
|
||||||
ROW_HEIGHT = 48
|
ROW_HEIGHT = 48
|
||||||
COL_WIDTH = 40
|
COL_WIDTH = 40
|
||||||
|
RECT = [22, 30, 126, 196]
|
||||||
|
|
||||||
CRAFT_RECIPES = {
|
CRAFT_RECIPES = {
|
||||||
lorentz_field: { wood: 16, metal: 8, science: 2 },
|
lorentz_field: { wood: 16, metal: 8, science: 2 },
|
||||||
@@ -39,6 +40,24 @@ class Inventory
|
|||||||
@grid[row][col][1][0] += amount
|
@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]
|
@grid[row][col][1][0] = @grid[row][col][1][1] if @grid[row][col][1][0] > @grid[row][col][1][1]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
$bus.on(:consume) do |type, amount|
|
||||||
|
row, col = find_slot(type)
|
||||||
|
next false unless row
|
||||||
|
next false if @grid[row][col][1][0] < amount
|
||||||
|
@grid[row][col][1][0] -= amount
|
||||||
|
next true
|
||||||
|
end
|
||||||
|
|
||||||
|
$bus.on(:count) do |type|
|
||||||
|
row, col = find_slot(type)
|
||||||
|
next 0 unless row
|
||||||
|
next @grid[row][col][1][0]
|
||||||
|
end
|
||||||
|
|
||||||
|
$bus.on(:selected_item) do
|
||||||
|
@inventory_selected
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Draw the inventory
|
# Draw the inventory
|
||||||
@@ -71,27 +90,40 @@ class Inventory
|
|||||||
def button_down(id, pos)
|
def button_down(id, pos)
|
||||||
case id
|
case id
|
||||||
when Gosu::MS_LEFT, Gosu::MS_RIGHT
|
when Gosu::MS_LEFT, Gosu::MS_RIGHT
|
||||||
mouse_click(*pos, id)
|
return mouse_click(*pos, id)
|
||||||
when Gosu::KB_1 then @inventory_selected = :occams_razor
|
when Gosu::KB_1 then @inventory_selected = :occams_razor
|
||||||
when Gosu::KB_2 then @inventory_selected = :quantum_bow
|
when Gosu::KB_2 then @inventory_selected = :quantum_bow
|
||||||
when Gosu::KB_3 then @inventory_selected = :blade_of_recursion
|
when Gosu::KB_3 then @inventory_selected = :blade_of_recursion
|
||||||
when Gosu::KB_C
|
when Gosu::KB_DOWN
|
||||||
row, col = find_slot(@inventory_selected)
|
row, col = find_slot(@inventory_selected)
|
||||||
@inventory_selected = @grid[(row + 1) % @grid.size][col][0]
|
@inventory_selected = @grid[(row + 1) % @grid.size][col][0]
|
||||||
when Gosu::KB_V
|
when Gosu::KB_UP
|
||||||
|
row, col = find_slot(@inventory_selected)
|
||||||
|
@inventory_selected = @grid[(row - 1) % @grid.size][col][0]
|
||||||
|
when Gosu::KB_LEFT
|
||||||
|
row, col = find_slot(@inventory_selected)
|
||||||
|
@inventory_selected = @grid[row][(col - 1) % @grid[row].size][0]
|
||||||
|
when Gosu::KB_RIGHT
|
||||||
row, col = find_slot(@inventory_selected)
|
row, col = find_slot(@inventory_selected)
|
||||||
@inventory_selected = @grid[row][(col + 1) % @grid[row].size][0]
|
@inventory_selected = @grid[row][(col + 1) % @grid[row].size][0]
|
||||||
|
when Gosu::KB_RETURN
|
||||||
|
craft(@inventory_selected, ctrl: Gosu.button_down?(Gosu::KB_RIGHT_CONTROL) || Gosu.button_down?(Gosu::KB_LEFT_CONTROL))
|
||||||
|
else
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Mouse click detection
|
# Mouse click detection
|
||||||
def mouse_click(mx, my, id)
|
def mouse_click(mx, my, id)
|
||||||
|
return false unless intersects?([mx, my, 1, 1], RECT)
|
||||||
|
|
||||||
x_start, y_start = OFFSET
|
x_start, y_start = OFFSET
|
||||||
row_idx = ((my - y_start) / ROW_HEIGHT).floor
|
row_idx = ((my - y_start) / ROW_HEIGHT).floor
|
||||||
col_idx = ((mx - x_start) / COL_WIDTH).floor
|
col_idx = ((mx - x_start) / COL_WIDTH).floor
|
||||||
|
|
||||||
return if row_idx < 0 || row_idx >= @grid.size
|
return true if row_idx < 0 || row_idx >= @grid.size
|
||||||
return if col_idx < 0 || col_idx >= @grid[row_idx].size
|
return true if col_idx < 0 || col_idx >= @grid[row_idx].size
|
||||||
|
|
||||||
type, (amount, max) = @grid[row_idx][col_idx]
|
type, (amount, max) = @grid[row_idx][col_idx]
|
||||||
|
|
||||||
@@ -104,6 +136,8 @@ class Inventory
|
|||||||
craft(type, ctrl: Gosu.button_down?(Gosu::KB_RIGHT_CONTROL) || Gosu.button_down?(Gosu::KB_LEFT_CONTROL))
|
craft(type, ctrl: Gosu.button_down?(Gosu::KB_RIGHT_CONTROL) || Gosu.button_down?(Gosu::KB_LEFT_CONTROL))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
+29
-13
@@ -8,11 +8,26 @@ class Prop
|
|||||||
# A prop is one that is placed at the center of a tile (radar, torch & chest)
|
# A prop is one that is placed at the center of a tile (radar, torch & chest)
|
||||||
attr_reader :x, :y
|
attr_reader :x, :y
|
||||||
|
|
||||||
|
def self.setup_sprites(path, frames)
|
||||||
|
@frames_count = frames
|
||||||
|
@spritesheet = Gosu::Image.load_tiles(path, 20, 20, retro: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.spritesheet
|
||||||
|
@spritesheet
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.frames_count
|
||||||
|
@frames_count
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.ghost
|
||||||
|
@spritesheet&.first
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(x, y)
|
def initialize(x, y)
|
||||||
@x = x
|
@x = x
|
||||||
@y = y
|
@y = y
|
||||||
@frames_count = 0
|
|
||||||
@spritesheet = nil
|
|
||||||
@health = 100
|
@health = 100
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -34,7 +49,7 @@ class Prop
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update(dt)
|
def update(dt)
|
||||||
return unless Gosu.button_down?(Gosu::MS_LEFT)
|
return unless Gosu.button_down?(Gosu::MS_LEFT) || Gosu.button_down?(Gosu::KB_X)
|
||||||
|
|
||||||
player_x, player_y = $bus.get(:player_position) || [0, 0]
|
player_x, player_y = $bus.get(:player_position) || [0, 0]
|
||||||
|
|
||||||
@@ -42,12 +57,13 @@ class Prop
|
|||||||
|
|
||||||
return unless tile_x == @x && tile_y == @y
|
return unless tile_x == @x && tile_y == @y
|
||||||
|
|
||||||
mouse_x, mouse_y = $bus.get(:mouse_pos)
|
if Gosu.button_down?(Gosu::MS_LEFT)
|
||||||
cam_x, cam_y = $bus.get(:camera_pos)
|
mouse_x, mouse_y = $bus.get(:mouse_pos)
|
||||||
world_mouse_x = mouse_x + cam_x
|
cam_x, cam_y = $bus.get(:camera_pos)
|
||||||
world_mouse_y = mouse_y + cam_y
|
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)
|
return unless intersects?([world_mouse_x, world_mouse_y, 1, 1], self.rect)
|
||||||
|
end
|
||||||
|
|
||||||
@health -= DESTRUCTION_SPEED * dt
|
@health -= DESTRUCTION_SPEED * dt
|
||||||
if @health <= 0
|
if @health <= 0
|
||||||
@@ -60,16 +76,16 @@ class Prop
|
|||||||
end
|
end
|
||||||
|
|
||||||
def draw
|
def draw
|
||||||
return unless @spritesheet
|
return unless self.class.spritesheet
|
||||||
|
|
||||||
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
||||||
screen_x = @x * 120 + 90 - cam_x
|
screen_x = @x * 120 + 90 - cam_x
|
||||||
screen_y = @y * 120 + 90 - cam_y
|
screen_y = @y * 120 + 90 - cam_y
|
||||||
|
|
||||||
elapsed = Gosu.milliseconds / 1000.0
|
elapsed = Gosu.milliseconds / 1000.0
|
||||||
frame_index = ((elapsed * @frames_count).floor) % @frames_count
|
frame_index = ((elapsed * self.class.frames_count).floor) % self.class.frames_count
|
||||||
|
|
||||||
@spritesheet[frame_index].draw(screen_x - 20, screen_y - 20, screen_y, 2, 2)
|
self.class.spritesheet[frame_index].draw(screen_x - 20, screen_y - 20, screen_y, 2, 2)
|
||||||
|
|
||||||
if @health < 100
|
if @health < 100
|
||||||
percent = 1.0 - @health / 100.0
|
percent = 1.0 - @health / 100.0
|
||||||
@@ -81,7 +97,7 @@ class Prop
|
|||||||
bar_x = screen_x - w / 2
|
bar_x = screen_x - w / 2
|
||||||
bar_y = screen_y + h + 5
|
bar_y = screen_y + h + 5
|
||||||
|
|
||||||
Gosu.draw_rect(bar_x, bar_y, bar_width, bar_height, Gosu::Color::RED, screen_y + 1)
|
Gosu.draw_rect(bar_x, bar_y, bar_width, bar_height, Gosu::Color::RED, screen_y - 19)
|
||||||
end
|
end
|
||||||
|
|
||||||
return unless DEBUG
|
return unless DEBUG
|
||||||
|
|||||||
+1
-5
@@ -1,11 +1,7 @@
|
|||||||
require_relative "base"
|
require_relative "base"
|
||||||
|
|
||||||
class Chest < Prop
|
class Chest < Prop
|
||||||
def initialize(x, y)
|
setup_sprites("assets/images/chest.png", 1)
|
||||||
super(x, y)
|
|
||||||
@frames_count = 1
|
|
||||||
@spritesheet = Gosu::Image.load_tiles("assets/images/chest.png", 20, 20, retro: true)
|
|
||||||
end
|
|
||||||
|
|
||||||
def resources
|
def resources
|
||||||
{ wood: rand(0..64), metal: rand(0..16), science: rand(0..4) }
|
{ wood: rand(0..64), metal: rand(0..16), science: rand(0..4) }
|
||||||
|
|||||||
+51
-5
@@ -58,8 +58,7 @@ class PropsHandler
|
|||||||
[start_room_x + 2, start_room_y + 2]
|
[start_room_x + 2, start_room_y + 2]
|
||||||
].sample
|
].sample
|
||||||
chest = Chest.new(x, y)
|
chest = Chest.new(x, y)
|
||||||
@props << chest
|
add(chest)
|
||||||
@grid[[x, y]] = chest
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def nearby_props(rect)
|
def nearby_props(rect)
|
||||||
@@ -84,9 +83,7 @@ class PropsHandler
|
|||||||
|
|
||||||
def add(prop)
|
def add(prop)
|
||||||
@props << prop
|
@props << prop
|
||||||
|
@grid[[prop.x, prop.y]] = prop
|
||||||
key = [prop.x, prop.y]
|
|
||||||
@grid[key] = prop
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update(dt)
|
def update(dt)
|
||||||
@@ -97,10 +94,59 @@ class PropsHandler
|
|||||||
@grid.delete([prop.x, prop.y])
|
@grid.delete([prop.x, prop.y])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if Gosu.button_down?(Gosu::KB_P) # place selected if it is a placeable item
|
||||||
|
selected_item = $bus.get(:selected_item)
|
||||||
|
if selected_item == :torch
|
||||||
|
player_x, player_y = $bus.get(:player_position) || [0, 0]
|
||||||
|
tile = [(player_x - 90) / 120, (player_y - 90) / 120].map(&:round)
|
||||||
|
torch = Torch.new(*tile)
|
||||||
|
return if @grid[[tile[0], tile[1]]] # can't place if something is already there
|
||||||
|
return if $bus.get_all(:collides?, torch.rect).include?(:character) # can't place if colliding with player
|
||||||
|
return unless $bus.get(:consume, :torch, 1)
|
||||||
|
add(torch)
|
||||||
|
elsif selected_item == :radar
|
||||||
|
player_x, player_y = $bus.get(:player_position) || [0, 0]
|
||||||
|
tile = [(player_x - 90) / 120, (player_y - 90) / 120].map(&:round)
|
||||||
|
radar = Radar.new(*tile)
|
||||||
|
return if @grid[[tile[0], tile[1]]]
|
||||||
|
return if $bus.get_all(:collides?, radar.rect).include?(:character)
|
||||||
|
return unless $bus.get(:consume, :radar, 1)
|
||||||
|
add(radar)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def button_down(id, pos)
|
||||||
|
#
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw
|
def draw
|
||||||
cam = $bus.get(:camera_pos) || [0, 0]
|
cam = $bus.get(:camera_pos) || [0, 0]
|
||||||
nearby_props([*cam, *SCREEN_SIZE]).each(&:draw)
|
nearby_props([*cam, *SCREEN_SIZE]).each(&:draw)
|
||||||
|
draw_ghost_prop!
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw_ghost_prop!
|
||||||
|
# draw a ghost of the prop that would be placed if the player presses the place button,
|
||||||
|
# to give them a preview of where it would go, also tint it red if it can't be placed there for any reason
|
||||||
|
# or green if it can
|
||||||
|
selected_item = $bus.get(:selected_item)
|
||||||
|
return unless [:torch, :radar].include?(selected_item)
|
||||||
|
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
||||||
|
player_x, player_y = $bus.get(:player_position) || [0, 0]
|
||||||
|
x, y = [(player_x - 90) / 120, (player_y - 90) / 120].map(&:round)
|
||||||
|
return if @grid[[x, y]]
|
||||||
|
return if $bus.get(:count, selected_item) < 1
|
||||||
|
world_x = x * 120 + 90
|
||||||
|
world_y = y * 120 + 90
|
||||||
|
screen_x = world_x - cam_x
|
||||||
|
screen_y = world_y - cam_y
|
||||||
|
possible = !$bus.get_all(:collides?, [world_x - 20, world_y - 20, 40, 40]).include?(:character)
|
||||||
|
color = possible ? Gosu::Color.new(255 * 0.7, 128, 239, 128) : Gosu::Color.new(255 * 0.7, 255, 116, 108)
|
||||||
|
if selected_item == :torch
|
||||||
|
Torch.ghost.draw(screen_x - 20, screen_y - 20, screen_y, 2, 2, color)
|
||||||
|
elsif selected_item == :radar
|
||||||
|
Radar.ghost.draw(screen_x - 20, screen_y - 20, screen_y, 2, 2, color)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
+1
-5
@@ -1,11 +1,7 @@
|
|||||||
require_relative "base"
|
require_relative "base"
|
||||||
|
|
||||||
class Radar < Prop
|
class Radar < Prop
|
||||||
def initialize(x, y)
|
setup_sprites("assets/images/radar.png", 4)
|
||||||
super(x, y)
|
|
||||||
@frames_count = 4
|
|
||||||
@spritesheet = Gosu::Image.load_tiles("assets/images/radar.png", 20, 20, retro: true)
|
|
||||||
end
|
|
||||||
|
|
||||||
def resources
|
def resources
|
||||||
{ wood: rand(0..2), metal: rand(0..8), science: rand(0..2) }
|
{ wood: rand(0..2), metal: rand(0..8), science: rand(0..2) }
|
||||||
|
|||||||
+1
-5
@@ -1,11 +1,7 @@
|
|||||||
require_relative "base"
|
require_relative "base"
|
||||||
|
|
||||||
class Torch < Prop
|
class Torch < Prop
|
||||||
def initialize(x, y)
|
setup_sprites("assets/images/torch.png", 4)
|
||||||
super(x, y)
|
|
||||||
@frames_count = 4
|
|
||||||
@spritesheet = Gosu::Image.load_tiles("assets/images/torch.png", 20, 20, retro: true)
|
|
||||||
end
|
|
||||||
|
|
||||||
def resources
|
def resources
|
||||||
{ wood: rand(0..8) }
|
{ wood: rand(0..8) }
|
||||||
|
|||||||
+10
-5
@@ -61,10 +61,14 @@ class Game < Scene
|
|||||||
py = SCREEN_SIZE[1] / 2.0
|
py = SCREEN_SIZE[1] / 2.0
|
||||||
|
|
||||||
# Collect torch positions relative to camera
|
# Collect torch positions relative to camera
|
||||||
torches = $bus.get(:nearby_torches,
|
torch_lights = []
|
||||||
[cam_x - SCREEN_SIZE[0] / 2, cam_y - SCREEN_SIZE[1] / 2, SCREEN_SIZE[0] * 2, SCREEN_SIZE[1] * 2]
|
# Only calculate torch lights if the setting is enabled, to save performance
|
||||||
) || []
|
if $bus.get(:settings, :torches_lightup)
|
||||||
torch_lights = torches.map { |t| [t[0] - cam_x, t[1] - cam_y] }
|
torches = $bus.get(:nearby_torches,
|
||||||
|
[cam_x - SCREEN_SIZE[0] / 2, cam_y - SCREEN_SIZE[1] / 2, SCREEN_SIZE[0] * 2, SCREEN_SIZE[1] * 2]
|
||||||
|
) || []
|
||||||
|
torch_lights = torches.map { |t| [t[0] - cam_x, t[1] - cam_y] }
|
||||||
|
end
|
||||||
|
|
||||||
tiles_x = (SCREEN_SIZE[0] / cell) + 2
|
tiles_x = (SCREEN_SIZE[0] / cell) + 2
|
||||||
tiles_y = (SCREEN_SIZE[1] / cell) + 2
|
tiles_y = (SCREEN_SIZE[1] / cell) + 2
|
||||||
@@ -152,6 +156,7 @@ class Game < Scene
|
|||||||
def button_down(id, pos)
|
def button_down(id, pos)
|
||||||
return $bus.emit(:change_scene, Menu.new) if id == Gosu::KB_ESCAPE
|
return $bus.emit(:change_scene, Menu.new) if id == Gosu::KB_ESCAPE
|
||||||
|
|
||||||
@hud.button_down(id, pos)
|
return if @hud.button_down(id, pos)
|
||||||
|
return if @props.button_down(id, pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Reference in New Issue
Block a user