Last active
August 9, 2024 13:12
-
-
Save xenobrain/2b398d8789fc9077187025d50aa0d111 to your computer and use it in GitHub Desktop.
Shadowcasting in ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def tick(args) | |
grid_w = 16 | |
grid_h = 16 | |
args.state.grid ||= [ | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, | |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, | |
] | |
if args.state.tick_count.zero? # flip grid y-axis | |
y = 0 | |
while y < grid_h >> 1 | |
x = 0 | |
while x < grid_w | |
i = grid_w * y + x | |
j = grid_w * (grid_h - 1 - y) + x | |
temp = args.state.grid[i] | |
args.state.grid[i] = args.state.grid[j] | |
args.state.grid[j] = temp | |
x += 1 | |
end | |
y += 1 | |
end | |
end | |
args.state.start_x ||= 5 | |
args.state.start_y ||= 5 | |
radius = 5 | |
args.state.start_x += args.inputs.left_right | |
args.state.start_y += args.inputs.up_down | |
visible_tiles = Array.new(grid_w * grid_h, 0) | |
compute_fov(args.state.grid, args.state.start_x, args.state.start_y, radius, visible_tiles) | |
# draw map | |
grid_w.times do |y| | |
grid_h.times do |x| | |
color = args.state.grid[y * grid_w + x] == 1 ? [100, 100, 100] : [0, 0, 0] | |
args.outputs.solids << [x * 32, y * 32, 32, 32, *color, 255] | |
end | |
end | |
# draw visible tiles | |
grid_w.times do |y| | |
grid_h.times do |x| | |
if visible_tiles[y * grid_w + x] == 1 | |
args.outputs.solids << [x * 32, y * 32, 32, 32, 0, 255, 0, 128] | |
end | |
end | |
end | |
args.outputs.solids << [args.state.start_x * 32, args.state.start_y * 32, 32, 32, 255, 0, 0, 255] | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MULT = [ | |
1, 0, 0, -1, -1, 0, 0, 1, | |
0, 1, -1, 0, 0, -1, 1, 0, | |
0, 1, 1, 0, 0, -1, -1, 0, | |
1, 0, 0, 1, -1, 0, 0, -1 | |
] | |
def compute_fov grid, grid_w, grid_h, x, y, radius, visible_tiles | |
visible_tiles[y * grid_w + x] = 1 | |
radius2 = radius * radius | |
octant = 0 | |
while octant < 8 | |
row = 1 | |
start_slope = 1.0 | |
end_slope = 0.0 | |
xx = MULT[octant] | |
xy = MULT[octant + 8] | |
yx = MULT[octant + 16] | |
yy = MULT[octant + 24] | |
while row <= radius | |
dx = -row - 1 | |
dy = -row | |
blocked = false | |
new_start = 0.0 | |
while dx <= 0 | |
dx += 1 | |
cell_x = x + dx * xx + dy * xy | |
cell_y = y + dx * yx + dy * yy | |
l_slope = (dx - 0.5) / (dy + 0.5) | |
r_slope = (dx + 0.5) / (dy - 0.5) | |
break if end_slope > l_slope | |
next if start_slope < r_slope | |
cell_index = cell_y * grid_w + cell_x | |
if dx * dx + dy * dy < radius2 && cell_x >= 0 && cell_y >= 0 && cell_x < grid_w && cell_y < grid_h | |
visible_tiles[cell_index] = 1 | |
end | |
if blocked | |
if cell_x >= 0 && cell_y >= 0 && cell_x < grid_w && cell_y < grid_h && grid[cell_index] == 1 | |
new_start = r_slope | |
else | |
blocked = false | |
start_slope = new_start | |
end | |
elsif cell_x >= 0 && cell_y >= 0 && cell_x < grid_w && cell_y < grid_h && grid[cell_index] == 1 && row < radius | |
blocked = true | |
new_start = r_slope | |
end | |
end | |
break if blocked | |
row += 1 | |
end | |
octant += 1 | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment