I haven't looked at your code and it won't run without error, but I already created a mage generator I was (And probably still will) going to use for a game at some point. At some point I'm going to have to redo this better. This is the main.lua code:
Code: Select all
_r = math.random
_f = math.floor
_ce = math.ceil
_c = math.cos
_s = math.sin
_sq = math.sqrt
_at2 = math.atan2
_d2r = math.rad
_r2d = math.deg
_m = math.mod
_mx = math.max
_mn = math.min
pi = math.pi
gr = love.graphics
ti = love.timer
ms = love.mouse
kb = love.keyboard
math.randomseed(os.time())
math.randomseed(_r())
_r() _r() _r()
--require "savetable"
require "enemies"
require "behaviors"
require "maths"
love.filesystem.setIdentity("MapGen")
function love.run()
scrn = {}
scrn.w = 160
scrn.h = 144
scrn.ws = 3
scrn.fls = true
scrn.dox = -24
scrn.doy = -8
setScreenMode(scrn.ws)
hasBuffers, result = pcall(createBuffers)
love.load(arg)
gr.clear()
while true do
fps = ti.getFPS()
local dt = ti.getDelta()
ti.step()
time = ti.getTime()
gr.clear()
love.update(dt)
love.draw(dt)
if love.event then
for e,a,b,c in love.event.poll() do
if e == "q" then
if love.audio then love.audio.stop() end
return
end
love.handlers[e](a,b,c)
end
end
ti.sleep(.001)
gr.present()
end
end
function love.load(arg)
print("Arguments:")
for i, p in pairs(arg) do
print(p)
end
print(" ")
m = {}
gr.setLineWidth(1)
font1 = gr.newImageFont("font.png", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 :-!.,\"?>_", 0)
font2 = gr.newImageFont("font2.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`_*#=[]'", 0)
font2:setLineHeight(.6)
font3 = gr.newImageFont("font3.png", " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-,:", 0)
font3:setLineHeight(.9)
font4 = gr.newFont(love._vera_ttf, 18)
font4:setLineHeight(1.4)
imgPlayer = gr.newImage("player.png")
quadPlayer = {}
for x=1,4 do
quadPlayer[x] = {}
for y=0,1 do
quadPlayer[x][y] = gr.newQuad((x-1)*16,y*16,16,16,imgPlayer:getWidth(),imgPlayer:getHeight())
end
end
imgTile = gr.newImage("room.png")
quadTile = {}
--QUADS WALL TOP
quadTile["wall_tl1"] = gr.newQuad(0,0,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_t1"] = gr.newQuad(16,0,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tdl1"] = gr.newQuad(32,0,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tdm1"] = gr.newQuad(48,0,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tdr1"] = gr.newQuad(64,0,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tr1"] = gr.newQuad(80,0,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tl2"] = gr.newQuad(0,16,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_t2"] = gr.newQuad(16,16,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tdl2"] = gr.newQuad(32,16,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tdm2"] = gr.newQuad(48,16,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tdr2"] = gr.newQuad(64,16,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_tr2"] = gr.newQuad(80,16,16,16,imgTile:getWidth(),imgTile:getHeight())
--QUADS WALL SIDES
quadTile["wall_l"] = gr.newQuad(0,80,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_ldt"] = gr.newQuad(0,32,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_ldb"] = gr.newQuad(0,48,16,32,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_r"] = gr.newQuad(80,80,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_rdt"] = gr.newQuad(80,32,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_rdb"] = gr.newQuad(80,48,16,32,imgTile:getWidth(),imgTile:getHeight())
--QUADS WALL BOTTOM
quadTile["wall_bl"] = gr.newQuad(0,96,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_b"] = gr.newQuad(16,96,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_bdl"] = gr.newQuad(32,96,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_bdm"] = gr.newQuad(48,96,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_bdr"] = gr.newQuad(64,96,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["wall_br"] = gr.newQuad(80,96,16,16,imgTile:getWidth(),imgTile:getHeight())
--QUADS FLOOR
quadTile["floor_db"] = gr.newQuad(0,112,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["floor_dt1"] = gr.newQuad(32,112,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["floor_dt2"] = gr.newQuad(16,112,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["floor_dr"] = gr.newQuad(48,112,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["floor_dl"] = gr.newQuad(64,112,16,16,imgTile:getWidth(),imgTile:getHeight())
quadTile["floor_1"] = gr.newQuad(80,112,16,16,imgTile:getWidth(),imgTile:getHeight())
--QUADS DOOR 1
quadTile["door_l_1"] = gr.newQuad(96,0,8,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_r_1"] = gr.newQuad(104,0,8,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_t_1"] = gr.newQuad(112,0,32,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_b_1"] = gr.newQuad(112,24,32,8,imgTile:getWidth(),imgTile:getHeight())
--QUADS DOOR 2 (Locked Door)
quadTile["door_l_2"] = gr.newQuad(96,0+32,8,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_r_2"] = gr.newQuad(104,0+32,8,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_t_2"] = gr.newQuad(112,0+32,32,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_b_2"] = gr.newQuad(112,24+32,32,8,imgTile:getWidth(),imgTile:getHeight())
--QUADS DOOR 3 (Boss Door)
quadTile["door_l_3"] = gr.newQuad(96,0+64,8,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_r_3"] = gr.newQuad(104,0+64,8,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_t_3"] = gr.newQuad(112,0+64,32,24,imgTile:getWidth(),imgTile:getHeight())
quadTile["door_b_3"] = gr.newQuad(112,24+64,32,8,imgTile:getWidth(),imgTile:getHeight())
player = {
x = 64, y = 64,
w = 12, h = 7,
hit,
mx, my,
speed = 64,
facing = 4,
step = 0,
stepFrame = 0,
hasMap = false
}
player.hit = {
x = (player.w / 2),
y = (player.h)
}
generateDungeon()
game.dungeon[player.mx][player.my].visited = true
gr.setBackgroundColor(0,0,0)
end
function love.update(dt)
m.x = _mn(_mx(_f((ms.getX() - scrn.ox) / scrn.s),0),scrn.w-1)
m.y = _mn(_mx(_f((ms.getY() - scrn.oy) / scrn.s),0),scrn.h-1)
local kSpace = kb.isDown(" ")
local kLeft = kb.isDown("left")
local kRight = kb.isDown("right")
local kUp = kb.isDown("up")
local kDown = kb.isDown("down")
local kShift = kb.isDown("lshift") or kb.isDown("rshift")
if game.isScrolling == false and game.paused == false then
local cx, cy
if kLeft and kRight == false then
player.facing = 1
player.moving = true
cx = player.x - dt * player.speed
cy = player.y
if checkTile(player.mx,player.my,cx-player.hit.x,cy-player.hit.y) == 0 and checkTile(player.mx,player.my,cx-player.hit.x,cy) == 0 then
player.x = cx
if player.x < 24 then
player.x = game.tw * 16
player.mx = player.mx - 1
game.scroll_h = -1
game.dungeon[player.mx][player.my].visited = true
end
end
elseif kRight and kLeft == false then
player.facing = 3
cx = player.x + dt * player.speed
cy = player.y
if checkTile(player.mx,player.my,cx+player.hit.x,cy-player.hit.y) == 0 and checkTile(player.mx,player.my,cx+player.hit.x,cy) == 0 then
player.x = cx
if player.x > game.tw * 16 then
player.x = 24
player.mx = player.mx + 1
game.scroll_h = 1
game.dungeon[player.mx][player.my].visited = true
end
end
end
if kUp and kDown == false then
player.facing = 2
cx = player.x
cy = player.y - dt * player.speed
if checkTile(player.mx,player.my,cx-player.hit.x,cy-player.hit.y) == 0 and checkTile(player.mx,player.my,cx+player.hit.x,cy-player.hit.y) == 0 then
player.y = cy
if player.y < 24 then
player.y = (game.th+.75) * 16
player.my = player.my - 1
game.scroll_v = -1
game.dungeon[player.mx][player.my].visited = true
end
end
elseif kDown and kUp == false then
player.facing = 4
cx = player.x
cy = player.y + dt * player.speed
if checkTile(player.mx,player.my,cx-player.hit.x,cy) == 0 and checkTile(player.mx,player.my,cx+player.hit.x,cy) == 0 then
player.y = cy
if player.y > (game.th+.75) * 16 then
player.y = 24
player.my = player.my + 1
game.scroll_v = 1
game.dungeon[player.mx][player.my].visited = true
end
end
end
if kLeft == false and kRight == false and kUp == false and kDown == false then
player.moving = false
else
player.moving = true
end
if player.moving then
player.step = player.step + dt * 8
if player.step > 1 then
player.step = 0
player.stepFrame = player.stepFrame + 1
if player.stepFrame > 1 then player.stepFrame = 0 end
end
end
for i, e in pairs(game.dungeon[player.mx][player.my].enemy) do
e:update(dt)
end
end
if game.scroll_h ~= 0 or game.scroll_v ~= 0 then
game.isScrolling = true
else
game.isScrolling = false
end
if game.scroll_h < 0 then
game.scroll_h = game.scroll_h + dt * game.scroll_s
if game.scroll_h > 0 then game.scroll_h = 0 end
elseif game.scroll_h > 0 then
game.scroll_h = game.scroll_h - dt * game.scroll_s
if game.scroll_h < 0 then game.scroll_h = 0 end
end
if game.scroll_v < 0 then
game.scroll_v = game.scroll_v + dt * game.scroll_s
if game.scroll_v > 0 then game.scroll_v = 0 end
elseif game.scroll_v > 0 then
game.scroll_v = game.scroll_v - dt * game.scroll_s
if game.scroll_v < 0 then game.scroll_v = 0 end
end
end
function checkTile(mx,my,cx,cy)
return game.dungeon[mx][my].tile[_f(cx/16)][_f(cy/16)].hit
end
function love.draw()
gr.setBlendMode("alpha")
gr.setCanvas(fb[1])
gr.setFont(font3)
local spw = (16*11)
local sph = (16*10)
if game.scroll_v ~= 0 or game.scroll_h ~= 0 then
if game.scroll_v < 0 then
drawLevel(player.mx, player.my+1, scrn.dox, scrn.doy + (sph * game.scroll_v) + sph)
drawLevel(player.mx, player.my , scrn.dox, scrn.doy + (sph * game.scroll_v))
elseif game.scroll_v > 0 then
drawLevel(player.mx, player.my-1, scrn.dox, scrn.doy + (sph * game.scroll_v) - sph)
drawLevel(player.mx, player.my , scrn.dox, scrn.doy + (sph * game.scroll_v))
end
if game.scroll_h < 0 then
drawLevel(player.mx+1, player.my, scrn.dox + (spw * game.scroll_h) + spw, scrn.doy)
drawLevel(player.mx , player.my, scrn.dox + (spw * game.scroll_h), scrn.doy)
elseif game.scroll_h > 0 then
drawLevel(player.mx-1, player.my, scrn.dox + (spw * game.scroll_h) - spw, scrn.doy)
drawLevel(player.mx , player.my, scrn.dox + (spw * game.scroll_h), scrn.doy)
end
else
drawLevel(player.mx, player.my, scrn.dox + spw * game.scroll_h, scrn.doy)
end
if game.paused == true then
gr.setFont(font1)
gr.setColor(0,0,0,100)
gr.rectangle("fill",0,0,scrn.w,scrn.h)
gr.setColor(0,0,0)
gr.print("PAUSED", 7*8, 9*8+1)
gr.setColor(255,255,255)
gr.print("PAUSED", 7*8, 9*8)
end
gr.setFont(font3)
t = "FPS: " .. fps .. "\nPlayer:\n" .. player.mx .. "," .. player.my .. "\n" .. _f(player.x) .. "," .. _f(player.y) .. "\n" .. _f(player.x/16) .. "," .. _f(player.y/16)
gr.setColor(0,0,0)
gr.print(t, 2, 3)
gr.setColor(255,255,255)
gr.print(t, 2, 2)
if showmap then drawMap(12, scrn.h - (game.sh * 8) - 12, 8) end
gr.setCanvas()
gr.setColor(0,0,0)
gr.rectangle("fill", 0, 0, gr.getWidth(), gr.getHeight())
gr.setColor(255,255,255)
gr.rectangle("fill", scrn.ox, scrn.oy, scrn.w * scrn.s, scrn.h * scrn.s)
gr.draw(fb[1], scrn.ox, scrn.oy, 0, scrn.s)
end
function drawMap(ox, oy, bs)
gr.setFont(font3)
for x=1,game.sw do
for y=1,game.sh do
local xx, yy = x-1, y-1
gr.setColor(255,255,255,100)
gr.rectangle("fill", ox + xx * bs, oy + yy * bs, bs, bs)
if game.dungeon[x][y].visited or player.hasMap then
if game.dungeon[x][y].type == "boss" then
gr.setColor(175,0,0)
elseif game.dungeon[x][y].type == "start" then
gr.setColor(0,175,0)
elseif game.dungeon[x][y].bosskey == true then
gr.setColor(175,175,0)
elseif game.dungeon[x][y].branch > 0 then
gr.setColor(100,100,100)
elseif game.dungeon[x][y].deadend == true then
gr.setColor(160,160,160)
elseif game.dungeon[x][y].mark == true then
gr.setColor(100,100,100)
else
gr.setColor(0,0,0,255)
end
gr.rectangle("fill", ox + xx * bs + 1, oy + yy * bs + 1, bs - 2, bs - 2)
local dh, ds = _ce(bs * .5 / 2), _ce(bs * .5)
local l, u, r, d = 1, 2, 3, 4
if game.dungeon[x][y].exit[l] > -1 then
if game.dungeon[x][y].exit[l] == 1 then
gr.setColor(0,0,0,200)
else
gr.setColor(255,0,0,200)
end
gr.rectangle("fill", ox + xx * bs, oy + yy * bs + (bs / 2) - dh, 1, ds)
end
if game.dungeon[x][y].exit[r] > -1 then
if game.dungeon[x][y].exit[r] == 1 then
gr.setColor(0,0,0,200)
else
gr.setColor(255,0,0,200)
end
gr.rectangle("fill", ox + xx * bs + (bs) - 1, oy + yy * bs + (bs / 2) - dh, 1, ds)
end
if game.dungeon[x][y].exit[u] > -1 then
if game.dungeon[x][y].exit[u] == 1 then
gr.setColor(0,0,0,200)
else
gr.setColor(255,0,0,200)
end
gr.rectangle("fill", ox + xx * bs + (bs / 2) - dh, oy + yy * bs, ds, 1)
end
if game.dungeon[x][y].exit[d] > -1 then
if game.dungeon[x][y].exit[d] == 1 then
gr.setColor(0,0,0,200)
else
gr.setColor(255,0,0,200)
end
gr.rectangle("fill", ox + xx * bs + (bs / 2) - dh, oy + yy * bs + (bs) - 1, ds, 1)
end
if debugVar then
gr.setColor(0,0,0,255)
gr.print(game.dungeon[x][y].depth, ox + xx * bs + 5, oy + yy * bs + 6)
end
end
end
end
if debugVar then
for rt, pp in pairs(game.path) do
j = 0
for i, p in pairs(game.path[rt].st) do
j = j + 1
gr.setColor(0,0,0,175)
--gr.print(j, p.x * game.tw + 7, p.y * game.th + 8)
gr.setColor(unpack(p.c))
if j > 1 then
gr.line(ox + p.x * bs + 3.5 - bs, oy + p.y * bs + 3.5 - bs, ox + game.path[rt].st[j-1].x * bs + 3.5 - bs, oy + game.path[rt].st[j-1].y * bs + 3.5 - bs)
end
gr.circle("fill", ox + p.x * bs + 4 - bs, oy + p.y * bs + 4 - bs, 2)
--gr.print(j, p.x * game.tw + 7, p.y * game.th + 7)
end
end
gr.setColor(0,255,0)
gr.circle("fill", ox + player.mx * bs + 4 - bs, oy + player.my * bs + 4 - bs, 2)
else
gr.setColor(0,255,0)
gr.circle("fill", ox + player.mx * bs + (bs / 2) - bs, oy + player.my * bs + (bs / 2) - bs, 2)
end
end
function drawLevel(mx,my,ox,oy)
ox = _f(ox)
oy = _f(oy)
for x=1,game.tw do
for y=0,game.th do
local f = game.dungeon[mx][my].tile[x][y].img.f
local w = game.dungeon[mx][my].tile[x][y].img.w
gr.setColor(255,255,255)
if f ~= "" then
gr.drawq(imgTile, quadTile[f], ox + x * 16, oy + y * 16)
end
if w ~= "" then
gr.drawq(imgTile, quadTile[w], ox + x * 16, oy + y * 16)
end
end
end
if game.dungeon[mx][my].door[1] > 0 then
gr.drawq(imgTile, quadTile["door_l_" .. game.dungeon[mx][my].door[1]], ox + 24, oy + 4.5 * 16)
end
if game.dungeon[mx][my].door[2] > 0 then
gr.drawq(imgTile, quadTile["door_t_" .. game.dungeon[mx][my].door[2]], ox + 5.5 * 16, oy + 8)
end
if game.dungeon[mx][my].door[3] > 0 then
gr.drawq(imgTile, quadTile["door_r_" .. game.dungeon[mx][my].door[3]], ox + (game.tw) * 16, oy + 4.5 * 16)
end
if game.dungeon[mx][my].door[4] > 0 then
gr.drawq(imgTile, quadTile["door_b_" .. game.dungeon[mx][my].door[4]], ox + 5.5 * 16, oy + (game.th) * 16)
end
if game.isScrolling == false then
for i, e in pairs(game.dungeon[mx][my].enemy) do
e:draw()
end
end
if mx == player.mx and my == player.my then
if checkPlayerColEnemy() > -1 then
gr.setColor(255,255,255)
gr.rectangle("fill", _f(ox + player.x - player.hit.x), _f(oy + player.y - player.hit.y), player.hit.x * 2, player.hit.y)
end
gr.setColor(0,0,0)
gr.point(_f(ox + player.x) + .5, _f(oy + player.y) + .5)
gr.setColor(255,255,255)
gr.drawq(imgPlayer,quadPlayer[player.facing][player.stepFrame], _f(ox + player.x), _f(oy + player.y) + 1, 0, 1, 1, 8, 16)
end
for x=1,game.tw do
for y=0,game.th do
local u = game.dungeon[mx][my].tile[x][y].img.u
gr.setColor(255,255,255)
if u ~= "" then
gr.drawq(imgTile, quadTile[u], ox + x * 16, oy + y * 16)
end
end
end
for x=0,game.tw*2-1 do
for y=0,game.th*2-1 do
--gr.setColor(0,0,0,100)
--gr.rectangle("fill", x*8, y*8, 7, 7)
end
end
end
function checkPlayerColEnemy()
local c = -1
for i, e in pairs(game.dungeon[player.mx][player.my].enemy) do
if c == -1 then
if overlap(player.x-player.hit.x, player.y-player.hit.y, player.w, player.h, e.x, e.y, e.w, e.h) then
c = e.id
end
end
end
return c
end
function overlap(x1,y1,w1,h1, x2,y2,w2,h2)
return not (x1+w1 < x2 or x2+w2 < x1 or y1+h1 < y2 or y2+h2 < y1)
end
function love.mousepressed(x, y, button)
if button == "l" then
elseif button == "r" then
elseif button == "m" then
elseif button == "wu" then
elseif button == "wd" then
end
end
function love.keypressed(k)
if k == " " then
for i=1,4 do
if kb.isDown("lshift") then
door(player.mx, player.my, i, 1)
else
door(player.mx, player.my, i, 0)
end
end
end
if k == "p" then
game.paused = not game.paused
end
if k == "m" then
showmap = not showmap
end
if k == "`" then
player.hasMap = true
end
if kb.isDown("lshift") and game.isScrolling == false then
if k == "left" then
if game.dungeon[player.mx][player.my].exit[1] > -1 then
player.mx = player.mx - 1
game.scroll_h = -1
end
elseif k == "up" then
if game.dungeon[player.mx][player.my].exit[2] > -1 then
player.my = player.my - 1
game.scroll_v = -1
end
elseif k == "right" then
if game.dungeon[player.mx][player.my].exit[3] > -1 then
player.mx = player.mx + 1
game.scroll_h = 1
end
elseif k == "down" then
if game.dungeon[player.mx][player.my].exit[4] > -1 then
player.my = player.my + 1
game.scroll_v = 1
end
end
end
if k == "escape" then
love.load()
end
if k == "tab" then
if kb.isDown("lalt") then
scrn.fls = not scrn.fls
updateScaling()
else
local modes = gr.getModes()
local mxs = _f(_mn(modes[1].width / scrn.w), _f((modes[1].height) / scrn.h))
if kb.isDown("lshift") then scrn.ws = scrn.ws - 1 else scrn.ws = scrn.ws + 1 end
if kb.isDown("lctrl") then scrn.ws = 0 end
if scrn.ws > mxs then scrn.ws = 0 end
if scrn.ws < 0 then scrn.ws = mxs end
setScreenMode(scrn.ws)
end
end
end
function love.focus(f)
if f then
else
game.paused = true
end
end
function generateDungeon()
stime = ti.getTime()
-- Set up Game Map
game = {
sw = _r(2,4)*2,
sh = _r(2,4)*2,
tw = 11,
th = 9,
scroll_h = 0,
scroll_v = 0,
scroll_s = 2,
isScrolling = false,
paused = false,
is = 8,
path = {},
dungeon = {},
seed = os.time()
}
math.randomseed(game.seed)
-- Set up Map Screens
local t
for x=0,game.sw+1 do
game.dungeon[x] = {}
for y=0,game.sh+1 do
if y <= game.sw/2 then t = "mtn" elseif x < game.sh/2+1 then t = "dst" else t = "frs" end
game.dungeon[x][y] = createRoom(t)
game.dungeon[x][y].enemy[#game.dungeon[x][y].enemy+1] = enemyPrototype.goomba:new(x, y, 5*16, 5*16)
game.dungeon[x][y].enemy[#game.dungeon[x][y].enemy+1] = enemyPrototype.goomba:new(x, y, 5.5*16, 5*16)
game.dungeon[x][y].enemy[#game.dungeon[x][y].enemy+1] = enemyPrototype.goomba:new(x, y, 6*16, 5*16)
game.dungeon[x][y].enemy[#game.dungeon[x][y].enemy+1] = enemyPrototype.goomba:new(x, y, 6.5*16, 5*16)
end
end
createPath()
local l, u, r, d = 1, 2, 3, 4
for x=0,game.sw+1 do
for y=0,game.sh+1 do
setTiles(x, y)
end
end
-- print(table.save(game.dungeon, true))
print("Generation time:", ti.getTime() - stime)
end
function door(x, y, dr, oc)
local dr2 = wrapDir(dr)
local x2, y2 = x, y
if x >= 1 and y >= 1 and x <= game.sw and y <= game.sh and game.dungeon[x][y].exit[dr] > -1 then
local l, u, r, d = 1, 2, 3, 4
game.dungeon[x][y].door[dr] = oc
if dr == l then
game.dungeon[x][y].tile[1][5].hit = oc
x2 = x - 1
elseif dr == u then
game.dungeon[x][y].tile[6][1].hit = oc
y2 = y - 1
elseif dr == r then
game.dungeon[x][y].tile[game.tw][5].hit = oc
x2 = x + 1
elseif dr == d then
game.dungeon[x][y].tile[6][game.th].hit = oc
y2 = y + 1
end
--Open other side of door too
game.dungeon[x2][y2].door[dr2] = oc
if dr2 == l then
game.dungeon[x2][y2].tile[1][5].hit = oc
elseif dr2 == u then
game.dungeon[x2][y2].tile[6][1].hit = oc
elseif dr2 == r then
game.dungeon[x2][y2].tile[game.tw][5].hit = oc
elseif dr2 == d then
game.dungeon[x2][y2].tile[6][game.th].hit = oc
end
print("DOOR", x, y, dr, "BDOOR", x2, y2, dr2)
end
end
function createRoom(t)
local r = {
exit = { [1] = -1, [2] = -1, [3] = -1, [4] = -1 },
door = { [1] = 0, [2] = 0, [3] = 0, [4] = 0 },
back = { [1] = {}, [2] = {}, [3] = {}, [4] = {} },
mark = false,
type = "room",
depth = -1,
branch = 0,
key = false,
bosskey = false,
deadend = false,
tile = {},
visited = false,
enemy = {}
}
for i=1,4 do
r.back[i] = { mx = -1, my = -1, d = -1 }
end
for x=0,game.tw+1 do
r.tile[x] = {}
for y=0,game.th+1 do
r.tile[x][y] = { hit = 1, img = { f = "", w = "", u = "" } }
end
end
for x=2,game.tw-1 do
for y=2,game.th-1 do
r.tile[x][y].hit = 0
end
end
return r
end
function setTiles(x, y)
local l, u, r, d = 1, 2, 3, 4
for x2=1,game.tw-1 do
for y2=1,game.th-1 do
game.dungeon[x][y].tile[x2][y2].img.f = "floor_1"
end
end
game.dungeon[x][y].tile[1][0].img.w = "wall_tl1"
game.dungeon[x][y].tile[1][1].img.w = "wall_tl2"
game.dungeon[x][y].tile[game.tw][0].img.w = "wall_tr1"
game.dungeon[x][y].tile[game.tw][1].img.w = "wall_tr2"
game.dungeon[x][y].tile[1][game.th].img.w = "wall_bl"
game.dungeon[x][y].tile[game.tw][game.th].img.w = "wall_br"
for x2 = 2, game.tw-1 do
game.dungeon[x][y].tile[x2][0].img.w = "wall_t1"
game.dungeon[x][y].tile[x2][1].img.w = "wall_t2"
game.dungeon[x][y].tile[x2][game.th].img.w = "wall_b"
end
for y2 = 2, game.th-1 do
game.dungeon[x][y].tile[1][y2].img.w = "wall_l"
game.dungeon[x][y].tile[game.tw][y2].img.w = "wall_r"
end
for i = 1, 4 do
if i == l and game.dungeon[x][y].exit[l] > 0 then
game.dungeon[x][y].tile[1][4].img.w = "wall_ldt"
game.dungeon[x][y].tile[1][5].img.w = ""
game.dungeon[x][y].tile[1][4].img.u = "wall_ldb"
game.dungeon[x][y].tile[1][5].img.f = "floor_dl"
elseif i == u and game.dungeon[x][y].exit[u] > 0 then
game.dungeon[x][y].tile[5][0].img.w = "wall_tdl1"
game.dungeon[x][y].tile[5][1].img.w = "wall_tdl2"
game.dungeon[x][y].tile[6][0].img.u = "wall_tdm1"
game.dungeon[x][y].tile[6][0].img.w = ""
game.dungeon[x][y].tile[6][1].img.w = ""
game.dungeon[x][y].tile[7][0].img.w = "wall_tdr1"
game.dungeon[x][y].tile[7][1].img.w = "wall_tdr2"
game.dungeon[x][y].tile[6][0].img.f = "floor_dt1"
game.dungeon[x][y].tile[6][1].img.f = "floor_dt2"
elseif i == r and game.dungeon[x][y].exit[r] > 0 then
game.dungeon[x][y].tile[game.tw][4].img.w = "wall_rdt"
game.dungeon[x][y].tile[game.tw][5].img.w = ""
game.dungeon[x][y].tile[game.tw][4].img.u = "wall_rdb"
game.dungeon[x][y].tile[game.tw][5].img.f = "floor_dr"
elseif i == d and game.dungeon[x][y].exit[d] > 0 then
game.dungeon[x][y].tile[5][game.th].img.w = "wall_bdl"
game.dungeon[x][y].tile[6][game.th].img.w = ""
game.dungeon[x][y].tile[6][game.th].img.u = "wall_bdm"
game.dungeon[x][y].tile[7][game.th].img.w = "wall_bdr"
game.dungeon[x][y].tile[6][game.th].img.f = "floor_db"
end
end
end
function createPath()
local tmpEmpty = {}
local runthrough = 1
local filled = false
local l, u, r, d = 1, 2, 3, 4
local nr, mnr, c
repeat
local rt = runthrough
local i = 1
local k = 0
c = {_r(50,150),_r(50,150),_r(50,150)}
if runthrough == 1 then
local xx = _r(1,game.sw)
local yy = game.sh
game.path[1] = { x = xx, y = yy, cx = xx, cy = yy, sx = xx, sy = yy, st = {}, bel, applic = true }
player.mx = xx
player.my = yy
done = false
game.path[rt].st[1] = { x = game.path[1].x, y = game.path[1].y, d = 0, c = c }
game.dungeon[game.path[1].x][game.path[1].y].type = "start"
else
local te = _r(1,#tmpEmpty)
game.path[rt] = { x, y, cx, cy, sx = tmpEmpty[te].x, sy = tmpEmpty[te].y, st = {}, bel }
done = false
game.path[rt].x = game.path[rt].sx
game.path[rt].y = game.path[rt].sy
local x, y, neigh = -1, -1, {}
for h=1,4 do
if h == l then
if game.dungeon[game.path[rt].x-1][game.path[rt].y].mark == true then
neigh[#neigh+1] = { x = game.path[rt].x-1, y = game.path[rt].y, d = h }
end
elseif h == u then
if game.dungeon[game.path[rt].x][game.path[rt].y-1].mark == true then
neigh[#neigh+1] = { x = game.path[rt].x, y = game.path[rt].y-1, d = h }
end
elseif h == r then
if game.dungeon[game.path[rt].x+1][game.path[rt].y].mark == true then
neigh[#neigh+1] = { x = game.path[rt].x+1, y = game.path[rt].y, d = h }
end
elseif h == d then
if game.dungeon[game.path[rt].x][game.path[rt].y+1].mark == true then
neigh[#neigh+1] = { x = game.path[rt].x, y = game.path[rt].y+1, d = h }
end
end
end
if #neigh > 0 then
local r = _r(1,#neigh)
x = neigh[r].x
y = neigh[r].y
dr = wrapDir(neigh[r].d)
game.path[rt].st[1] = { x = x, y = y, d = dr, c = c }
game.dungeon[x][y].exit[dr] = 1
game.dungeon[x][y].door[dr] = 1
game.dungeon[x][y].branch = game.dungeon[x][y].branch - 1
game.path[rt].st[2] = { x = game.path[rt].x, y = game.path[rt].y, d = neigh[r].d, c = c }
i = i + 1
else
game.path[rt].st[1] = { x = game.path[rt].x, y = game.path[rt].y, d = 0, c = c }
end
end
mnr = _r(3,10)
game.dungeon[game.path[rt].x][game.path[rt].y].mark = true
nr = 1
while done == false do
--Choose Direction
dr = _r(1,4)
local loop = true
local j = 0
while loop == true do
j = j + 1
--Check Direction
if dr == l then
game.path[rt].cx = game.path[rt].x-1
game.path[rt].cy = game.path[rt].y
elseif dr == u then
game.path[rt].cx = game.path[rt].x
game.path[rt].cy = game.path[rt].y-1
elseif dr == r then
game.path[rt].cx = game.path[rt].x+1
game.path[rt].cy = game.path[rt].y
elseif dr == d then
game.path[rt].cx = game.path[rt].x
game.path[rt].cy = game.path[rt].y+1
end
if game.path[rt].cx > 0 and game.path[rt].cy > 0 and game.path[rt].cx < game.sw + 1 and game.path[rt].cy < game.sh + 1 then
nb = game.dungeon[game.path[rt].cx][game.path[rt].cy].mark
if nb == false then
nr = nr + 1
game.dungeon[game.path[rt].cx][game.path[rt].cy].mark = true
game.dungeon[game.path[rt].x][game.path[rt].y].exit[dr] = 1
game.dungeon[game.path[rt].x][game.path[rt].y].door[dr] = 1
i = i + 1
game.path[rt].st[i] = { x = game.path[rt].cx, y = game.path[rt].cy, d = dr, c = c }
game.path[rt].x = game.path[rt].cx
game.path[rt].y = game.path[rt].cy
loop = false
k = k + 1
end
end
if j >= 20 then
loop = false
k = k + 1
end
end
if k >= 100 or nr >= mnr then
done = true
end
end
tmpEmpty = {}
local f = 0
local f2 = 0
for x=1,game.sw do
for y=1,game.sh do
if game.dungeon[x][y].mark == false then
f = f + 1
if game.dungeon[x-1][y].mark or game.dungeon[x][y-1].mark or game.dungeon[x+1][y].mark or game.dungeon[x][y+1].mark then
f2 = f2 + 1
tmpEmpty[f2] = { x = x, y = y }
end
end
end
end
if f == 0 then
filled = true
end
runthrough = runthrough + 1
if runthrough > 1000 then
filled = true
end
until filled == true
local lng = { path = 0, len = 0 }
for i, p in pairs(game.path) do
local l = #p.st
if l > lng.len and game.dungeon[p.st[#p.st].x][p.st[#p.st].y].branch == 0 then
lng.len = l
lng.path = i
end
game.dungeon[p.st[#p.st].x][p.st[#p.st].y].deadend = true
end
local dx, dy = game.path[lng.path].st[lng.len].x, game.path[lng.path].st[lng.len].y
local dx2, dy2 = game.path[lng.path].st[lng.len-1].x, game.path[lng.path].st[lng.len-1].y
game.dungeon[dx][dy].type = "boss"
-- print(game.path[lng.path].st[lng.len].x, game.path[lng.path].st[lng.len].y)
-- print(game.path[lng.path].st[lng.len-1].x, game.path[lng.path].st[lng.len-1].y)
--FIND ALL DEAD ENDS
local potenkey = {}
for x=1,game.sw do
for y=1,game.sh do
if game.dungeon[x][y].deadend == true and game.dungeon[x][y].type == "room" then
potenkey[#potenkey+1] = { x = x, y = y }
end
end
end
--PLACE BOSS KEY
local kr = _r(1,#potenkey)
game.dungeon[potenkey[kr].x][potenkey[kr].y].bosskey = true
--MARK ROOM DEPTH
local sdepth = 0
for i, p in pairs(game.path) do
for j=1,#p.st do
if j == 1 then
if i == 1 then
sdepth = 0
else
sdepth = game.dungeon[p.st[j].x][p.st[j].y].depth
end
else
sdepth = sdepth + 1
end
game.dungeon[p.st[j].x][p.st[j].y].depth = sdepth
end
end
--MARK DOORS
for x=1,game.sw do
for y=1,game.sh do
if game.dungeon[x][y].exit[l] > 0 then
game.dungeon[x-1][y].exit[r] = 1
game.dungeon[x-1][y].door[r] = 1
game.dungeon[x][y].back[l] = { mx = x - 1, my = y, d = r }
end
if game.dungeon[x][y].exit[r] > 0 then
game.dungeon[x+1][y].exit[l] = 1
game.dungeon[x+1][y].door[l] = 1
game.dungeon[x][y].back[r] = { mx = x + 1, my = y, d = l }
end
if game.dungeon[x][y].exit[u] > 0 then
game.dungeon[x][y-1].exit[d] = 1
game.dungeon[x][y-1].door[d] = 1
game.dungeon[x][y].back[u] = { mx = x, my = y - 1, d = d }
end
if game.dungeon[x][y].exit[d] > 0 then
game.dungeon[x][y+1].exit[u] = 1
game.dungeon[x][y+1].door[u] = 1
game.dungeon[x][y].back[d] = { mx = x, my = y + 1, d = u }
end
end
end
--Lock the Boss Door with the special Boss Key lock
for i=1,4 do
door(dx, dy, i, 3)
end
end
function wrapDir(n)
n = n + 2
if n == 5 then n = 1 end
if n == 6 then n = 2 end
return n
end
function setScreenMode(s)
if s == 0 then
modes = gr.getModes()
gr.setMode(modes[1].width, modes[1].height, true, false)
else
gr.setMode(scrn.w * s, scrn.h * s, false, false)
end
updateScaling()
end
function updateScaling()
scrn.s = _mn(gr.getWidth() / scrn.w, gr.getHeight() / scrn.h)
if scrn.fls then
scrn.s = _f(scrn.s)
end
scrn.ox = (gr.getWidth() - (scrn.w * scrn.s)) / 2
scrn.oy = (gr.getHeight() - (scrn.h * scrn.s)) / 2
end
function distanceFrom(x1,y1,x2,y2) return _sq((x2 - x1) ^ 2 + (y2 - y1) ^ 2) end
function degToRad(d) return d * pi / 180 end
function sort(T) table.sort(T, function(a, b) return a.y < b.y end ) end
function formatNumber(number)
return (string.format("%d", number):reverse():gsub( "(%d%d%d)" , "%1," ):reverse():gsub("^(-?),","%1"))
end
function createBuffers()
fb = {
[1] = gr.newCanvas(1024, 1024)
}
for i, f in pairs(fb) do
f:setFilter("nearest", "nearest")
end
return true
end
Note: This will not run on 90% of Löve if not 100% as it's broken now in how it's displayed. Also, there are no images included since they're not relevant. All you need is the code that generates the maze. It's a TERRIBLE mess so don't complain. The MAIN code is in the function "createPath()".
It works by first creating a random path from the start square (room) off in a random direction for a specified time or until it closes itself in. The last square is marked as the end (exit or boss room) square. Then it loops a few times doing the same thing, but instead it first chooses a random square that A) is not the start, end or special room and B) has at least one empty neighbor. Then starts with one of those empty neighbors and draws a path until a specified time or it closes itself in. It also places special rooms, in this case what would have been a "key" room.
It can make a maze of any size if need be and can be set to fill in the entire grid or stop earlier.
I created this before anyone had even heard of Binding of Isaac.