Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

Weave Maze: an experiment with meshes

edited October 2017 in Code Sharing Posts: 489

The code below draws a weave maze using a mesh (and does nothing more) (updated). An example of its output is below:

image

--
-- Weave Maze
--

supportedOrientations(LANDSCAPE_ANY)
displayMode(FULLSCREEN)
function setup()
    len = 32 -- Size of tiles
    xn = math.floor(WIDTH/len)
    yn = math.floor(HEIGHT/len)
    ox = (WIDTH - xn * len) / 2
    oy = (HEIGHT - yn * len) / 2
    bCol = color(33, 42, 109) -- background
    fCol = color(255, 127, 0) -- foreground
    local m = newMaze(xn, yn)
    mm = mMesh(m, len)
    font("ArialRoundedMTBold")
    fontSize(len * 0.6)
    smooth()
end

function draw()
    background(0)
    pushMatrix()
    translate(ox, oy)
    mm:draw()
    stroke(bCol)
    strokeWidth(2)
    fill(fCol)
    ellipse(len / 2, len * (yn - 1 / 2), len * 0.9)
    ellipse(len * (xn - 1 / 2), len / 2, len * 0.9)
    fill(bCol)
    text("S", len / 2, len * (yn - 1 / 2))
    text("E", len * (xn - 1 / 2), len / 2)
    popMatrix()
end

function newMaze()
    local m = {}
    local s = {}
    local cell = {math.random(xn), math.random(yn)}
    m[index(cell)] = {}
    table.insert(s, cell)
    while #s > 0 do
        cell = s[#s]
        local ds = dirs(m, cell)
        while #ds > 0 do
            local d = ds[math.random(#ds)]
            cell = move(m, cell, d, s)
            ds = dirs(m, cell)
        end
        table.remove(s)
    end
    return m
end

function index(cell)
    return (cell[2] - 1) * xn + cell[1]
end

function dirs(m, cell)
    local ds = {}
    local x = cell[1]
    local y = cell[2]
    local ncell
    local tcell
    local L, R, U, D
    local mi = m[index(cell)] or {}
    if x > 1 and not mi.W then
        ncell = {x - 1, y}
        if not m[index(ncell)] then L = true
        elseif x > 2 then
            tcell = {x - 1, y}
            local nmi = m[index(tcell)] or {}
            if not nmi.W and not nmi.E then
                ncell = {x - 2, y}
                if not m[index(ncell)] then L = true end
            end
        end        
    end
    if x < xn and not mi.E then
        ncell = {x + 1, y}
        if not m[index(ncell)] then R = true
        elseif x < xn - 1 then
            tcell = {x + 1, y}
            local nmi = m[index(tcell)] or {}
            if not nmi.W and not nmi.E then
                ncell = {x + 2, y}
                if not m[index(ncell)] then R = true end
            end
        end
    end      
    if y > 1 and not mi.S then
        ncell = {x, y - 1}
        if not m[index(ncell)] then D = true
        elseif y > 2 then
            tcell = {x, y - 1}
            local nmi = m[index(tcell)] or {}
            if not nmi.N and not nmi.S then
                ncell = {x, y - 2}
                if not m[index(ncell)] then D = true end
            end
        end
    end
    if y < yn and not mi.N then
        ncell = {x, y + 1}
        if not m[index(ncell)] then U = true
        elseif y < yn - 1 then
            tcell = {x, y + 1}
            local nmi = m[index(tcell)] or {}
            if not nmi.N and not nmi.S then
                ncell = {x, y + 2}
                if not m[index(ncell)] then U = true end
            end
        end
    end
    if L then table.insert(ds, "L") end
    if R then table.insert(ds, "R") end
    if U then table.insert(ds, "U") end
    if D then table.insert(ds, "D") end
    return ds
end

function move(m, cell, d, s)
    local mi = m[index(cell)]
    local x = cell[1]
    local y = cell[2]
    local nCell, w1, w2, dx, dy
    if d == "L" then
        w1 = "W"; w2 = "E"
        dx = -1; dy = 0
    elseif d == "R" then
        w1 = "E"; w2 = "W"
        dx = 1; dy = 0
    elseif d == "U" then
        w1 = "N"; w2 = "S"
        dx = 0; dy = 1
    elseif d == "D" then
        w1 = "S"; w2 = "N"
        dx = 0; dy = -1
    end
    mi[w1] = true
    x = x + dx; y = y + dy
    mi = m[index({x, y})]
    if mi then
        mi.T = true
        x = x + dx; y = y + dy
    end        
    nCell = {x, y}
    m[index(nCell)] = {[w2] = true}
    table.insert(s, nCell)
    return nCell
end

function mMesh(m, l)
    local mMesh = mesh()
    mMesh.texture = mTex()
    for j = 1, yn do
        for i = 1, xn do
            local x = (i - 1) * l + l/2
            local y = (j - 1) * l + l/2
            local idx = mMesh:addRect(x, y, l, l)
            local u, v = texIndex(m[index({i, j})])
            mMesh:setRectTex(idx, u, v, 1/8, 1/8)
        end
    end
    return mMesh
end

function mTex()
    local l = 64 -- Size of tile textures
    local img = image(l * 8, l * 8)
    local h = l/2
    local q = l * 3/5 -- Width of path
    local e = q/2
    local s = l/8 -- Margin for tunnel
    local hpe = h + e
    local hme = h - e
    local hpes = hpe + s
    local hmes = hme - s
    setContext(img)
    noSmooth()
    rectMode(CORNER)
    noStroke()
    fill(bCol)
    rect(0, 0, l * 8, l * 8)
    fill(fCol)
    for i = 0, 31 do
        local i1 = i % 2
        local i2 = math.floor(i / 2) % 2
        local i3 = math.floor(i / 4) % 2
        local i4 = math.floor(i / 8) % 2
        local i5 = math.floor(i / 16) % 2
        local x = (i % 8) * l
        local y = math.floor(i/8) * l
        if i1 == 1 then rect(x + hme, y + hme, q, hpe) end
        if i2 == 1 then rect(x + hme, y + hme, hpe, q) end
        if i3 == 1 then rect(x + hme, y, q, hpe) end
        if i4 == 1 then rect(x, y + hme, hpe, q) end
        if i5 == 1 then
            if i1 == 1 or i3 == 1 then
                rect(x, y + hme, hmes, q)
                rect(x + hpes, y + hme, hmes, q)
                if i1 == 0 then rect(x + hme, y + hpe, q, s)  end
                if i3 == 0 then rect(x + hme, y + hmes, q, s) end
            else
                rect(x + hme, y, q, hmes)
                rect(x + hme, y + hpes, q, hmes)
                if i2 == 0 then rect(x + hpe, y + hme, s, q) end
                if i4 == 0 then rect(x + hmes, y + hme, s, q) end
            end
        end
    end
    setContext()
    return img
end

function texIndex(mi)
    local i = 0
    if mi.N then i = i + 1 end
    if mi.E then i = i + 2 end
    if mi.S then i = i + 4 end
    if mi.W then i = i + 8 end
    if mi.T then i = i + 16 end
    return (i % 8)/8, math.floor(i / 8) / 8
end
Tagged:

Comments

Sign In or Register to comment.