Roguelikes
Posted: Tue Aug 08, 2023 3:30 am
I know at least Gunroar is interested in roguelikes, so I thought it would be fun to have a thread on techniques with a special emphasis on love.
I got side-tracked from updating my old roguelike into developing caves. I'm using a simple bombardment function on areas created by recursively splitting a rectangle into smaller rectangles.
This is giving me good results. Of course, the trick is to keep everything connected. Lava blobs are still blocking paths, occasionally. On the other hand, the whole point to a map is to partition off the space, since large, open areas usually result in the player getting surrounded and killed. (Water is impassible in my game.)
I got side-tracked from updating my old roguelike into developing caves. I'm using a simple bombardment function on areas created by recursively splitting a rectangle into smaller rectangles.
Code: Select all
-- pseudo-lua
r = big_rectangle
curr = btree()
splitter(curr, 1)
function splitter(curr, i)
if i < max_iterations then
l, r = split_rectangle_at_a_random_length()
curr:add(l, r)
splitter(l, i+1)
splitter(r, i+1)
end
return curr
end
Code: Select all
function _M:bomb(bound, r, tile, reps, only)
r = math.round(r)
local cs = {}
local rcx, rcy = bound:center()
local sqsz = math.max(bound.size_x, bound.size_y) / 2
for i = 1, reps or 10 do
local cx, cy, trec
for j = 1, 100 do
local a = math.random() * math.pi * 2
local r2 = math.random(sqsz - r)
cx = math.round(math.cos(a) * r2 + rcx)
cy = math.round(math.sin(a) * r2 + rcy)
trec = rectangle:new(cx, cy, cx, cy):grow(r)
if bound:encloses(trec) then
break
end
end
table.insert(cs, { x=cx, y=cy})
local rect = bound:clip(trec)
if not rect then
log.error('rectangle error %s, (%d, %d), r%d, x%f', tostring(bound), cx, cy, r, bound.size_x)
end
assert(rect)
assert(bound:encloses(rect), 'out of bound')
if only then
for x, y in rect:iter() do
if self:get(x, y) ~= only then
rect = nil
end
end
end
if rect then
for x, y in rect:iter() do
local d = math.sqrt((cx - x)^2 + (cy - y)^2)
local r3 = r - math.random() + 0.5
if d <= r3 and self.bounds:has_point(x, y) then
self:set(x, y, tile)
end
end
end
end
return cs
end