#### Howdy, Stranger!

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

# [SOLVED] Trying to figure out collision detection for a randomly generated maze

edited December 2014 Posts: 18

I am making a game that involves tilting a ball through a randomly generated maze. I retrieved some code that randomly generates a maze from Wildbill from http://codea.io/talk/discussion/1275/open-the-maze/p1. I added a ball that can be tilted through the maze and I have enabled touch detection on the outer edges of the maze so that the ball cannot pass through. My problem is that I cannot seem to figure out how to detect when the ball is touching the lines inside the maze, so that the ball will not simply pass through each line. Does anyone know how to get the ball to not pass through the lines of the maze with the code I am currently using or with any other code that can randomly generate a maze and can allow a ball to be tilted through? Any help would be much appreciated.

Thanks,

Chris

Tagged:

## Comments

• edited December 2014 Posts: 18
``````local ballX
local ballY
local mazeDraw
function setup()

displayMode(FULLSCREEN)
EAST = 0
NORTH = 1
WEST = 2
SOUTH = 3
EWALL = 1
NWALL = 2
WWALL = 4
SWALL = 8
XOFF = 30
YOFF = 70
d=0
ALLWALLS = EWALL + NWALL + WWALL + SWALL
VISITED = 16
NMAX = 15
mazeDraw = true
N = 15
pN = 15
M = WIDTH
XYOFF = XOFF

if HEIGHT < WIDTH then
M = HEIGHT
XYOFF = YOFF
end

stack = {}
startx = 1; starty = 1
endx  = N; endy = N
createmaze(N, startx, starty, endx, endy)
--solvemaze()
ballX = 210
ballY = 60
end

function draw()

-- This sets a dark background color
background(255, 0, 0, 255)
if mazeDraw == true then
ballX = ballX + Gravity.x*12
ballY = ballY + Gravity.y*12
-- This sets the line thickness
-- See if maze size has changed
strokeWidth(5)

if pN ~= N then
createmaze(N, startx, starty, endx, endy)
pN = N
end

for i=1, N do
x = XOFF + (i-1)*S
for j=1, N do
y = YOFF + (j-1)*S
c = maze[i][j]
w = c%VISITED
we = w%2
wn = math.floor(w/NWALL)%2
ww = math.floor(w/WWALL)%2
ws = math.floor(w/SWALL)
fill(255, 255, 255, 255)
if we == 1 then
line(x+S+150, y+20, x+S+150, y-S+20)
end
if wn == 1 then
line(x+150, y+20, x+S+150, y+20)
end
if ww == 1 then
line(x+150, y+20, x+150, y-S+20)
end
if ws == 1 then
line(x+150, y-S+20, x+S+150, y-S+20)
end
end
end

fontSize(30)
font("AmericanTypewriter-Bold")
text("Tilt the ball through the maze!", 512, 700)
strokeWidth(5)
stroke(0, 73, 255, 255)
fill(0, 78, 255, 255)
ellipse(ballX, ballY, 30)
fill(255, 255, 255, 255)
stroke(255, 255, 255, 255)
if ballX > x+S+150 and ballY < y+20 and ballX > y-S+20 then
ballX = ballX - 20
ballY = ballY - 20
end
if ballY > y+20 then
ballX = ballX - 20
ballY = ballY - 20
end
if ballX < 180 then
ballX = ballX + 20
end
if ballY < 60 then
ballY = ballY + 20
end
end
if ballX < 780 and ballX > 760 and ballY > 650 and ballY < 670 then
fontSize(30)
font("Futura-Medium")
text("You made it to the end of the maze!", 512, 384)
mazeDraw = false
end
end
function createmaze(n, sx, sy, ex, ey)
if mazeDraw == true then
if ex > N then
ex = N; ey = N
end
S = (M - 2*XYOFF)/N
maze = {}
for i=0, NMAX+1 do
maze[i] = {}
for j = 0, NMAX+1 do
maze[i][j] = ALLWALLS
if i == 0 or i == N+1 then
maze[i][j] = maze[i][j] + VISITED
elseif j == 0 or j == N+1 then
maze[i][j] = maze[i][j] + VISITED
end

end
end

