building a map from mapsize variable.

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
forestwolf42
Prole
Posts: 24
Joined: Tue Dec 20, 2011 5:18 pm

building a map from mapsize variable.

Post by forestwolf42 »

So I'm currently building a random maze generator, and for overall flexibility I want to be able to change map size in two simple variables, (SizeY and SizeX), but at the moment I'm unsure as how to construct a map table from these variables, I'm basically trying to make foo fill the map with walls (which are 2's in my code) according to SizeX and SizeY by using similar code to the love.graphics.draw for filling in the map, but I don't entirely understands how that works in the first place so I'm unsure how to adapt it to my purposes.

I looked at the http://www.lua.org/manual/5.1/manual.html#2.5.7 for info on tables but my brain basically melted trying to figure out what it all meant.
Attachments
MazeMaker.love
Working this time.
(624 Bytes) Downloaded 174 times
Last edited by forestwolf42 on Tue Jan 10, 2012 8:41 pm, edited 1 time in total.
User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

Re: building a map from mapsize variable.

Post by MarekkPie »

Did you package this correctly? I am not seeing any .lua files.
User avatar
forestwolf42
Prole
Posts: 24
Joined: Tue Dec 20, 2011 5:18 pm

Re: building a map from mapsize variable.

Post by forestwolf42 »

Apparently not, let me fix that.
User avatar
forestwolf42
Prole
Posts: 24
Joined: Tue Dec 20, 2011 5:18 pm

Re: building a map from mapsize variable.

Post by forestwolf42 »

I fixed it, sorry about that.
User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

Re: building a map from mapsize variable.

Post by MarekkPie »

http://en.wikipedia.org/wiki/Maze_generation_algorithm

This would be a good place to start.
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: building a map from mapsize variable.

Post by Jasoco »

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.
Attachments
MapGen.love
Use at your own risk. It probably won't run at all.
(55.68 KiB) Downloaded 183 times
User avatar
forestwolf42
Prole
Posts: 24
Joined: Tue Dec 20, 2011 5:18 pm

Re: building a map from mapsize variable.

Post by forestwolf42 »

MarekkPie wrote:http://en.wikipedia.org/wiki/Maze_generation_algorithm

This would be a good place to start.
I have looked at that, but it's not really relevant to my question of making the starting map table based off of two variables, instead of simply filling a pre-made table.
User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

Re: building a map from mapsize variable.

Post by MarekkPie »

Well, if you just want to build a table of size WIDTH, HEIGHT, just:

Code: Select all

map = {}
for j, HEIGHT do
  for i, WIDTH do
    table.insert(map, {x = i, y = j, visited = false})
  end
end
At that point, then follow one of the algorithms in that wikipedia article. If that still isn't what you need, then I have no idea what you're asking.
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: building a map from mapsize variable.

Post by Jasoco »

As I said, you start with a grid of a certain size:

Code: Select all

map = {}
for x = 0, mapWidth - 1 do
  map[x] = {}
  for y = 0, mapHeight - 1 do
    map[x][y] = { marked = false }
  end
end
Is my preferred grid creation method.

Pick a random start point. Draw a random path in random directions until you either reach a preset destination or box yourself in. Then repeat the path-finding algorithm by choosing a starting point with at least one empty neighbor and draw paths out in the same manner until either all squares are filled or you have drawn the required amount of paths depending on how you want the maze to look.

If you want you can even pre-mark squares as "unusable" to make a pattern and have it fill that in so you can create dungeons with neat shapes instead of solid blocks.

That's basically the gist. It took a while for me to even do that myself and am going to have to recode it again at some point in the future to be more modern. But it works. (At least the maze part. The graphical end is screwed up in my example because it's a hybrid of multiple versions of 0.8.0 but was created during 0.7.2.
User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

Re: building a map from mapsize variable.

Post by MarekkPie »

Jasoco's map maker is better; the node coordinates are indexed as they should be for a matrix.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 1 guest