Last active
August 29, 2015 14:04
-
-
Save tarrouye/cce08f9c984ed81440dd to your computer and use it in GitHub Desktop.
Ladderman Gist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# Main | |
-- Ladderman | |
displayMode(FULLSCREEN) | |
supportedOrientations(PORTRAIT) | |
function setup() | |
LOADINGIMGS, PLAYING, LOST = 1, 2, 3 | |
imgLoader = Loader() | |
MODE = LOADINGIMGS | |
end | |
function afterImgSetup() | |
MODE = PLAYING | |
stuffs() | |
initialise() | |
end | |
function draw() | |
background(255) | |
if MODE == LOADINGIMGS then | |
imgLoader:draw() | |
if imgLoader.doneLoading then | |
afterImgSetup() | |
end | |
end | |
if MODE == PLAYING or MODE == LOST then | |
drawGame() | |
end | |
if MODE == LOST then | |
drawLost() | |
end | |
end | |
function touched(t) | |
if t.state == ENDED then | |
if MODE == PLAYING then | |
touchPlaying(t) | |
elseif MODE == LOST then | |
touchLost(t) | |
end | |
end | |
end | |
--# Playing | |
-- Just holds most of the functions for the playing state | |
-- Resets the game | |
function initialise() | |
ladders = {} | |
player = { x = rightX, y = sizes.ladder.y * 2.5, cid = math.random(1, 5), iid = 1, angle = 0 } | |
sign = { x = 0, y = sizes.ladder.y + sizes.sign.y / 2, alpha = 0 } | |
for r = 1, math.ceil(HEIGHT / sizes.ladder.y) + 1 do | |
addRow(true) | |
end | |
groundO = sizes.ladder.y | |
score = 0 | |
highscore = readLocalData("highscore") or 0 | |
time = .5 | |
if timeT ~= nil then tween.stop(timeT) end | |
canMove = true | |
fell = false | |
end | |
-- Draws everything for the playing state | |
function drawGame() | |
-- Draw the 'bulding' background | |
for bi = #ladders, 1, -2 do | |
sprite(imgs.brick, WIDTH / 2, ladders[bi].y, WIDTH, sizes.ladder.y) | |
end | |
-- Draw the ladders | |
for li = #ladders, 1, -1 do | |
local ladder = ladders[li] | |
if not ladder.hole then | |
sprite(imgs.ladder, ladder.x, ladder.y, sizes.ladder.x, sizes.ladder.y) | |
else | |
sprite(imgs.hole, ladder.x, ladder.y, sizes.ladder.x, sizes.ladder.y) | |
end | |
end | |
-- Draw the player | |
pushMatrix() translate(player.x, player.y) rotate(player.angle) | |
sprite(imgs.player[player.cid][player.iid], 0, 0, sizes.player.x, sizes.player.y) | |
popMatrix() | |
-- Draw the ground if it is still onscreen | |
if groundO < sizes.ladder.y then | |
sprite(imgs.ground, WIDTH / 2, sizes.ladder.y / 2 - groundO, WIDTH, sizes.ladder.y) | |
end | |
-- Draw the timer bar | |
local o = WIDTH / 200 | |
local a = (rightX - sizes.ladder.x / 2) - (leftX + sizes.ladder.x / 2) | |
sprite(imgs.bar[1], WIDTH / 2, HEIGHT - HEIGHT / 40, a, HEIGHT / 20) | |
sprite(imgs.bar[2], WIDTH / 2, HEIGHT - HEIGHT / 40, (a - o*1.8) * time, HEIGHT / 20 - o*1.8) | |
-- Draws the score and then the highscore right below it | |
sprite(imgs.panel, WIDTH / 2, HEIGHT / 2, sizes.replay.x) | |
font(GAMEFONT) | |
fill(0) if score >= highscore then fill(255,0,0) end fontSize(WIDTH / 10) | |
text(score, WIDTH / 2, HEIGHT / 2) | |
fill(255,0,0) fontSize(WIDTH / 20) | |
text(math.max(highscore, score), WIDTH / 2, HEIGHT / 2 - fontSize() * 1.5) | |
fill(0) | |
text("SCORE", WIDTH / 2, HEIGHT / 2 + fontSize() * 1.5) | |
stroke(0, 155, 255, 153) strokeWidth(oneS * 2) | |
line(WIDTH / 2 - sizes.replay.x / 2.17, HEIGHT / 2 - fontSize(), WIDTH / 2 + sizes.replay.x / 2.17, HEIGHT / 2 - fontSize()) | |
line(WIDTH / 2 - sizes.replay.x / 2.17, HEIGHT / 2 + fontSize(), WIDTH / 2 + sizes.replay.x / 2.17, HEIGHT / 2 + fontSize()) | |
-- Lost / died sign | |
tint(255, sign.alpha) | |
sprite(imgs.sign, sign.x, sign.y, sizes.sign.x, sizes.sign.y) | |
noTint() | |
end | |
-- Losing sequence | |
function fall() | |
canMove = false | |
fell = true | |
sounds.fall() | |
if timeT ~= nil then tween.stop(timeT) end | |
tween(.75, _G, { groundO = 0 }) | |
falling = tween(.75, player, { y = 0, angle = 230 }, tween.easing.linear, function() | |
sounds.die() | |
sign.x = player.x + sizes.ladder.x / 2 + sizes.sign.x / 1.75 | |
if player.x == leftX then sign.x = player.x - sizes.ladder.x / 2 - sizes.sign.x / 1.75 end | |
falling = tween(.5, sign, { alpha = 255 }, tween.easing.linear, function() | |
animateEndMenu() | |
MODE = LOST | |
end) | |
end) | |
end | |
-- Adds another row to the top of the ladder | |
function addRow(rnok) | |
local y | |
if #ladders == 0 then y = sizes.ladder.y / 2 | |
else y = ladders[#ladders].y + sizes.ladder.y end | |
local rand = math.random(1, 5) | |
local rhole, lhole = false, false | |
if not rnok then | |
if rand == 2 and lastRand ~= 3 then rhole = true | |
elseif rand == 3 and lastRand ~= 2 then lhole = true end | |
end | |
lastRand = rand | |
table.insert(ladders, { x = rightX, y = y, hole = rhole }) | |
table.insert(ladders, { x = leftX, y = y, hole = lhole }) | |
end | |
-- Checks if the player is in a hole | |
function checkLoss() | |
if fell then return true end | |
for li = #ladders, 1, -1 do | |
local ladder = ladders[li] | |
if ladder.hole and ladder.x == player.x and math.abs(ladder.y - player.y) < sizes.ladder.y / 2 then | |
if score > highscore then | |
saveLocalData("highscore", score) | |
end | |
fall() | |
return true | |
end | |
end | |
return false | |
end | |
-- Moves ladders and player, and calls to check if player is in a hole | |
function moveObjects(right) | |
canMove = false | |
player.iid = 2 | |
sounds.climb() | |
if right then | |
player.x = rightX | |
else | |
player.x = leftX | |
end | |
checkLoss() | |
for li = #ladders, 1, -1 do | |
local ladder = ladders[li] | |
tween(0.04, ladder, { y = ladder.y - sizes.ladder.y }) | |
if ladder.y < 0 then | |
table.remove(ladders, li) | |
end | |
end | |
tween.delay(0.04, function() | |
addRow() | |
if not checkLoss() then | |
player.iid = 1 | |
score = score + 1 | |
canMove = true | |
end | |
end) | |
end | |
-- Adds a bit of time to the timer | |
function addToTimer() | |
if timeT ~= nil then | |
tween.stop(timeT) | |
timeT = nil | |
end | |
time = math.min(time + .04, 1) | |
timeT = tween(time * 8, _G, { time = 0 }, tween.easing.linear, fall) | |
end | |
-- All the touch code for the playing state | |
function touchPlaying(t) | |
if canMove then | |
moveObjects(t.x > WIDTH / 2) | |
addToTimer() | |
end | |
end | |
--# Lost | |
-- Just holds most of the functions for the lost state | |
function animateEndMenu() | |
tween(.5, replay, { y = HEIGHT / 2 - sizes.replay.x - sizes.replay.y}) | |
end | |
function animateHideEndMenu() | |
tween(.5, replay, { y = -sizes.replay.y / 2 }, tween.easing.linear, function() | |
initialise() | |
MODE = PLAYING | |
end) | |
end | |
function drawLost() | |
sprite(imgs.panel, replay.x, replay.y, sizes.replay.x, sizes.replay.y) | |
stroke(0, 155, 255, 153) strokeWidth(oneS * 2) | |
local lof, sof, tof = sizes.replay.x / 2.17, sizes.replay.y / 4, sizes.replay.y / 9 | |
--line(replay.x - lof, replay.y - sof, replay.x + lof, replay.y - sof) | |
--line(replay.x - lof, replay.y + sof, replay.x + lof, replay.y + sof) | |
fill(0) fontSize(sizes.replay.y * .6) | |
text("AGAIN?", replay.x, replay.y) | |
end | |
function touchLost(t) | |
if t.x >= replay.x - sizes.replay.x / 2 and t.x <= replay.x + sizes.replay.x / 2 | |
and t.y >= replay.y - sizes.replay.y / 2 and t.y <= replay.y + sizes.replay.y / 2 then | |
animateHideEndMenu() | |
end | |
end | |
--# Variables | |
function stuffs() | |
GAMEFONT = "Futura-CondensedMedium" | |
oneS = WIDTH / 768 | |
sounds = { | |
climb = function() sound("A Hero's Quest:Swing 3") end, | |
fall = function() sound("A Hero's Quest:Hurt 4") end, | |
die = function() sound("A Hero's Quest:Hurt 5") end | |
} | |
local bimg, gimg = makeImgs() | |
imgs = { | |
ladder = readImage("Documents:LMLadder"), | |
hole = readImage("Documents:LMHole"), | |
player = { | |
{ readImage("Documents:LMPlayerB1"), readImage("Documents:LMPlayerB2") }, | |
{ readImage("Documents:LMPlayerL1"), readImage("Documents:LMPlayerL2") }, | |
{ readImage("Documents:LMPlayerP1"), readImage("Documents:LMPlayerP2") }, | |
{ readImage("Documents:LMPlayerG1"), readImage("Documents:LMPlayerG2") }, | |
{ readImage("Documents:LMPlayerY1"), readImage("Documents:LMPlayerY2") }, | |
}, | |
ground = gimg, | |
sign = readImage("Documents:LMRipsign"), | |
brick = bimg, | |
bar = { readImage("Documents:LMBargray"), readImage("Documents:LMBarred") }, | |
panel = readImage("Documents:LMGlasspanel") | |
} | |
sizes = { | |
ladder = vec2(WIDTH / 9, HEIGHT / 9), | |
player = vec2(WIDTH / 10, HEIGHT / 9.5), | |
sign = vec2(WIDTH / 8, HEIGHT / 9), | |
replay = vec2(WIDTH / 4.725, WIDTH / 9) | |
} | |
replay = { x = WIDTH / 2, y = -sizes.replay.y / 2 } | |
leftX = WIDTH / 3.5 | |
rightX = WIDTH * 2.5/3.5 | |
end | |
function makeImgs() | |
local brickImg = image(WIDTH, HEIGHT / 9) setContext(brickImg) | |
for i = 1, 9 do | |
sprite("Documents:LMStone", -WIDTH / 18 + (WIDTH / 9) * i, HEIGHT / 18, WIDTH / 9, HEIGHT / 9) | |
end | |
setContext() | |
local groundImg = image(WIDTH, HEIGHT / 9) setContext(groundImg) | |
for i = 1, 9 do | |
sprite("Documents:LMGrass", -WIDTH / 18 + (WIDTH / 9) * i, HEIGHT / 18, WIDTH / 9, HEIGHT / 9) | |
end | |
setContext() | |
return brickImg, groundImg | |
end | |
--# ImagesToLoad | |
ImagesToLoad = { | |
{ spriteKey = "Documents:LMLadder", url = "http://i.imgur.com/xIqzbtJ.png" }, | |
{ spriteKey = "Documents:LMHole", url = "http://i.imgur.com/o3a08eD.png" }, | |
{ spriteKey = "Documents:LMPlayerB1", url = "http://i.imgur.com/lZBuLGQ.png" }, | |
{ spriteKey = "Documents:LMPlayerB2", url = "http://i.imgur.com/eSj4r9g.png" }, | |
{ spriteKey = "Documents:LMPlayerG1", url = "http://i.imgur.com/api8OpI.png" }, | |
{ spriteKey = "Documents:LMPlayerG2", url = "http://i.imgur.com/86vF38r.png" }, | |
{ spriteKey = "Documents:LMPlayerL1", url = "http://i.imgur.com/ZqLSUj2.png" }, | |
{ spriteKey = "Documents:LMPlayerL2", url = "http://i.imgur.com/gfKRLMi.png" }, | |
{ spriteKey = "Documents:LMPlayerP1", url = "http://i.imgur.com/x2vI7Gk.png" }, | |
{ spriteKey = "Documents:LMPlayerP2", url = "http://i.imgur.com/U7860TA.png" }, | |
{ spriteKey = "Documents:LMPlayerY1", url = "http://i.imgur.com/LQndLGf.png" }, | |
{ spriteKey = "Documents:LMPlayerY2", url = "http://i.imgur.com/kfE2Yal.png" }, | |
{ spriteKey = "Documents:LMRipsign", url = "http://i.imgur.com/OVaoNjo.png" }, | |
{ spriteKey = "Documents:LMBargray", url = "http://i.imgur.com/gSB7EAr.png" }, | |
{ spriteKey = "Documents:LMBarred", url = "http://i.imgur.com/5TDecbn.png" }, | |
{ spriteKey = "Documents:LMGlasspanel", url = "http://i.imgur.com/rkz6v3L.png" }, | |
{ spriteKey = "Documents:LMStone", url = "http://i.imgur.com/5dnSgbO.png" }, | |
{ spriteKey = "Documents:LMGrass", url = "http://i.imgur.com/sjnBImb.png" }, | |
} | |
--# Loader | |
Loader = class() | |
function Loader:init() | |
self.loaded = 0 | |
self.loading = nil | |
self.doneLoading = false | |
self.onEnterTime = 0 | |
self.colour = color(0, 133, 255, 255) | |
self.circSize = (WIDTH / 3)*2 + 40 | |
self.displayErrorMessage = false | |
self.queue = {} | |
self:onEnter() | |
end | |
function Loader:onEnter() | |
self.loaded = 0 | |
self.loading = nil | |
self.doneLoading = false | |
self.changing = nil | |
self.onEnterTime = ElapsedTime | |
self.displayErrorMessage = false | |
self.queue = {} | |
self:loadImages() | |
end | |
function Loader:loadImages() | |
for id, stuff in ipairs(ImagesToLoad) do | |
if readImage(stuff.spriteKey) == nil then | |
self:addToQueue(stuff) | |
else | |
self.loaded = self.loaded + 1 | |
end | |
end | |
self:checkQueue() | |
end | |
function Loader:addToQueue(stuff) | |
table.insert(self.queue, stuff) | |
self:checkQueue() | |
end | |
function Loader:checkQueue() | |
if self.loaded == #ImagesToLoad then | |
self.doneLoading = true | |
end | |
for id, stuff in ipairs(self.queue) do | |
if id == 1 and self.loading == nil then | |
self:load(stuff) | |
self.loading = "busy" | |
table.remove(self.queue, id) | |
end | |
end | |
end | |
function Loader:load(stuff) | |
local saveThenNext = function(img) | |
saveImage(stuff.spriteKey, img) | |
self.loaded = self.loaded + 1 | |
self.loading = nil | |
self:checkQueue() | |
end | |
--[[local getActualUrl = function(data) | |
local check = '<meta content="Shared with Dropbox" property="og:description" /><meta content="(.*)" property="og:image" />' | |
--local a, b = data:find(';\nShmodelPreview.init_photo("', 1, true) | |
--local c, d = data:find('", ', b, true) | |
--local acUrl = data:sub(b+1, c-1) | |
local acUrl = data:match(check) | |
http.request(acUrl, saveThenNext, function() self:failed() end) | |
end]] | |
http.request(stuff.url, saveThenNext, function() self:failed() end) | |
end | |
function Loader:failed() | |
self.displayErrorMessage = true | |
end | |
function Loader:draw() | |
background(255) | |
if self.displayErrorMessage == false then | |
pushStyle() | |
stroke(self.colour) noFill() strokeWidth(1) | |
ellipse(WIDTH/2, HEIGHT/2, self.circSize) | |
font("HelveticaNeue-Light") fontSize(35) | |
fill(self.colour) | |
text("Loading", WIDTH/2, fontSize()) | |
for i = 1, #ImagesToLoad do | |
stroke(self.colour) strokeWidth(2) | |
noFill() | |
if self.loaded >= i then | |
fill(self.colour) | |
end | |
local perRow = 6 | |
local spacing, size = 50, 25 | |
local rows = math.ceil(#ImagesToLoad / perRow) | |
local row = math.ceil(i / perRow) | |
local off = rows / 2 | |
local startY = HEIGHT/2 + off * size + off * spacing | |
local y = startY - size * (row-0.5) - spacing * (row-0.5) | |
local inRow = i - ((row-1) * perRow) | |
local startX = WIDTH/2 - (perRow/2 * size) - (perRow/2 * spacing) | |
local x = startX + size * (inRow-0.5) + spacing * (inRow-0.5) | |
ellipse(x, y, size) | |
end | |
popStyle() | |
else | |
font(STANDARDFONT) fontSize(35) | |
fill(38, 38, 38, 255) textAlign(CENTER) | |
text("An Error Occured. Please Check\nYour Internet And Reload Codea.", WIDTH/2, HEIGHT/2) | |
end | |
end | |
function Loader:touched(touch) | |
-- Codea does not automatically call this method | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment