|
Post by Admin on Aug 28, 2018 14:07:59 GMT
here is the code (directly)
-- Snek -- Meant to be played in portrait mode -- Just swipe to turn snake
-- Touch Handling -- Not all of it's needed, but it's a useful template I made and use local T = {}
for i = 1, 5 do T[i] = {0, 0, 0, 0, 0, 0, 0, false} end
function T.isDown(o, i) i = i or 1 return o[i][8] end
function T.pos(o, i) i = i or 1 return o[i][1], o[i][2] end
function T.ipos(o, i) i = i or 1 return o[i][3], o[i][4] end
function T.dpos(o, i) i = i or 1 return o[i][5], o[i][6] end
function T.vect(o, i) i = i or 1 return o[i][1] - o[i][3], o[i][2] - o[i][4] end
function T.vectdistp(o, i) -- dist^2 local vx, vy = o:vect(i) return vx*vx + vy*vy end
function T.dur(o, i) return sys.gettime() - o[i][7] end
draw.touchbegan = function(t) for i = 1, #t do local id, x, y = t[i].id, t[i].x, t[i].y if id < 6 then local T = T[id] T[1], T[2] = x, y T[3], T[4] = x, y T[5], T[6] = 0, 0 T[7], T[8] = sys.gettime(), true end end end
draw.touchmoved = function(t) for i = 1, #t do local id, x, y = t[i].id, t[i].x, t[i].y if id < 6 then local T = T[id] T[5], T[6] = x - T[1], y - T[2] T[1], T[2] = x, y end end end
draw.touchended = function(t) for i = 1, #t do local id, x, y = t[i].id, t[i].x, t[i].y if id < 6 then local T = T[id] T[1], T[2] = x, y T[8] = false end end end
-- Create things local function init() local W, H = draw.getsize()
-- Grid that game is played on Grid = {} -- x, y: location on screen Grid.x, Grid.y = 0, (H - W) / 2 -- w, h: cells in grid Grid.w = 10 Grid.h = Grid.w -- s: side length of 1 grid cell Grid.s = W / Grid.w -- Function to draw grid Grid.disp = function(o) local x, y = o.x, o.y local x1, y1 = o.x + o.w * o.s, o.y + o.h * o.s draw.fillrect(x, y, x1, y1, colors.midnight_blue) draw.rect(x, y, x1, y1, colors.white) end
-- Coin that snek eats Coin = {} -- Coin's location on Grid Coin.x, Coin.y = 0, 0 Coin.r = Grid.s / 2
Coin.isOn = function(o, x, y) return o.x == x and o.y == y end
-- Total Coins Coin.max = math.floor(Grid.w * Grid.h * 0.8) Coin.bag = 0
Coin.reset = function(o) o.bag = 0 o.spawned = false end
-- Coin's availability Coin.spawned = false -- Place Coin on Grid Coin.spawn = function(o) local t = {} for x = 1, Grid.w do for y = 1, Grid.h do if not Snek:inBody(x, y) then t[#t + 1] = {x, y} end end end
local r = math.random(1, #t) o.x, o.y = t[r][1], t[r][2]
o.spawned = true end
-- Coin been ate Coin.ate = function(o) o.bag = o.bag + 1 o.spawned = false end
Coin.time = 0
-- Coin's Loop Coin.updt = function(o, dt) o.time = (o.time + 2*dt) % (2 * math.pi) if o.bag >= o.max then Game:win() end if not o.spawned then o:spawn() end end
-- Draw meter Coin.meter = function(o) local g = Grid draw.fillrect(0, g.y - 20, W * o.bag/o.max, g.y, colors.red) draw.rect(0, g.y - 20, W, g.y, colors.white) end
-- Draw Coin Coin.disp = function(o) Coin:meter() if o.spawned then local g = Grid draw.fillcircle( g.x + (o.x - 1) * g.s + g.s * 0.5, g.y + (o.y - 1) * g.s + g.s * 0.5, o.r, colors.gold ) draw.fillcircle( g.x + (o.x - 1) * g.s + g.s * 0.45, g.y + (o.y - 1) * g.s + g.s * 0.45, o.r * 0.8, {1, 1, 0, math.cos(o.time)} ) end end
--The snek you play as Snek = {}
Snek.reset = function(o) -- Snek head location on grid local v = math.floor(Grid.w * 0.4) o.x, o.y = math.random(1 + v, Grid.w - v), math.random(1 + v, Grid.w - v)
-- Snek current direction Snek.dir = 1 -- Next direction Snek.mdir = 1 Snek.maxspeed = 6.9 Snek.speed = 5 -- Max speed at about 1/4 of the coins Snek.speedadd = (Snek.maxspeed - Snek.speed) / (Coin.max / 4) Snek.timer = 0
-- Snek parts o.body = { {o.x, o.y, 1, false}, {o.x, o.y + 1, 1, false}, {o.x, o.y + 2, 1, false}, } end
Snek:reset()
-- Add part Snek.insert = function(o, x, y, dir, butt) table.insert(o.body, 1, {x, y, dir, butt or false}) end
-- Remove part Snek.remove = function(o) table.remove(o.body) end
-- Get your swipe input Snek.swipe = function(o) if T:isDown(1) then local vx, vy = T:vect(1) local a = math.atan(vy / vx) + (vx < 0 and math.pi or 0) local pi = math.pi if -pi/4 < a and a < pi/4 then o.mdir = o.dir ~= 4 and 2 or o.dir elseif pi/4 < a and a < 3 * pi / 4 then o.mdir = o.dir ~= 1 and 3 or o.dir elseif 3*pi/4 < a and a < 5*pi/4 then o.mdir = o.dir ~= 2 and 4 or o.dir else o.mdir = not (a ~= a) and o.dir ~= 3 and 1 or o.dir end end end
-- Move snek Snek.move = function(o) if o.mdir % 2 == 0 then o.x = o.x + (o.mdir == 2 and 1 or -1) else o.y = o.y + (o.mdir == 1 and -1 or 1) end o.dir = o.mdir end
-- snek hungry Snek.eat = function(o) if Coin:isOn(o.x, o.y) then Coin:ate() o:insert(o.x, o.y, o.dir, true) o.speed = o.speed <= o.maxspeed and o.speed + o.speedadd or o.speed end end
-- Does it touch snek? Snek.inBody = function(o, x, y) for i = 2, #o.body do local v = o.body[i] if v[1] == x and v[2] == y then return true end end end
-- Ouch Snek.hit = function(o) if o.x < 1 or o.x > Grid.w or o.y < 1 or o.y > Grid.h then Game:lose() end if o:inBody(o.x, o.y) then Game:lose() end end
--Update snek Snek.updt = function(o, dt) o:swipe()
o.timer = o.timer + dt * o.speed if o.timer >= 1 then o:eat()
o:move() o:insert(o.x, o.y, o.dir) o:remove() o.timer = 0 o:hit() end end
Snek.drawpart = function(o, x, y, dx, dy, head, butt) local s = Grid.s if butt then dx, dy = 0, 0 end local a, b = Grid.x + (x - 1) * s - dx, Grid.y + (y - 1) * s - dy local c, d = a + s, b + s local r = Grid.s * 0.5 draw.fillrect(a, b, c, d, colors.medium_sea_green) --draw.fillcircle(a + r, b + r, r, colors.medium_sea_green) if head then s = s / 4 -- Eyes draw.fillrect( o.dir == 2 and c - s or a, o.dir == 3 and d - s or b, o.dir == 2 and c or a + s, o.dir == 3 and d or b + s, colors.black ) draw.fillrect( o.dir == 2 and c - s or o.dir == 4 and a or c, o.dir == 1 and b or d - s, o.dir == 2 and c or o.dir == 4 and a + s or c - s, o.dir == 1 and b + s or d, colors.black ) end end
Snek.calcdxdy = function(o, dir) local dx, dy = 0, 0 if dir % 2 == 0 then dx = (1 - o.timer) * Grid.s * (dir == 2 and 1 or -1) else dy = (1 - o.timer) * Grid.s * (dir == 1 and -1 or 1) end return dx, dy end
Snek.disp = function(o) for i = 1, #o.body do local b = o.body[i] local dx, dy = o:calcdxdy(b[3]) o:drawpart(b[1], b[2], dx, dy, false, b[4]) end
local dx, dy = o:calcdxdy(o.dir) o:drawpart(o.x, o.y, dx, dy, true) end
local function fontfits(txt, W, H, hor, vert) local max = 0 for i = 1, 1000 do draw.setfont("Menlo", i) local w, h = draw.stringsize(txt) if hor and w > W then max = i - 1 break end if vert and h > H then max = i - 1 break end end draw.setfont("Menlo", 12) return max end
Game = {} -- 0 start, 1 run, 2 pause, 3 win, 4 lose Game.state = 0 Game.timer = 3
Game.lose = function(o) o.timer = 0 o.state = 4 end
Game.win = function(o) o.state = 3 o.timer = 0 o:resetfire() end
Game.pbttn = { x = W / 3, y = Grid.y + W, xx = W - W / 3, yy = H, lock = false, time = 0.3 } Game.pbttn.isIn = function(o, x, y) return o.x < x and x < o.xx and o.y < y and y < o.yy end Game.ubttn = function(o) if T:isDown(1) then local x, y = T:ipos(1) if o.pbttn:isIn(x, y) then o.state = 2 o.pbttn.lock = true end end end Game.dbttn = function(o) local p = o.pbttn local s = "PAUSE" draw.setfont("Menlo", fontfits(s, p.xx - p.x, 0, true, false)) local w, h = draw.stringsize(s) draw.string(s, W/2 - w/2, p.y + (p.yy-p.y)/2 - h/2, colors.white) draw.rect(p.x, p.y, p.xx, p.yy, colors.white) end
Game.fireworks = {}
Game.rckt = function(o, i) local t = o.fireworks local x, y, r = W / 2, H + 10, math.random() * 5 local a = math.random() * math.pi/2 + math.pi/4 local l = math.random() local color = { 0.5 + math.random() * 0.5, 0.5 + math.random() * 0.5, 0.5 + math.random() * 0.5, l } t[i] = {x, y, r, a, l, color} end
Game.resetfire = function(o) for i = 1, 3 do o:rckt(i) end end
Game.explopart = {} Game.explometa = {} setmetatable(Game.explopart, Game.explometa) Game.explometa.__mode = "v"
Game.makeexplo = function(o, x, y, r, l, color) local t = { x, y, r, math.random() * 2 * math.pi, l, color } return t end Game.rcktexplo = function(o, i) local r = o.fireworks[i] local t = o.explopart local v = {["dead"] = false} for i = 1, 20 do r[6][4] = 1 v[#v + 1] = o:makeexplo(r[1], r[2], r[3], 2 * r[5] * math.random(), r[6]) end t[#t + 1] = v
o:rckt(i) end
Game.updtexplo = function(o, dt) local t = o.explopart for i = 1, #t do local v = t[i] if v and not v.dead then for j = 1, #v do local e = v[j] local dx, dy = e[5] * 8 * math.cos(e[4]), e[5] * 8* math.sin(e[4])
e[1], e[2] = e[1] + dx, e[2] + dy
e[5] = e[5] > 0 and e[5] - dt or 0 if e[5] < 0.2 then e[6][4] = e[6][4] - dt end end else t[i] = nil end end end
Game.dispexplo = function(o) local t = o.explopart for i = 1, #t do local v = t[i] if v and not v.dead then for j = 1, #v do local e = v[j] draw.fillcircle(e[1], e[2], e[3], e[6]) end end end end
Game.updtfire = function(o, dt) local t = o.fireworks for i = 1, #t do local v = t[i] local dx, dy = v[5] * 5 * math.cos(v[4]), v[5] * 5 * math.sin(v[4])
v[1], v[2] = v[1] + dx, v[2] - dy
v[6][4] = v[6][4] - dt
if v[6][4] <= 0 then o:rcktexplo(i) end end
o:updtexplo(dt) end
Game.dispfire = function(o) local t = o.fireworks for i = 1, #t do local v = t[i] draw.fillcircle(v[1], v[2], v[3], v[6]) end o:dispexplo() end
Game:resetfire()
Game.updt = function(o, dt) if o.state == 0 then o.timer = o.timer - dt if o.timer <= 0 then o.state = 1 o.timer = 3 end elseif o.state == 1 then o:ubttn() Snek:updt(dt) Coin:updt(dt) elseif o.state == 2 then if o.pbttn.lock then o.pbttn.time = o.pbttn.time - dt if o.pbttn.time <= 0 then o.pbttn.lock = false end else if T:isDown(1) then o.state = 0 o.pbttn.time = 0.3 end end elseif o.state == 3 then o.timer = o.timer + dt o:updtfire(dt) if o.timer > 4 then if T:isDown(1) then Snek:reset() Coin:reset() o.state = 0 o.timer = 3 end end else o.timer = o.timer + dt if o.timer > 3.2 then if T:isDown(1) then Snek:reset() Coin:reset() o.state = 0 o.timer = 3 end end end end
Game.maxfont = fontfits("A", 0, W, false, true)
Game.disp = function(o) Grid:disp() Coin:disp() Snek:disp() Game:dbttn() if o.state == 0 then draw.setfont("Menlo", o.maxfont) local s = tostring(math.ceil(o.timer)) local w, h = draw.stringsize(s) draw.string(s, W/2 - w/2, H/2 - h/2, colors.white) elseif o.state == 1 then
elseif o.state == 2 then local s = "PAUSED" draw.setfont("Menlo", fontfits(s, W, 0, true, false)) local w, h = draw.stringsize(s) draw.string(s, W/2 - w/2, H/2 - h/2, colors.white) elseif o.state == 3 then draw.fillrect(0, 0, W, H, {0, 0, 0, o.timer/3})
o:dispfire()
local s = "YOU WON!" if o.timer > 4 then s = "PRESS SCREEN" end draw.setfont("Menlo", fontfits(s, W, 0, true, false)) local w, h = draw.stringsize(s) draw.string(s, W/2 - w/2, H/2 - h/2, colors.teal) else draw.fillrect(0, 0, W, H, {0, 0, 0, o.timer/3}) local s = "YOU LOSE" if o.timer > 3.2 then s = "PRESS SCREEN" end draw.setfont("Menlo", fontfits(s, W, 0, true, false)) local w, h = draw.stringsize(s) draw.string(s, W/2 - w/2, H/2 - h/2, colors.crimson)
end end end
-- Update those things local function updt(dt) Game:updt(dt) end
-- Draw those things local function disp(dt) Game:disp() end
-- Main game loop local function main() -- Personally, I like the better definition setting 2 has draw.setscreen(2)
init() -- Init Stuff
-- Delta Timer local timer = { step_last = sys.gettime() }
timer.step = function() local time, last = sys.gettime(), timer.step_last timer.step_last= time return time - last end
-- Fps setting fps = 120 ipf = 1 / fps
-- dt: time between last call to timer.step local dt, ft = timer.step(), 0 -- Game Loop while true do dt = timer.step() -- Update and Draw at FPS if ft < ipf then ft = ft + dt else draw.doevents() updt(ft)
draw.beginframe() draw.clear(draw.black) disp(ft) --draw.string(1/ft, 0, 100, colors.white) draw.endframe()
ft = 0 end sys.sleep(0.01) end end
main()
|
|