x = ex; y = ey
sp = 1
setvisited(ex, ey)
erasewalls(sx-1, sy, sx, sy)
erasewalls(ex, ey, ex+1, ey)
while true do
nx, ny = getunvisitedneighbor(x, y)
if nx < 0 then
x, y = pop()
if sp == 1 then
break
end
else
setvisited(nx, ny)
push(x, y)
erasewalls(x, y, nx, ny)
x = nx; y = ny

end
end
end
end
function push(a, b)
stack[sp]  = a
stack[sp+1] = b
sp = sp + 2
end
function pop()
sp = sp - 1
b = stack[sp]
a = stack[sp-1]
sp = sp - 1
return a, b
end
function getneighbor(x, y, d)
--print("x ", x, "y ", y, "d ", d)
if d == EAST then
x = x + 1
elseif d == NORTH then
y = y + 1
elseif d == WEST then
x = x -1
else
y = y - 1
end
return x, y
end
function notvisited(x, y)
if x < 1 or x > N then
return false
end
if y < 1 or y > N then
return false
end
v = math.floor(maze[x][y] / VISITED)
if v >= 1 then
return false
else
return true
end
end
function setvisited(x, y)
maze[x][y] = maze[x][y] + VISITED
end
function getunvisitedneighbor(x, y)
nu = 0
uds = {}
for i=EAST, SOUTH do
nx, ny = getneighbor(x, y, i)
if notvisited(nx, ny)then
nu = nu + 1
uds[nu] = i
end
end
if nu == 0 then
return -1, -1
end
td = math.random(1, nu)
nx, ny = getneighbor(x, y, uds[td])
return nx, ny
end
function getdirection(x, y, nx, ny)
if nx > x then
d = EAST
elseif ny > y then
d = NORTH
elseif nx < x then
d = WEST
else
d = SOUTH
end
return d
end
function erasewalls(x, y, nx, ny)
d = getdirection(x, y, nx, ny)
if d == EAST then
maze[x][y] = maze[x][y] - EWALL
maze[nx][ny] = maze[nx][ny] - WWALL
elseif d == NORTH then
maze[x][y] = maze[x][y] - NWALL
maze[nx][ny] = maze[nx][ny] - SWALL
elseif d == WEST then
maze[x][y] = maze[x][y] - WWALL
maze[nx][ny] = maze[nx][ny] - EWALL
else
maze[x][y] = maze[x][y] - SWALL
maze[nx][ny] = maze[nx][ny] - NWALL
end
end

``````
• Mod
Posts: 9,979

@ChrisKarpinski The easiest way is to use physics.body with EDGE. EDGE would be used to draw all the lines. Then let the physics engine do all the collision testing. I already did what you're trying to do using physics.body and it's posted somewhere in this forum. I'll try to find it and post the link.

• Posts: 342

Depending on the size of the maze, you could use physics. I can't run the code right now, or I would give a better answer. But I think physics is probably your most viable option.

• Mod
Posts: 9,979

@ChrisKarpinski Here's the code that I added physics.body to. I did it in August 2013. It looks like we started out with the same code.

``````supportedOrientations(PORTRAIT)
displayMode(FULLSCREEN)

function setup()
c1=physics.body(CIRCLE,10)
c1.x=700
c1.y=800
c1.gravityScale=0
c1.sleepingAllowed=false

tab1={}
tab2={}

EAST = 0
NORTH = 1
WEST = 2
SOUTH = 3
EWALL = 1
NWALL = 2
WWALL = 4
SWALL = 8
XOFF = 30
YOFF = 70
ALLWALLS = EWALL + NWALL + WWALL + SWALL
VISITED = 16
NMAX = 40
N=10  -- maze size
pN = N
M = WIDTH
XYOFF = XOFF
stack = {}
startx = 1; starty = 1
endx  = N; endy = N
createmaze(N, startx, starty, endx, endy)
done=false
end

