Skip to content

Instantly share code, notes, and snippets.

@MattMcFarland
Created April 21, 2017 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MattMcFarland/230280295e1b9ef8004380051ca7f85c to your computer and use it in GitHub Desktop.
Save MattMcFarland/230280295e1b9ef8004380051ca7f85c to your computer and use it in GitHub Desktop.
pico8 - random dungeon
-- Copyright(c) Matt McFarland - 2017
-- MIT LICENSE
-- This will create rooms using the BSP method
rooms = {}
function _init()
local main_container = container(0, 6, 127, 121)
local max_depth = 6
local container_tree = split_container(main_container, max_depth)
cls()
square = 1
--add a function to room
--which updates the map
foreach(rooms, function (room)
room:paint()
end)
--use paths for map
paths(container_tree)
container_tree:paint()
end
function tree(leaf)
return {
leaf=leaf,
lchild=nil,
rchild=nil,
paint=function(self)
self.leaf:paint()
if (self.lchild ~= nil) then
self.lchild:paint()
end
if (self.rchild ~= nil) then
self.rchild:paint()
end
end
}
end
function paths(t)
if (nil == t.lchild or nil == t.rchild) return
t.lchild.leaf:path(t.rchild.leaf)
paths(t.lchild)
paths(t.rchild)
end
function container(x, y, w, h)
-- create a container cell
-- it may be discarded
local c = {
x=flr(x), y=flr(y),
w=flr(w), h=flr(h),
}
c.cx=c.x+flr(c.w/2)
c.cy=c.y+flr(c.h/2)
function c:paint()
rect(
self.x, self.y,
self.x + self.w,
self.y + self.h,
7
)
end
function c:path(o)
line(
self.cx,
self.cy,
o.cx,
o.cy,
5
)
end
return c
end
function make_room(c)
if (nil == c) return
-- create and add room from
-- the given container's info
local r = {}
local padding = 3
r.x=c.x + padding
r.y=c.y + padding
r.w=c.w - padding * 2
r.h=c.h - padding * 2
function r:paint()
rectfill(
self.x, self.y,
self.x + self.w,
self.y + self.h,
3
)
end
add(rooms, r)
end
-- "random split" a container
function r_split(cont)
local r1 = nil
local r2 = nil
if (rint(0,1) == 1) then
r1 = container(
cont.x, cont.y,
rint(1, cont.w), cont.h
)
r2 = container(
cont.x + r1.w, cont.y,
cont.w - r1.w, cont.h
)
if (r1.w / r1.h < 0.45 or r2.w / r2.h < 0.45) then
return r_split(cont)
end
else
r1 = container(
cont.x, cont.y,
cont.w, rint(1, cont.h)
)
r2 = container(
cont.x, cont.y + r1.h,
cont.w, cont.h - r1.h
)
if (r1.h / r1.w < 0.45 or r2.h / r2.w < 0.45) then
return r_split(cont)
end
end
return r1, r2
end
function split_container(c, iter)
local root = tree(c)
if (iter ~= 0) then
local sr1, sr2 = r_split(c)
root.lchild = split_container(sr1, iter-1)
root.rchild = split_container(sr2, iter-1)
-- when we reach the end,
-- add rooms to the containers
if (iter == 1) then
make_room(sr1)
make_room(sr2)
end
end
return root
end
function rint(a, b)
return flr(rnd(b+1) + a)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment