Skip to content

Instantly share code, notes, and snippets.

/Spin and Shoot Secret

Created August 24, 2016 02:40
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 anonymous/0de1ca51eaf934aecd018247a214a0ab to your computer and use it in GitHub Desktop.
Save anonymous/0de1ca51eaf934aecd018247a214a0ab to your computer and use it in GitHub Desktop.
--# Main
function setModes()
displayMode(FULLSCREEN_NO_BUTTONS)
supportedOrientations(LANDSCAPE_RIGHT)
ellipseMode(CENTER)
spriteMode(CENTER)
rectMode(CENTER)
textAlign(CENTER)
font("Futura-CondensedMedium")
CENTRE = vec2(WIDTH/2, HEIGHT/2)
end
function parameters()
psize = 25
shotsize = 10
jumplen = 30
turnaccel = 0.05
screensave = false
alpha = 150
c = {color(255,0,0,alpha), color(0,0,255,alpha), color(0,255,0,alpha), color(255,255,0,alpha)}
mapnames = {"CLASSIC", "SLAUGHTERHOUSE", "SMALL MAZE", "LARGE MAZE", "4 CIRCLES", "CROSSHAIRS", "SLIDERS", "SQUEEZE", "SPINNER"}
mapnames[0] = "RANDOM MAP"
end
function settings()
players = 2
bots = 1
startlives = 3
mapnumber = 0
gravity = false
if screensave then
players = 4
bots = 4
end
end
function setup()
setModes()
parameters()
settings()
screen = Menu()
physics.gravity(0,0)
physics.continuous = true
end
function draw()
background(0)
screen:draw()
noStroke()
fill(255, 255 - 255 * math.max(0, (ElapsedTime - lastchange)))
rect(WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)
end
function touched(t)
screen:touched(t)
end
function collide(c)
if screen.collide then
screen:collide(c)
end
end
--# Menu
Menu = class()
function Menu:init()
lastchange = ElapsedTime
score = {0,0,0,0}
--kills = {0,0,0,0}
self.buttons = {}
table.insert(self.buttons, Button(WIDTH/4, HEIGHT/2, 100, "QUIT", function() close() end))
table.insert(self.buttons, Button(WIDTH/2, HEIGHT/2, 100, "PLAY", function() screen = Game() end))
table.insert(self.buttons, Button(WIDTH * .75, HEIGHT/2, 100, "SETTINGS", function() screen = Settings() end))
backgroundMesh = mesh()
backgroundMesh.vertices = {vec2(0,0), vec2(WIDTH,0), vec2(WIDTH,HEIGHT), vec2(WIDTH,HEIGHT), vec2(0,HEIGHT), vec2(0,0)}
backgroundMesh.colors = {c[1], c[2], c[3], c[3], c[4], c[1]}
end
function Menu:draw()
backgroundMesh:draw()
fontSize(100)
fill(255)
text("SPIN AND SHOOT 3", WIDTH/2, HEIGHT * .75)
for k,v in pairs(self.buttons) do
v:draw()
end
if screensave and ElapsedTime - lastchange > 1 then
screen = Game()
end
end
function Menu:touched(t)
for k,v in pairs(self.buttons) do
v:touched(t)
end
end
--# Settings
Settings = class()
function Settings:init()
lastchange = ElapsedTime
screensave = false
self.buttons = {}
table.insert(self.buttons, Button(WIDTH/2, HEIGHT/2, 100, "MENU", function() screen = Menu() end))
self.buttons.players = Button(WIDTH/4, HEIGHT/2, 100, "", function() togglePlayers() end)
self.buttons.startlives = Button(WIDTH * .75, HEIGHT/2, 100, "", function() toggleStartlives() end)
self.buttons.bots = Button(WIDTH/4, HEIGHT/5, 100, "", function() toggleBots() end)
self.buttons.maps = Button(WIDTH/2, HEIGHT/5, 100, "", function() toggleMaps() end)
self.buttons.gravity = Button(WIDTH * .75, HEIGHT/5, 100, "", function() toggleGravity() end)
end
function Settings:draw()
backgroundMesh:draw()
self.buttons.players.m = players .. " PLAYERS"
self.buttons.startlives.m = startlives .. ((startlives == 1 and " LIFE") or " LIVES")
self.buttons.bots.m = ((bots == 0 and "NO") or bots) .. " BOT" .. ((bots ~= 1 and "S") or "")
self.buttons.maps.m = mapnames[mapnumber]
self.buttons.gravity.m = ((gravity and "") or "NO ") .. "GRAVITY"
fontSize(100)
fill(255)
text("SETTINGS", WIDTH/2, HEIGHT * .75)
for k,v in pairs(self.buttons) do
v:draw()
end
end
function Settings:touched(t)
for k,v in pairs(self.buttons) do
v:touched(t)
end
end
function togglePlayers()
players = (players - 1) % 3 + 2
bots = math.min(bots, players)
end
function toggleStartlives()
startlives = (startlives + 2) % 6
end
function toggleBots()
bots = (bots + 1) % (players + 1)
end
function toggleMaps()
mapnumber = (mapnumber + 1) % (#mapnames + 1)
end
function toggleGravity()
gravity = not gravity
end
--# Game
Game = class()
function Game:init()
lastchange = ElapsedTime
p = {}
for i = 1,players do
p[i] = Spinner(i, WIDTH/2 * w(i) + WIDTH/4, HEIGHT/2 * h(i) + HEIGHT * .75 - math.ceil(players/2) * HEIGHT/4, c[i].r, c[i].g, c[i].b, i > players - bots)
end
self.shots = {}
self.shotBreaks = {}
self.map = Map()
winner = nil
kills = {0,0,0,0}
end
function Game:draw()
local dead = 0
for k,v in pairs(p) do
v:drawBack()
end
noStroke()
if gravity then
fill(10)
ellipse(CENTRE.x, CENTRE.y, 100)
end
for k,v in pairs(self.shotBreaks) do
v:draw()
if ElapsedTime > v.starttime + 1 then
table.remove(self.shotBreaks, k)
end
end
for k,v in pairs(p) do
v:draw()
if v.dead then
dead = dead + 1
else
winner = k
end
if gravity and not v.dead then
v.b:applyForce((CENTRE - v.b.position)/5)
end
end
if dead == players then
winner = 0
endGame()
elseif dead == players - 1 then
endGame()
end
stroke(255)
strokeWidth(5)
for k,v in pairs(self.shots) do
v:draw()
if gravity then
v.b:applyForce((CENTRE - v.b.position)/10)
end
end
self.map:draw()
end
function Game:touched(t)
for k,v in pairs(p) do
v:touched(t)
end
end
function Game:collide(c)
for k,v in pairs(p) do
if isHit(c, v.b) then
for j,w in pairs(self.shots) do
if isHit(c, w.b) then
v:getHit()
w.b:destroy()
if w.player ~= v.player then
kills[w.player] = kills[w.player] + 1
end
table.remove(self.shots, j)
return
end
end
--v.b.angularVelocity = 0
end
end
for i,v in pairs(self.shots) do
for j,w in pairs(self.shots) do
if i ~= j and hit(c, v.b, w.b) then
table.insert(self.shotBreaks, ShotBreak(c.position, v.c.r, v.c.g, v.c.b, w.c.r, w.c.g, w.c.b))
v.b:destroy()
w.b:destroy()
table.remove(self.shots, math.max(i,j))
table.remove(self.shots, math.min(i,j))
end
end
end
end
function endGame()
if winner ~= 0 then
p[winner]:die()
score[winner] = score[winner] + 1
end
for k,v in pairs(screen.shots) do
v.b:destroy()
table.remove(screen.shots, k)
end
screen.map:clear()
screen = End()
end
--# Spinner
Spinner = class()
function Spinner:init(player, centrex, centrey, r, g, b, bot)
self.player = player
-- self.b = physics.body(POLYGON, vec2(-len/2,-wid/2), vec2(len/2,-wid/2), vec2(len/2,wid/2), vec2(-len/2,wid/2))
self.b = physics.body(CIRCLE, psize)
self.b.position = vec2(centrex, centrey)
self.b.angle = angle(CENTRE - self.b.position) + 180
self.b.restitution = 1
self.b.linearDamping = 5
self.b.friction = 0
self.b.info = "PLAYER"
--self.b.fixedRotation = true
self.centrex = centrex
self.centrey = centrey
self.rwidth = WIDTH/2
self.rheight = HEIGHT/math.ceil(players/2)
self.c1 = color(r,g,b,255)
self.c2 = color(r,g,b,100)
self.c3 = color(r,g,b,50)
self.c4 = color(r,g,b,40)
self.touch = false
self.invincible = true
self.lastinvincible = ElapsedTime
self.invincibledelay = 0.5
self.health = startlives
self.dead = false
self.bot = bot
self.turn = turnaccel
self.angularVelocity = 0
end
function Spinner:drawBack()
if not self.dead then
strokeWidth(5)
stroke(self.c2)
if self.canshoot then
fill(self.c3)
elseif self.canshoot and self.bot then
--fill(self.c3)
fill(self.c4)
else
--fill(self.c4)
fill(0)
end
rect(self.centrex, self.centrey, self.rwidth, self.rheight)
if self.health <= 0 then
self:die()
end
if startlives > 1 then
fill(self.c2)
fontSize(200)
text(self.health, self.centrex, self.centrey)
end
end
end
function Spinner:draw()
if not self.dead then
pushMatrix()
translate(self.b.position:unpack())
rotate(self.b.angle)
if self.invincible and ElapsedTime * 10 - math.floor(ElapsedTime * 10) < 0.5 then
fill(self.c2)
else
fill(self.c1)
end
stroke(255)
strokeWidth(5)
ellipse(0, 0, 2 * psize)
line(0, 0, psize, 0)
popMatrix()
--self.b.linearVelocity = self.b.linearVelocity * 0.9
if not self.touch then
self.b:applyAngularImpulse(self.turn)
end
self.canshoot = math.abs(self.b.angularVelocity) > 300
self.invincible = ElapsedTime < self.lastinvincible + self.invincibledelay
if self.b.linearVelocity:len() > 1000 then
self.b.linearVelocity = 1000 * self.b.linearVelocity:normalize()
end
if math.abs(self.b.angularVelocity) > 2000 then
self.b.angularVelocity = 2000 * self.b.angularVelocity/math.abs(self.b.angularVelocity)
end
if self.bot then
self:botAI()
end
end
end
function Spinner:touched(t)
if t.x > self.centrex - self.rwidth/2 and t.x < self.centrex + self.rwidth/2 and t.y > self.centrey - self.rheight/2 and t.y < self.centrey + self.rheight/2 and not self.dead and not self.bot then
if t.state == BEGAN then
self.touch = true
end
if t.state == ENDED then
self.touch = false
self:jump()
end
end
end
function Spinner:jump()
self.b:applyLinearImpulse(jumplen * dirvec(self.b.angle))
self.turn = -self.turn
self:shoot()
self.b.angularVelocity = 0
end
function Spinner:shoot()
if self.canshoot then
table.insert(screen.shots, Shot(self.player, self.b.position + (psize + 2 * shotsize) * dirvec(self.b.angle), 50 * math.sqrt(math.abs(self.b.angularVelocity)) * dirvec(self.b.angle), self.c1))
self.canshoot = false
end
end
function Spinner:getHit()
if self.invincible then
self.invincible = false
else
self.health = self.health - 1
self:setInvincible()
end
end
function Spinner:setInvincible()
self.invincible = true
self.lastinvincible = ElapsedTime
end
function Spinner:die()
if self.b then
self.b:destroy()
self.b = nil
end
self.dead = true
end
function Spinner:botAI()
self.touch = self.canshoot
local ray = physics.raycast(self.b.position + (psize) * dirvec(self.b.angle), self.b.position + 1000 * dirvec(self.b.angle))
if ray then
if math.abs(ray.normal:angleBetween(-dirvec(self.b.angle))) then
if ray.body.info == "PLAYER" and self.canshoot then
self:jump()
return
end
--line(self.b.position.x, self.b.position.y, ray.point.x, ray.point.y)
for i = -1,1 do
local newRay = physics.raycast(ray.point, ray.point + 1000 * (-dirvec(self.b.angle)):rotate(2 * (-dirvec(self.b.angle)):angleBetween(ray.normal) + i * 0.05))
if newRay then
if newRay.body.info == "PLAYER" and newRay.body.position:dist(self.b.position) > psize and self.canshoot then
self:jump()
return
end
--line(ray.point.x, ray.point.y, newRay.point.x, newRay.point.y)
for j = -1,1 do
local lastRay = physics.raycast(newRay.point, newRay.point + 1000 * (ray.point - newRay.point):rotate(2 * (ray.point - newRay.point):angleBetween(newRay.normal) + j * 0.05))
if lastRay then
if lastRay.body.info == "PLAYER" and lastRay.body.position:dist(self.b.position) > psize and self.canshoot then
self:jump()
return
end
end
end
end
end
for k,v in pairs(screen.shots) do
--[[
local shotray = physics.raycast(v.b.position + (shotsize + 1) * v.b.linearVelocity:normalize(), v.b.position + 300 * v.b.linearVelocity:normalize())
if shotray then
if shotray.body.info == "PLAYER" and shotray.body.position:dist(self.b.position) < psize then
self:jump()
return
end
end
]]
for i = 1,4 do
if (v.b.position + i * v.b.linearVelocity * DeltaTime):dist(self.b.position) <= psize + shotsize then
self:jump()
return
end
end
end
--[[
if screen.map.changetime ~= 0 then
if math.random(500) == 1 then
self:jump()
return
end
end
]]
end
end
end
--# Shot
Shot = class()
function Shot:init(player, pos, v, c)
self.player = player
self.b = physics.body(CIRCLE, shotsize)
self.b.restitution = 1
self.b.mass = 10
self.b.position = pos
self.b.linearVelocity = v
self.c = c
end
function Shot:draw()
fill(self.c)
drawBody(self.b)
end
--# ShotBreak
ShotBreak = class()
function ShotBreak:init(pos, r1, g1, b1, r2, g2, b2)
self.pos = pos
self.starttime = ElapsedTime
self.c1 = color(r1, g1, b1, 255)
self.c2 = color(r2, g2, b2, 255)
self.lights = {}
for i = 1,20 do
table.insert(self.lights, Light(pos, self.c1))
table.insert(self.lights, Light(pos, self.c2))
end
end
function ShotBreak:draw()
local t = ElapsedTime - self.starttime
self.c1.a = 255 - 255 * math.min(1, t)
self.c2.a = 255 - 255 * math.min(1, t)
--print(self.c1, self.c2)
for k,v in pairs(self.lights) do
v:draw()
end
end
--# Light
Light = class()
function Light:init(pos, c)
self.pos = pos
self.c = c
self.dir = math.random(360)
self.speed = 3 * math.random()
self.size = 20 * math.random()
self.v = self.speed * dirvec(self.dir)
end
function Light:draw()
self.pos = self.pos + self.v
self.v = self.v * 0.9
fill(self.c)
ellipse(self.pos.x, self.pos.y, self.size)
end
--# Map
Map = class()
function Map:init()
self.bodies = {}
--[[
self:createEdge(0, 0, WIDTH, 0)
self:createEdge(0, 0, 0, HEIGHT)
self:createEdge(WIDTH, 0, WIDTH, HEIGHT)
self:createEdge(0, HEIGHT, WIDTH, HEIGHT)
--]]
self.maps = {self.CLASSIC, self.OPEN, self.SMAZE, self.LMAZE, self.BUMPERS, self.CROSSHAIRS, self.SLIDERS, self.SQUEEZE, self.SPINNER}
self.currentMap = (mapnumber == 0 and math.random(1, #self.maps)) or mapnumber
self.changetime = 0
self:resetMap()
self.lastchange = ElapsedTime
--[[
print(i)
local f = maps[i]
print(f)
self:f()
--]]
--[[
slider1 = physicsBox(50, HEIGHT/3)
slider1.type = STATIC
slider1.position = vec2(WIDTH/2, HEIGHT/6)
tween(1, slider1.linearVelocity, {y = HEIGHT/1.2})--, {loop = tween.loop.pingpong})
table.insert(self.bodies, slider1)
--]]
end
function Map:resetMap()
for k,v in pairs(self.bodies) do
v:destroy()
end
self.bodies = {}
self:createEdge(0, 0, WIDTH, 0)
self:createEdge(0, 0, 0, HEIGHT)
self:createEdge(WIDTH, 0, WIDTH, HEIGHT)
self:createEdge(0, HEIGHT, WIDTH, HEIGHT)
self.maps[self.currentMap](self)
end
function Map:draw()
stroke(255)
strokeWidth(5)
fill(255)
if self.changetime == 0 then
for k,v in pairs(self.bodies) do
drawBody(v)
end
else
local t = ElapsedTime - self.lastchange
local _,d = math.modf(t/self.changetime)
if d < 1 - 1/self.changetime or ElapsedTime * 10 < 0.5 + math.floor(ElapsedTime * 10) then
for k,v in pairs(self.bodies) do
drawBody(v)
end
end
if d > 1 - DeltaTime then
self:resetMap()
end
end
end
function Map:CLASSIC()
local body = physics.body(CIRCLE, 100)
body.position = CENTRE
body.restitution = 1
body.type = STATIC
table.insert(self.bodies, body)
end
function Map:OPEN()
self:createEdge(HEIGHT/3, 0, 0, HEIGHT/3)
self:createEdge(0, HEIGHT/1.5, HEIGHT/3, HEIGHT)
self:createEdge(WIDTH - HEIGHT/3, HEIGHT, WIDTH, HEIGHT/1.5)
self:createEdge(WIDTH, HEIGHT/3, WIDTH - HEIGHT/3, 0)
end
function Map:SMAZE()
numw,numh = 5,3
m = Maze(numw, numh)
z = m.maze
for i = 1,numw do
for j = 1,numh do
local x, y = (i - 1) * WIDTH/numw, HEIGHT - (j - 1) * HEIGHT/numh
if z[i][j][1] == 1 then self:createEdge(x, y, x + WIDTH/numw, y) end
if z[i][j][2] == 1 then self:createEdge(x, y, x, y - HEIGHT/numh) end
end
end
self.changetime = 5
end
function Map:LMAZE()
numw,numh = 7,5
m = Maze(numw, numh)
z = m.maze
for i = 1,numw do
for j = 1,numh do
local x, y = (i - 1) * WIDTH/numw, HEIGHT - (j - 1) * HEIGHT/numh
if z[i][j][1] == 1 then self:createEdge(x, y, x + WIDTH/numw, y) end
if z[i][j][2] == 1 then self:createEdge(x, y, x, y - HEIGHT/numh) end
end
end
self.changetime = 5
end
function Map:BUMPERS()
for i=1,4 do
local bumper = physics.body(CIRCLE, 50)
bumper.position = CENTRE + vec2(math.random(-100,100), math.random(-100,100))
bumper.restitution = 1
bumper.mass = 1000
bumper.linearVelocity = math.random(200) * dirvec(math.random(360))
table.insert(self.bodies, bumper)
end
end
function Map:CROSSHAIRS()
local body = physicsBox(50, HEIGHT/3)
body.type = STATIC
body.position = vec2(WIDTH/2, HEIGHT/6)
table.insert(self.bodies, body)
local body = physicsBox(50, HEIGHT/3)
body.type = STATIC
body.position = vec2(WIDTH/2, HEIGHT/1.2)
table.insert(self.bodies, body)
local body = physicsBox(WIDTH/3, 50)
body.type = STATIC
body.position = vec2(WIDTH/6, HEIGHT/2)
table.insert(self.bodies, body)
local body = physicsBox(WIDTH/3, 50)
body.type = STATIC
body.position = vec2(WIDTH/1.2, HEIGHT/2)
table.insert(self.bodies, body)
end
function Map:SLIDERS()
slider1 = physicsBox(50, HEIGHT/3)
slider1.type = KINEMATIC
slider1.position = vec2(WIDTH/2, HEIGHT/6)
tween(5, slider1.position, {y = HEIGHT/1.2}, {loop = tween.loop.pingpong})
table.insert(self.bodies, slider1)
slider2 = physicsBox(50, HEIGHT/3)
slider2.type = KINEMATIC
slider2.position = vec2(WIDTH/2, HEIGHT/1.2)
tween(5, slider2.position, {y = HEIGHT/6}, {loop = tween.loop.pingpong})
table.insert(self.bodies, slider2)
slider3 = physicsBox(WIDTH/3, 50)
slider3.type = KINEMATIC
slider3.position = vec2(WIDTH/6, HEIGHT/2)
tween(5, slider3.position, {x = WIDTH/1.2}, {loop = tween.loop.pingpong})
table.insert(self.bodies, slider3)
slider4 = physicsBox(WIDTH/3, 50)
slider4.type = KINEMATIC
slider4.position = vec2(WIDTH/1.2, HEIGHT/2)
tween(5, slider4.position, {x = WIDTH/6}, {loop = tween.loop.pingpong})
table.insert(self.bodies, slider4)
--[[
local vbar = physics.body(POLYGON, vec2(-25,-100), vec2(25,-100), vec2(25,100), vec2(-25,100))
vbar.categories = {1}
vbar.mask = {0}
vbar.restitution = 1
vbar.mass = 100000
vbar.fixedRotation = true
vbar.position = CENTRE
vbar.linearVelocity = vec2(0,100)
local hbar = physics.body(POLYGON, vec2(-100,-25), vec2(-100,25), vec2(100,25), vec2(100,-25))
hbar.categories = {2}
hbar.mask = {0}
hbar.restitution = 1
hbar.mass = 100000
hbar.fixedRotation = true
hbar.position = CENTRE
hbar.linearVelocity = vec2(100,0)
table.insert(self.bodies, vbar)
table.insert(self.bodies, hbar)
local vbar = physics.body(POLYGON, vec2(-25,-100), vec2(25,-100), vec2(25,100), vec2(-25,100))
vbar.categories = {3}
vbar.mask = {0}
vbar.restitution = 1
vbar.mass = 100000
vbar.fixedRotation = true
vbar.position = CENTRE
vbar.linearVelocity = vec2(0,-100)
local hbar = physics.body(POLYGON, vec2(-100,-25), vec2(-100,25), vec2(100,25), vec2(100,-25))
hbar.categories = {4}
hbar.mask = {0}
hbar.restitution = 1
hbar.mass = 100000
hbar.fixedRotation = true
hbar.position = CENTRE
hbar.linearVelocity = vec2(-100,0)
table.insert(self.bodies, vbar)
table.insert(self.bodies, hbar)
]]
end
function Map:SQUEEZE()
local speed = 50
local up = physics.body(EDGE, vec2(0,0), vec2(WIDTH,0))
up.type = KINEMATIC
up.linearVelocity = vec2(0,speed)
local right = physics.body(EDGE, vec2(0,0), vec2(0,HEIGHT))
right.type = KINEMATIC
right.linearVelocity = vec2(speed,0)
local left = physics.body(EDGE, vec2(WIDTH,0), vec2(WIDTH,HEIGHT))
left.type = KINEMATIC
left.linearVelocity = vec2(-speed,0)
local down = physics.body(EDGE, vec2(0,HEIGHT), vec2(WIDTH,HEIGHT))
down.type = KINEMATIC
down.linearVelocity = vec2(0,-speed)
table.insert(self.bodies, up)
table.insert(self.bodies, right)
table.insert(self.bodies, left)
table.insert(self.bodies, down)
local body = physics.body(CIRCLE, 50)
body.position = CENTRE
body.restitution = 1
body.type = STATIC
table.insert(self.bodies, body)
self.changetime = 5
end
function Map:SPINNER()
box1 = physicsBox(50, HEIGHT - 100)
box1.type = KINEMATIC
box1.position = CENTRE
box1.restitution = 1
box1.angularVelocity = 20
table.insert(self.bodies, box1)
box2 = physicsBox(HEIGHT - 100, 50)
box2.type = KINEMATIC
box2.position = CENTRE
box2.restitution = 1
box2.angularVelocity = 20
table.insert(self.bodies, box2)
end
function Map:clear()
for k,v in pairs(self.bodies) do
v:destroy()
end
end
function Map:createEdge(ax, ay, bx, by)
local body = physicsEdge(ax, ay, bx, by)
body.restitution = 1
table.insert(self.bodies, body)
end
--# Maze
Maze = class()
-- Code by Ignatz
function Maze:init(n,m)
local m=m or n --set m=n if not provided
t={} for i=1,n do t[i]={} end --create 2D maze
local stack={} --holds visited cells
local visitedCells=0
local totalCells=n*m
--set up little array to help with finding neighbours
local nb={{x=0,y=-1},{x=-1,y=0},{x=1,y=0},{x=0,y=1}}
--generate random starting cell
local cell={x=math.random(1,n),y=math.random(1,m)}
self.firstX,self.firstY=cell.x,cell.y
t[cell.x][cell.y]={1,1,1,1} -- top, left, right, bottom (1=wall)
visitedCells = visitedCells + 1
--loop through
while visitedCells<totalCells do
local prevVisitedCells=visitedCells
local r={1,2,3,4}
while #r~=0 do
--pick a random neighbour from the four directions
local rr=math.random(1,#r)
local s=r[rr]
table.remove(r,rr)
--work out x and y positions of neighbour
local x,y=cell.x+nb[s].x,cell.y+nb[s].y
--must be a valid cell that hasnt been visited
if x>0 and x<=n and y>0 and y<=m and t[x][y]==nil then
t[x][y]={1,1,1,1} -- top, right,bottom,left (1=wall)
t[cell.x][cell.y][s]=0 --break down wall in current cell
t[x][y][5-s]=0 --and neighbour
visitedCells = visitedCells + 1
table.insert(stack,{x=cell.x,y=cell.y}) --add previous cell to stack in case we need it
cell.x,cell.y=x,y --make neighbour the current cell
break
end
end
if prevVisitedCells==visitedCells then
--no unvisited neighbours found, go back to previous cell from stack
cell.x,cell.y=stack[#stack].x,stack[#stack].y
table.remove(stack,#stack)
end
end
self.maze=t
end
--# End
End = class()
function End:init()
lastchange = ElapsedTime
self.buttons = {}
table.insert(self.buttons, Button(WIDTH/4, HEIGHT/2, 100, "QUIT", function() close() end))
table.insert(self.buttons, Button(WIDTH * .75, HEIGHT/2, 100, "MENU", function() screen = Menu() end))
table.insert(self.buttons, Button(WIDTH/2, HEIGHT/2, 100, "PLAY", function() screen = Game() end))
end
function End:draw()
fill(c[winner].r, c[winner].g, c[winner].b, 50)
rect(CENTRE.x, CENTRE.y, WIDTH, HEIGHT)
fontSize(100)
if winner == 0 then
fill(255)
text("DRAW", WIDTH/2, HEIGHT * .75)
else
fill(c[winner])
text("WINNER", WIDTH/2, HEIGHT * .8)
text("WINNER", WIDTH/2, HEIGHT * .8)
fontSize(50)
text("(" .. kills[winner] .. " KILL" .. ((kills[winner] ~= 1 and "S)") or ")"), WIDTH/2, HEIGHT * .7)
text("(" .. kills[winner] .. " KILL" .. ((kills[winner] ~= 1 and "S)") or ")"), WIDTH/2, HEIGHT * .7)
end
fontSize(50)
for i=1,players do
fill(c[i])
text(score[i], WIDTH/2 - (players - 1) * 50 + (i - 1) * 100, HEIGHT/4)
text(score[i], WIDTH/2 - (players - 1) * 50 + (i - 1) * 100, HEIGHT/4)
--text(kills[i], WIDTH/2 - (players - 1) * 50 + (i - 1) * 100, HEIGHT/6)
--text(kills[i], WIDTH/2 - (players - 1) * 50 + (i - 1) * 100, HEIGHT/6)
end
for k,v in pairs(self.buttons) do
v:draw()
end
if screensave and ElapsedTime - lastchange > 1 then
screen = Game()
end
end
function End:touched(t)
if ElapsedTime > lastchange + 0.5 then
for k,v in pairs(self.buttons) do
v:touched(t)
end
end
end
--# Button
Button = class()
function Button:init(x,y,size,m,action)
self.pos = vec2(x,y)
self.size = size
self.m = m
self.action = action
self.hit = 0
end
function Button:draw()
pushMatrix()
translate(self.pos:unpack())
stroke(255)
strokeWidth(5)
if self.hit == 1 and self.ts ~= ENDED then fill(150) else fill(255) end
ellipse(0,0,2*self.size)
fill(0)
fontSize(self.size/4)
text(self.m,0,0)
popMatrix()
end
function Button:touched(t)
self.ts = t.state
if (vec2(t.x,t.y) - self.pos):len() <= self.size then
self.hit = 1
if self.ts == ENDED then
self.action()
end
else
self.hit = 0
end
end
--# Helper
function drawBody(body)
pushMatrix()
translate(body.x, body.y)
rotate(body.angle)
if body.shapeType == POLYGON then
local points = body.points
for j = 1, #points do
a = points[j]
b = points[(j % #points) + 1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CHAIN or body.shapeType == EDGE then
local points = body.points
for j = 1, #points - 1 do
a = points[j]
b = points[j+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CIRCLE then
ellipse(0, 0, body.radius*2)
end
popMatrix()
end
function physicsEdge(ax, ay, bx, by)
local body = physics.body(EDGE, vec2(ax,ay), vec2(bx,by))
return body
end
function physicsBox(w, h)
local body = physics.body(POLYGON, vec2(-w/2, h/2), vec2(-w/2, -h/2), vec2(w/2, -h/2), vec2(w/2, h/2))
return body
end
function w(i)
return (1-(i%2))
end
function h(i)
return math.floor((i-1)/2)
end
function dirvec(a)
return vec2(math.cos(math.rad(a)),math.sin(math.rad(a)))
end
function angle(vec)
return math.deg(vec2(1,0):angleBetween(vec))
end
function hit(c, a, b)
if (c.bodyA == a and c.bodyB == b) or (c.bodyA == b and c.bodyB == a) then
return true
else
return false
end
end
function isHit(c, a)
if c.bodyA == a or c.bodyB == a then
return true
else
return false
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment