From bf93aecad1b02df9f6d8ddc1dece176208455107 Mon Sep 17 00:00:00 2001 From: Daanish Date: Sat, 28 Mar 2026 11:38:20 +0000 Subject: [PATCH] Refactor event bus to use non-retrievable events; update collision handling and add new inventory initialization; add torch lighting in fog shader; --- assets/images/inventory.png | Bin 6593 -> 6678 bytes assets/images/torch.aseprite | Bin 0 -> 637 bytes assets/images/torch.png | Bin 0 -> 622 bytes game/character.rb | 10 +++-- game/enemy/ai.rb | 4 +- game/enemy/base.rb | 4 ++ game/maze.rb | 6 ++- game/placeables/base.rb | 42 ++++++++++++++++----- game/scene.rb | 70 ++++++++++++++++++++++------------- game/state.rb | 31 ++++++++++++++++ main.rb | 2 +- utils/bus.rb | 35 ++++++++++-------- utils/maze.rb | 4 +- utils/scene.rb | 2 +- 14 files changed, 150 insertions(+), 60 deletions(-) create mode 100644 assets/images/torch.aseprite create mode 100644 assets/images/torch.png diff --git a/assets/images/inventory.png b/assets/images/inventory.png index e581e05bb9701139c63c527eecf5c160b4b4969d..dec661506d40933aa315a18dc71db32efec0ec66 100644 GIT binary patch literal 6678 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 V@Av!sVl)65?CI*~vd$@?2>_AhGE@Kn literal 6593 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 diff --git a/assets/images/torch.aseprite b/assets/images/torch.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..95d1329ce95c773866950fceb8574a8fe71edd89 GIT binary patch literal 637 zcmbSz_Vy(P2~E*?50hvAk3ak5^zA?Y|No!8c6&=*duCQvWLQv{Q`Z_J zqnqK$*Q{dQ;QS~{TLY-SV4|pU}X5u1XC5jAjD8H z=k0ZGu0sX_Y!BoP_I}}bbSYFYcIUf8q5Tg+W2(6PpOm(on&R`zc&^Q_2CvDD@`h^j zJ$)C8xyID;hf3cpof=hDC%i{FeZO|JYXJI zzkVvNI$N=|)1*1>_s;0g^0qO>2c#oJa`XB>pWJphUFqxs_3PHxm9sthpC3;Beey(VmDEcnmtoEN+P)z*v zZr@JE{kIOfyo>>$w=KRfB5CP!|DqejGp3f| zw8C#&PDrku%5Ahlzu#2-)p8r9wKJb4-G91KW~RSnKaawtT^Co)uzc5YY*}@C^tMlj zwA1=pgH~2dNxT{SFmR{b;tv+BPgIwL_V9gU7xB0)ShB%>!Lwxttz+sQSKL|P_T=Cu z=E|6BF_DiZ%}nBA2)KWH*-szCuUjQ|7)IZ@pVs1@RA=*)OT=HLDr5hpzI}@$pK4xz ze)Z>O6T53-jSI`wc`vQ`WW($c7n+kUabsoi_eVQ!L@8q7(jm89dr2Tx<3I=gc1Fe8-^oKZ6$vG-}2LKR!5_S3zWT j&@zSM!l!3N!{kMcpBM o_radius - alpha = 255 - else - t = (dist - i_radius) / (o_radius - i_radius) # 0..1 - world_x = (sx + cam_x) * 0.005 - world_y = (sy + cam_y) * 0.005 - # Sample noise at world position so it scrolls with camera - # Add time-based offsets for animation - noise = (@noise[world_x + Gosu.milliseconds / 5000.0, world_y + Gosu.milliseconds / 6000.0] + 1.0) / 2.0 - alpha = (t * (1.0 + noise) * 255).to_i.clamp(0, 255) + d = Math.sqrt((px - sx)**2 + (py - sy)**2) + if d < p_i_radius + light_strength = 1.0 + elsif d < p_o_radius + t = (d - p_i_radius) / (p_o_radius - p_i_radius) # 0..1 + light_strength = 1.0 - t end + torch_lights.each do |lx, ly| + d = Math.sqrt((sx - lx)**2 + (sy - ly)**2) + + if d < t_i_radius + strength = 1.0 + elsif d < o_radius + t = (d - t_i_radius) / (o_radius - t_i_radius) # 0..1 + strength = 1.0 - t + else + strength = 0.0 + end + + light_strength += strength + end + + light_strength = light_strength.clamp(0.0, 1.0) + + t = 1.0 - light_strength + + world_x = (sx + cam_x) * 0.005 + world_y = (sy + cam_y) * 0.005 + + noise = (@noise[ + world_x + Gosu.milliseconds / 5000.0, + world_y + Gosu.milliseconds / 6000.0 + ] + 1.0) / 2.0 + + alpha = (t * (1.0 + noise) * 255).to_i.clamp(0, 255) + Gosu.draw_rect(sx, sy, cell, cell, Gosu::Color.new(alpha, 0, 0, 0), 10000 + sy) end end diff --git a/game/state.rb b/game/state.rb index 9c1e414..042c841 100644 --- a/game/state.rb +++ b/game/state.rb @@ -4,4 +4,35 @@ class State # 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 + end end \ No newline at end of file diff --git a/main.rb b/main.rb index bce9d98..0804305 100644 --- a/main.rb +++ b/main.rb @@ -20,7 +20,7 @@ class Window < Gosu::Window $bus.on(:quit_game) { close! } - $bus.on_retrievable(:mouse_pos) do + $bus.on(:mouse_pos) do next mouse_relative(mouse_x, mouse_y) end diff --git a/utils/bus.rb b/utils/bus.rb index a485352..026bb62 100644 --- a/utils/bus.rb +++ b/utils/bus.rb @@ -2,12 +2,11 @@ class EventBus def initialize # store callbacks with owner: {event => [ {callback:, owner:} ] } @events = Hash.new { |h, k| h[k] = [] } - @retrievable_events = {} end # Emit an event def emit(event, *args) - @events[event].each do |h| + @events[event].dup.each do |h| h[:callback].call(*args) end end @@ -28,30 +27,34 @@ class EventBus on(event, owner: owner, &wrapper) end + # Unsubscribe from an event def off(event, &callback) @events[event].reject! { |h| h[:callback] == callback } end - # Register a retrievable event (only one allowed) - def on_retrievable(event, owner = nil, &callback) - owner ||= callback.binding.eval("self") - @retrievable_events[event] = { callback: callback, owner: owner } - end - - # Get data from a retrievable event + # For events that return a value (e.g. queries), get the first non-nil response def get(event, *args) - if @retrievable_events[event] - @retrievable_events[event][:callback].call(*args) - else - nil + @events[event].dup.each do |h| + result = h[:callback].call(*args) + return result unless result.nil? end + nil end - # Unsubscribe from an object's events - def unlisten_owner(owner) + # For events that return multiple values (e.g. queries), get all non-nil responses + def get_all(event, *args) + results = [] + @events[event].dup.each do |h| + result = h[:callback].call(*args) + results << result unless result.nil? + end + results + end + + # Unsubscribe all events for a given owner (e.g. when an object is destroyed) + def remove_owner(owner) @events.each do |event, handlers| handlers.reject! { |h| h[:owner] == owner } end - @retrievable_events.delete_if { |_, h| h[:owner] == owner } end end \ No newline at end of file diff --git a/utils/maze.rb b/utils/maze.rb index 5fc9e02..4a273c3 100644 --- a/utils/maze.rb +++ b/utils/maze.rb @@ -15,14 +15,14 @@ class MazeData return if standalone - $bus.on_retrievable(:start_room_coords) do + $bus.on(:start_room_coords) do next @start_room ? [@start_room[0] * 2 + 1, @start_room[1] * 2 + 1] : nil end return unless DEBUG print_debug - $bus.on_retrievable(:boss_room_coords) do + $bus.on(:boss_room_coords) do next @boss_rooms.first ? [@boss_rooms.first[0] * 2 + 1, @boss_rooms.first[1] * 2 + 1] : nil end end diff --git a/utils/scene.rb b/utils/scene.rb index a730797..44ce2ff 100644 --- a/utils/scene.rb +++ b/utils/scene.rb @@ -14,6 +14,6 @@ class Scene end def close - $bus.unlisten_owner(self) + $bus.remove_owner(self) end end \ No newline at end of file