Refactor game window and shader management; add fog shader implementation and update configuration settings

This commit is contained in:
2026-03-29 04:44:55 +00:00
parent 3dbeadf976
commit 2064232226
6 changed files with 296 additions and 171 deletions
+3 -76
View File
@@ -37,8 +37,8 @@ class Game < Scene
@character.draw
@enemies.draw
@props.draw
@hud.draw
draw_fog! if $bus.get(:settings, :fog)
@hud.draw
draw_debug! if $bus.get(:settings, :debug)
end
@@ -49,83 +49,10 @@ class Game < Scene
end
def draw_fog!
cam_x, cam_y = @camera
cell = 10
p_i_radius = 80.0
p_o_radius = 350.0
t_i_radius = 10.0
o_radius = 160.0
$bus.emit(:shade)
return
# Player screen position
px = SCREEN_SIZE[0] / 2.0
py = SCREEN_SIZE[1] / 2.0
# Collect torch positions relative to camera
torch_lights = []
# Only calculate torch lights if the setting is enabled, to save performance
if $bus.get(:settings, :torches_lightup)
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_y = (SCREEN_SIZE[1] / cell) + 2
# This part is a shader but due to time constraints, I'm doing it on the CPU.
# If done on the GPU, we could have much better performance.
# and also make it more fine-grained and smoother gradients.
# doing it on the GPU would require better knowledge of the ruby openGL bindings and shader programming,
# which I don't have right now.
tiles_y.times do |j|
tiles_x.times do |i|
sx = i * cell
sy = j * cell
light_strength = 0.0
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
end
def draw_floor