function draw()
background(0,0,0)
translate(0,100)
fill(255, 0, 0, 255)
strokeWidth(2)
ellipse(c1.x,c1.y,20)
c1.x=c1.x+Gravity.x*10
c1.y=c1.y+Gravity.y*10
strokeWidth(5)
for i=1, N do
x = XOFF + (i-1)*S
for j=1, N do
y = YOFF + (j-1)*S
c = maze[i][j]
w = c%VISITED
we = w%2
wn = math.floor(w/NWALL)%2
ww = math.floor(w/WWALL)%2
ws = math.floor(w/SWALL)
if we == 1 then
line(x+S, y, x+S, y-S)
pb(x+S,y,x+S,y-S)
end
if wn == 1 then
line(x, y, x+S, y)
pb(x, y, x+S, y)
end
if ww == 1 then
line(x, y, x, y-S)
pb(x, y, x, y-S)
end
if ws == 1 then
line(x, y-S, x+S, y-S)
pb(x, y-S, x+S, y-S)
end
end
end
done=true
end

function pb(x,y,x1,y1)
local z
if not done then
for z=1,#tab1 do
if tab1[z].x==x and tab1[z].y==y and
tab1[z].z==x1 and tab1[z].w==y1 then
return
end
end
table.insert(tab1,vec4(x,y,x1,y1))
table.insert(tab2,physics.body(EDGE,vec2(x,y),vec2(x1,y1)))
tab2[#tab2].sleepingAllowed=false
end
end

function createmaze(n, sx, sy, ex, ey)
if ex > N then
ex = N; ey = N
end
S = math.floor((M - 2*XYOFF)/N)
maze = {}
for i=0, NMAX+1 do
maze[i] = {}
for j = 0, NMAX+1 do
maze[i][j] = ALLWALLS
if i == 0 or i == N+1 then
maze[i][j] = maze[i][j] + VISITED
elseif j == 0 or j == N+1 then
maze[i][j] = maze[i][j] + VISITED
end
end
end
x = ex; y = ey
sp = 1
setvisited(ex, ey)
erasewalls(sx-1, sy, sx, sy)
erasewalls(ex, ey, ex+1, ey)
while true do
nx, ny = getunvisitedneighbor(x, y)
if nx < 0 then
x, y = pop()
if sp == 1 then
break
end
else
setvisited(nx, ny)
push(x, y)
erasewalls(x, y, nx, ny)
x = nx; y = ny
end
end
end

function push(a, b)
stack[sp]  = a
stack[sp+1] = b
sp = sp + 2
end

function pop()
sp = sp - 1
b = stack[sp]
a = stack[sp-1]
sp = sp - 1
return a, b
end

function getneighbor(x, y, d)
if d == EAST then
x = x + 1
elseif d == NORTH then
y = y + 1
elseif d == WEST then
x = x -1
else
y = y - 1
end
return x, y
end

function notvisited(x, y)
if x < 1 or x > N then
return false
end
if y < 1 or y > N then
return false
end
v = math.floor(maze[x][y] / VISITED)
if v >= 1 then
return false
else
return true
end
end

function setvisited(x, y)
maze[x][y] = maze[x][y] + VISITED
end

function getunvisitedneighbor(x, y)
nu = 0
uds = {}
for i=EAST, SOUTH do
nx, ny = getneighbor(x, y, i)
if notvisited(nx, ny)then
nu = nu + 1
uds[nu] = i
end
end
if nu == 0 then
return -1, -1
end
td = math.random(1, nu)
nx, ny = getneighbor(x, y, uds[td])
return nx, ny
end

function getdirection(x, y, nx, ny)
if nx > x then
d = EAST
elseif ny > y then
d = NORTH
elseif nx < x then
d = WEST
else
d = SOUTH
end
return d
end

function erasewalls(x, y, nx, ny)
d = getdirection(x, y, nx, ny)
if d == EAST then
maze[x][y] = maze[x][y] - EWALL
maze[nx][ny] = maze[nx][ny] - WWALL
elseif d == NORTH then
maze[x][y] = maze[x][y] - NWALL
maze[nx][ny] = maze[nx][ny] - SWALL
elseif d == WEST then
maze[x][y] = maze[x][y] - WWALL
maze[nx][ny] = maze[nx][ny] - EWALL
else
maze[x][y] = maze[x][y] - SWALL
maze[nx][ny] = maze[nx][ny] - NWALL
end
end

``````
• Posts: 19

Funny ... I was experimenting with the exact same thing. What I did was make all walls inside physicsbodies as well and that works for me!

• Posts: 18

Thanks so much for the code Dave, my maze works perfectly now and now I've learned a thing or two about using physics in Codea. Big thanks to everyone else for the ideas and the help!

Sign In or Register to comment.