Skip to content

Instantly share code, notes, and snippets.

@SkyTheCoder
Created October 13, 2014 18:05
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 SkyTheCoder/7c9d7350d5d573459d90 to your computer and use it in GitHub Desktop.
Save SkyTheCoder/7c9d7350d5d573459d90 to your computer and use it in GitHub Desktop.
FallDodge, my Codea Cook-Off competition entry from a while ago.
--# Highscores
Highscores = class()
function Highscores:init()
--ScoreTracker(project,success callback, fail callback)
--s.results holds the returned results in a table.
self.data = {a = 0, b = 0}
self.tweened = {a = 0, b = 0}
self.tweens = {a = -1337, b = -1337}
self.scores = {}
self.name = ""
self.s = ScoreTracker("FallDodge",function(d)
table.sort(self.s.results, function(a, b)
return a[2] > b[2]
end)
self.scores = self.s.results
self.s.results = {}
print("High Scores!\n")
for i,j in pairs(self.s.results) do
print("Rank "..i.."\nUser: "..j[1]..
"\nScore: "..j[2]..
"\nField1: "..j[3]..
"\nField2: "..j[4]..
"\nField3: "..j[5])
end
end) -- setup score tracker
--This will create a new entry
--s:submit("test user","999","level 1","lives 2")
--This returns the entry.
tween.delay(2, function()
self:get()
end)
end
function Highscores:get()
self.s:request()
end
function Highscores:draw()
pushStyle()
pushMatrix()
background(255)
font("Copperplate-Light")
fontSize(48)
fill(0)
if newHighScore then
fontSize(24)
text("NEW PERSONAL BEST", 256, HEIGHT - 96)
fontSize(48)
end
text("HIGHSCORES", WIDTH / 2, HEIGHT / 2 + 96)
fontSize(24)
for k, v in pairs(self.scores) do
if k <= 5 then
text(v[1] .. ": " .. string.format("%18.0f", tonumber(v[2])), WIDTH / 2, HEIGHT / 2 - ((k - 1) * 36))
end
end
fontSize(36)
text("SUBMIT YOUR SCORE", WIDTH / 2, 192)
if self.textbox then
background(255)
text("ENTER YOUR NAME", WIDTH / 2, HEIGHT / 2 + 96)
fontSize(24)
self.name = keyboardBuffer()
local renderName = self.name
if isKeyboardShowing() and math.sin(4 * ElapsedTime) >= 0 then
renderName = renderName .. "|"
end
text(renderName, WIDTH / 2, HEIGHT / 2)
end
fontSize(24)
fill(self.data.b)
text("Back", WIDTH / 2, 96)
popStyle()
popMatrix()
end
function Highscores:touched(touch)
local time = 0.25
pushStyle()
font("Copperplate-Light")
fontSize(36)
local w, h = textSize("SUBMIT YOUR SCORE")
if math.abs(WIDTH / 2 - touch.x) <= w and math.abs(192 - touch.y) <= h then
if touch.state == BEGAN or touch.state == MOVING then
if self.tweened.a == 0 then
if self.tweens.a ~= -1337 then
tween.stop(self.tweens.a)
end
self.tweens.a = tween(time, self.data, {a = 128})
self.tweened.a = 1
end
else
if self.tweened.a == 1 then
if self.tweens.a ~= -1337 then
tween.stop(self.tweens.a)
end
self.tweens.a = tween(time, self.data, {a = 0})
self.tweened.a = 0
self.textbox = true
showKeyboard()
end
end
else
if self.tweens.a ~= -1337 and self.tweened.a == 1 then
tween.stop(self.tweens.a)
self.tweens.a = tween(time, self.data, {a = 0})
end
self.tweened.a = 0
end
local w, h = textSize("Back")
if math.abs(WIDTH / 2 - touch.x) <= w and math.abs(96 - touch.y) <= h then
if touch.state == BEGAN or touch.state == MOVING then
if self.tweened.b == 0 then
if self.tweens.b ~= -1337 then
tween.stop(self.tweens.b)
end
self.tweens.b = tween(time, self.data, {b = 128})
self.tweened.b = 1
end
else
if self.tweened.b == 1 then
if self.tweens.b ~= -1337 then
tween.stop(self.tweens.b)
end
self.tweens.b = tween(time, self.data, {b = 0})
self.tweened.b = 0
state = 1
end
end
else
if self.tweens.b ~= -1337 and self.tweened.b == 1 then
tween.stop(self.tweens.b)
self.tweens.b = tween(time, self.data, {b = 0})
end
self.tweened.b = 0
end
if touch.state == ENDED and not isKeyboardShowing() and self.textbox then
showKeyboard()
end
popStyle()
end
function Highscores:keyboard(key)
if key == RETURN then
self.textbox = false
hideKeyboard()
self.s:submit(self.name, math.floor(states[2].score))
tween.delay(2, function()
self:get()
end)
end
end
--# LoaderInfo
LoaderInfo = class()
function LoaderInfo:init()
self.a = {
"Interpolating",
"Splining",
"Training",
"Downloading",
"Converting",
"Ionizing",
"Teleporting",
"Transporting",
"Atomizing",
"Sculpting",
"Targetting",
"Lazering",
"Lazerizing",
"Exploding",
"Imploding",
"Exterminating",
"Deleting",
}
self.b = {
"Shiny",
"Wibbly-wobbly",
"Timey-wimey",
"Oddly Shaped",
"Spherical",
"Decomposed",
"Monkey",
"Machine",
"Machinima",
"Sanitized",
"Square",
"Blocky",
"Cube-y",
"Friendly",
"Mean",
"Meaty",
"Annoying",
"Perfectly Normally Shaped",
"Terrifying",
"Very",
}
self.c = {
"Monkeys (not apes)",
"Pandas",
"Gorillas (not monkeys)",
"Apes (not gorillas)",
"Walruses (koo-koo-ka-choo)",
"Terrifying Butterflies",
"Butterflies of Terror",
"Mechanical Bulls",
"TARDISes",
"Doctors",
"Minecrafts",
"Minecraft Worlds",
"Jerks",
"Old-Timey Time Watches",
"Jelly Babies",
"Laptops",
"Squirrels",
"Adorable Puppies",
"Christmas Goats",
}
end
function LoaderInfo:getPhrase()
local a = self.a[math.random(1, #self.a)]
local b = self.b[math.random(1, #self.b)]
local c = self.c[math.random(1, #self.c)]
return a .. " " .. b .. " " .. c
end
--# Lose
Lose = class()
function Lose:init()
self.bgSprites = {
readImage("Documents:DL-Asset-grass_full"),
readImage("Documents:DL-Asset-rock"),
readImage("Documents:DL-Asset-mushroom_red"),
readImage("Documents:DL-Asset-grass_full"),
readImage("Documents:DL-Asset-spring_pushed"),
readImage("Platformer Art:Guy Look Right"),
readImage("Documents:DL-Asset-grass_full"),
readImage("Platformer Art:Mushroom"),
}
self.offsets = {
50,
85,
85,
50,
75,
90,
50,
85,
}
self.angleOffset = 0
self.data = {a = 0, b = 0}
self.tweened = {a = 0, b = 0}
self.tweens = {a = -1337, b = -1337}
end
function Lose:draw()
pushStyle()
pushMatrix()
background(255)
pushMatrix()
translate(WIDTH / 2, HEIGHT / 2 + 196)
rotate(self.angleOffset)
for k, v in ipairs(self.bgSprites) do
sprite(v, 0, self.offsets[k])
rotate(360 / #self.bgSprites)
end
if isRecording() then
self.angleOffset = self.angleOffset + 0.5
else
self.angleOffset = self.angleOffset + 0.5 * DeltaTime * 60
end
popMatrix()
fill(0)
fontSize(48)
font("Copperplate-Light")
text("YOU LOST", WIDTH / 2, HEIGHT / 2 + 96)
text("YOUR SCORE: " .. string.format("%18.0f", math.floor(states[2].score)), WIDTH / 2, HEIGHT / 2)
fontSize(24)
fill(self.data.a)
text("Replay", WIDTH / 2, HEIGHT / 2 - 96)
fill(self.data.b)
text("Highscores", WIDTH / 2, 96)
popMatrix()
popStyle()
end
function Lose:touched(touch)
local time = 0.25
pushStyle()
font("Copperplate-Light")
fontSize(24)
local w, h = textSize("Replay")
if math.abs(WIDTH / 2 - touch.x) <= w and math.abs(HEIGHT / 2 - 96 - touch.y) <= h then
if touch.state == BEGAN or touch.state == MOVING then
if self.tweened.a == 0 then
if self.tweens.a ~= -1337 then
tween.stop(self.tweens.a)
end
self.tweens.a = tween(time, self.data, {a = 128})
self.tweened.a = 1
end
else
if self.tweened.a == 1 then
if self.tweens.a ~= -1337 then
tween.stop(self.tweens.a)
end
self.tweens.a = tween(time, self.data, {a = 0})
self.tweened.a = 0
state = 2
states[2].score = 0
end
end
else
if self.tweens.a ~= -1337 and self.tweened.a == 1 then
tween.stop(self.tweens.a)
self.tweens.a = tween(time, self.data, {a = 0})
end
self.tweened.a = 0
end
local w, h = textSize("Highscores")
if math.abs(WIDTH / 2 - touch.x) <= w and math.abs(96 - touch.y) <= h then
if touch.state == BEGAN or touch.state == MOVING then
if self.tweened.b == 0 then
if self.tweens.b ~= -1337 then
tween.stop(self.tweens.b)
end
self.tweens.b = tween(time, self.data, {b = 128})
self.tweened.b = 1
end
else
if self.tweened.b == 1 then
if self.tweens.b ~= -1337 then
tween.stop(self.tweens.b)
end
self.tweens.b = tween(time, self.data, {b = 0})
self.tweened.b = 0
state = 4
end
end
else
if self.tweens.b ~= -1337 and self.tweened.b == 1 then
tween.stop(self.tweens.b)
self.tweens.b = tween(time, self.data, {b = 0})
end
self.tweened.b = 0
end
popStyle()
end
function Lose:keyboard(key)
end
--# Static
static = {}
--# Game
Game = class()
function Game:init()
newHighScore = false
self.genOff = 200
self.offset = vec2(0, 0)
self.renderbg = RenderBG(self)
self.player = Player(self, 50, HEIGHT - 92)
tween(3, self.player.pos, {x = 200}, tween.easing.linear, function()
self.player.pose = 1
tween.delay(1, function()
self.player.pose = 2
end)
tween.delay(2, function()
tween.delay(0.5, function()
self.player.pose = 3
end)
tween(1, self.player.pos, {y = HEIGHT - 86}, tween.easing.quadIn)
tween(1, self.player.aestheticAngle, {a = 45}, tween.easing.quadIn, function()
tween(1.5, self.player.aestheticAngle, {a = 0}, tween.easing.quadOut)
tween(1, self.player.pos, {x = 300, y = HEIGHT - 128}, tween.easing.quadIn, function()
self.player.move = true
self.player.moveY = true
end)
end)
end)
end)
self.objects = {}
self.generate = false
tween.delay(16, function()
self.generate = true
end)
self.done = false
self.types = {
Mushroom,
Spring,
Ledge,
}
self.weights = {
65,
20,
15
}
self.pcount = 0
self.score = 0
end
function Game:gen()
local i = math.random(0, 1)
local type
while type == nil do
local cType = math.random(1, #self.weights)
local chance = self.weights[cType]
if math.random(0, 100) <= chance then
type = self.types[cType]
end
end
table.insert(self.objects, type(self, (WIDTH * 0.2 + i * (WIDTH * 0.6)) + (-i * 2 + 1) * 49, self.genOff))
self.genOff = self.genOff - 200
end
function Game:win()
self.player.move = false
self.player.dir = -1
self.player.pose = 3
tween(1, self.player.pos, {y = HEIGHT + 100}, tween.easing.quadOut, function()
tween(0.5, self.player.pos, {x = 200}, tween.easing.quadInOut, function()
tween(2, self.player.pos, {y = HEIGHT - 92}, tween.easing.quadIn, function()
self.player.pose = 5
tween(3, self.player.pos, {x = 50}, tween.easing.linear, function()
self.player.pose = 2
tween.delay(0.5, function()
self.player.dir = 1
self.player.pose = 1
tween.delay(0.5, function()
self.player.pose = 2
tween.delay(0.5, function()
self.player.pose = 3
self.player.breakScared = true
tween(1, self.player.pos, {y = HEIGHT - 64}, tween.easing.quadOut, function()
tween(1, self.player.pos, {y = HEIGHT - 92}, tween.easing.quadIn, function()
tween.delay(0.5, function()
self.player.pose = 2
self.player.breakScared = false
self.player:lookScared()
tween.delay(0.5, function()
self.player.pose = 1
tween.delay(0.5, function()
self.player.pose = 2
self.player.dir = -1
tween.delay(0.5, function()
self.player.pose = 5
tween(3, self.player.pos, {x = -100}, tween.easing.linear, function()
--print("DONE")
--displayMode(STANDARD)
self.done = true
end)
end)
end)
end)
end)
end)
end)
end)
end)
end)
end)
end)
end)
end)
end
function Game:minusPcount()
self.pcount = self.pcount - 1
end
function Game:plusPcount()
self.pcount = self.pcount + 1
end
function Game:draw()
if self.player.move then
self.score = self.score + DeltaTime * 5
self.score = self.score + math.max(0, self.player.motY) * DeltaTime * 5
end
if math.floor(self.player.pos.y / 46) <= -256 then
state = 5
end
for k, v in ipairs(self.objects) do
if v.type == "ledge" then
self.pcount = self.pcount + 1
end
end
--print(static.ledge.pcount)
pushStyle()
pushMatrix()
translate(self.offset.x, self.offset.y)
self.renderbg:draw()
self.player:draw()
for k, v in ipairs(self.objects) do
v:draw()
end
if self.generate then
if self.player.pos.y <= self.genOff + HEIGHT * 3 then
self:gen()
end
if self.player.pos.y <= self.genOff + HEIGHT * 3 then
self:gen()
end
if self.player.pos.y <= self.genOff + HEIGHT * 3 then
self:gen()
end
if self.player.pos.y <= self.genOff + HEIGHT * 3 then
self:gen()
end
if self.player.pos.y <= self.genOff + HEIGHT * 3 then
self:gen()
end
if self.player.pos.y <= self.genOff + HEIGHT * 3 then
self:gen()
end
if self.player.pos.y <= self.genOff + HEIGHT * 3 then
self:gen()
end
end
if self.done then
fontSize(48)
--text("YOU WON!!!", WIDTH / 2, HEIGHT / 2)
state = 3
if self.score > readGlobalData("FallDodge.Highscore", 0) then
newHighScore = true
saveGlobalData("FallDodge.Highscore", self.score)
end
end
popMatrix()
popStyle()
if self.pcount == 0 and self.player.onLedge then
self.player.onLedge = false
self.player.pose = 3
--self.player.moveY = true
end
self.pcount = 0
--static.ledge.setPCount(0)
font("Copperplate-Light")
fontSize(24)
color(0)
text("YOUR SCORE: " .. string.format("%18.0f", self.score), WIDTH / 2, HEIGHT - 48)
end
function Game:getObj(id)
return self.objects[id] or {pos = {y = 0}}
end
function Game:touched(touch)
self.player:touched(touch)
end
function Game:keyboard(key)
end
--# Ledge
static.ledge = { -- Static variables, the same for all classes
pcount = 0
}
Ledge = class()
function Ledge:init(game, x, y)
self.game = game
self.pos = vec2(x, y)
self.img = readImage("Documents:DL-Asset-stone_ledge_left")
self.dir = 1
self:calcDir()
self.bounceTime = 0
self.type = "ledge"
self.setPlayerAnim = false
end
function Ledge:calcDir()
if self.pos.x <= WIDTH / 2 then
self.dir = 1
else
self.dir = -1
end
end
function static.ledge.setPCount(n)
static.ledge.pcount = n
end
function Ledge:draw()
self.game:minusPcount()
--static.ledge.pcount = static.ledge.pcount - 1
if math.abs(self.game.player.pos.y - self.pos.y) <= 80 and math.abs(self.game.player.pos.x - self.pos.x) <= 60 then
--print("COLLISION")
if self.game.player.pos.y < self.pos.y - 20 then
--print("UNDER")
self.game.player.motY = math.abs(self.game.player.motY * 0.5)
self.game.player.pos.y = self.game.player.pos.y - 5
else
--print("TOP")
self.game:plusPcount()
--static.ledge.pcount = static.ledge.pcount + 1
if self.bounceTime <= 3 then
--print("BOUNCE")
self.game.player.motY = -math.abs(self.game.player.motY * 0.5)
self.bounceTime = self.bounceTime + 1
else
self.game.player.pos.y = self.pos.y + 80
--print("STAY")
--self.game.player.moveY = false
self.game.player.onLedge = true
if math.abs(self.game.player.motX) >= 0.5 then
--print("FAST")
if not self.setPlayerAnim then
self.game.player.pose = 5
self.setPlayerAnim = true
end
else
--print("SLOW")
if self.setPlayerAnim then
self.game.player.pose = 1
self.setPlayerAnim = false
end
end
end
end
elseif math.abs(self.game.player.pos.x - self.pos.x) > 60 then
--print("OFF SIDE")
self.bounceTime = 0
end
if self.bounceTime ~= 0 and self.game.player.pos:dist(self.pos) > 200 then
--print("FAR")
self.bounceTime = 0
end
--print(self.bounceTime)
pushStyle()
pushMatrix()
translate(self.pos.x, self.pos.y)
sprite(self.img, 0, 0, self.dir * self.img.width, self.img.height)
popMatrix()
popStyle()
end
--# Main
--The name of the project must match your Codea project name if dependencies are used.
--Project: FallDodge
--Version: Alpha 1.5.1
--Comments:
-- FallDodge
displayMode(FULLSCREEN)
-- Use this function to perform your initial setup
function setup()
dl_meta_url = "https://dl.dropboxusercontent.com/s/hm3h54zodpjohq7/info.dl_meta?dl=1&token_hash=AAGtxlx5b7xN6mFfly97HNUAkMnmh8pFmBWkzE1WRkW6Nw"
http.request(dl_meta_url, dl_meta_success, dl_meta_fail)
--startRecording()
print("Hello World!")
parameter.watch("1 / DeltaTime")
menu = Menu()
game = Game()
replay = Replay()
highscores = Highscores()
lose = Lose()
states = {
menu,
game,
replay,
highscores,
lose,
}
state = 1
oldState = state
ready = false
animStart = 0
needToGet = 1
gotten = 0
introData = {0, 0, 0, 0}
introFiles = {
readImage("Documents:DL-Asset-intro_1"),
readImage("Documents:DL-Asset-intro_2"),
readImage("Documents:DL-Asset-intro_3"),
readImage("Documents:DL-Asset-intro_4"),
}
readyForStates = false
readyForStatesDraw = false
showTouches = true
lineCount()
lInfo = LoaderInfo()
phrase = ""
loopPhrase()
getUrls = {}
end
function loopPhrase()
phrase = lInfo:getPhrase()
tween.delay(2, loopPhrase)
end
function dl_meta_success(meta, status, headers)
--print(meta)
local dls = {}
local valid = string.find(meta, "DL%-META\n%.-")
if valid then
print("Valid!")
local syntax = string.match(meta, "DL%-META\nSYNTAX (.-) END_SYNTAX\n")
syntax = string.gsub(syntax, "%$NEWLINE", "\n")
print("Syntax: " .. syntax)
for id, url, info in meta:match("DATA_START\n(.-)\nDATA_END"):gmatch(syntax) do
dls[#dls + 1] = {id = id, url = url, info = info}
print("ID: " .. id .. " URL: " .. url .. " Info: " .. info)
end
end
needToGet = #dls
--dlAssets(dls)
getUrls = dls
getNextAsset()
getNextAsset()
getNextAsset()
getNextAsset()
end
function getNextAsset()
if gotten < needToGet then
dlAsset(getUrls[gotten + 1].url, getUrls[gotten + 1].id, getUrls[gotten + 1].info)
gotten = gotten + 1
end
end
function dlAsset(url, id, info)
http.request(url, function(img, status, headers)
if status == 200 and img ~= nil then
print("Downloaded asset " .. id .. " (AKA " .. info .. ") successfully")
saveImage("Documents:DL-Asset-" .. id, img)
end
getNextAsset()
end, function(err)
displayMode(STANDARD)
print("ERROR DOWNLOADING ASSET " .. id .. "(AKA " .. info .. "): " .. err)
if err == "Unable to create request (bad url?)" then
print("URL:")
print(url)
end
if err == "A connection failure occured" then
print("Try checking your internet connection")
end
getNextAsset()
end)
end
function dlAssets(dls)
if #dls > 0 then
for k, v in ipairs(dls) do
end
end
end
function dl_meta_fail(err)
print("ERROR FETCHING DOWNLOAD METADATA: " .. err)
if err == "A connection failure occurred" then
print("Try checking your internet connection")
end
print("Attempting to run anyways...")
gotten = needToGet
print("Running")
print("If any spots appear blank where they were not, this was because images were not downloaded")
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
-- Do your drawing here
background(255)
fill(0)
font("Copperplate-Light")
fontSize(48)
text("Loading", WIDTH / 2, HEIGHT / 2 + 48)
fontSize(36)
text(phrase, WIDTH / 2, HEIGHT / 2)
fontSize(24)
text(string.rep("O", gotten) .. string.rep("o", needToGet - gotten), WIDTH / 2, HEIGHT / 2 - 48)
text("Cancelling loading will cause the app to crash", WIDTH / 2, HEIGHT / 2 - 96)
if ready then
if readyForStatesDraw then
if state ~= oldState then
states[state]:init()
oldState = state
end
end
states[state]:draw()
tint(255, introData[1])
sprite("Documents:DL-Asset-intro_1", WIDTH / 2, HEIGHT / 2, WIDTH, HEIGHT)
noTint()
for k, v in ipairs(introFiles) do
tint(255, introData[k])
sprite(v, WIDTH / 2, HEIGHT / 2, WIDTH)
noTint()
end
elseif gotten >= needToGet then
lineCount()
ready = true
tween.stopAll()
tween(1, introData, {255, 0, 0, 0}, tween.easing.quadInOut, function()
readyForStatesDraw = true
tween.delay(1, function()
tween(1, introData, {255, 255, 0, 0}, tween.easing.quadInOut, function()
tween.delay(1, function()
tween(1, introData, {255, 255, 255, 0}, tween.easing.quadInOut, function()
tween.delay(2, function()
tween(1, introData, {255, 255, 255, 255}, tween.easing.quadInOut, function()
tween.delay(2, function()
tween(1, introData, {0, 0, 0, 0}, tween.easing.quadInOut, function()
readyForStates = true
end)
end)
end)
end)
end)
end)
end)
end)
end)
end
pushStyle()
fill(32)
stroke(16, 128)
strokeWidth(8)
if isRecording() and showTouches and (CurrentTouch.state == BEGAN or CurrentTouch.state == MOVING) then
ellipse(CurrentTouch.x, CurrentTouch.y, 50, 50)
end
popStyle()
end
function touched(touch)
if readyForStates then
states[state]:touched(touch)
end
end
function keyboard(key)
if readyForStates then
states[state]:keyboard(key)
end
end
--# Menu
Menu = class()
function Menu:init()
self.bgSprites = {
readImage("Documents:DL-Asset-grass_full"),
readImage("Documents:DL-Asset-rock"),
readImage("Documents:DL-Asset-mushroom_red"),
readImage("Documents:DL-Asset-grass_full"),
readImage("Documents:DL-Asset-spring_pushed"),
readImage("Platformer Art:Guy Look Right"),
readImage("Documents:DL-Asset-grass_full"),
readImage("Platformer Art:Mushroom"),
}
self.offsets = {
50,
85,
85,
50,
75,
90,
50,
85,
}
self.angleOffset = 0
self.data = {a = 0, b = 0}
self.tweened = {a = 0, b = 0}
self.tweens = {a = -1337, b = -1337}
end
function Menu:draw()
pushStyle()
pushMatrix()
background(255)
pushMatrix()
translate(WIDTH / 2, HEIGHT / 2 + 128)
rotate(self.angleOffset)
for k, v in ipairs(self.bgSprites) do
sprite(v, 0, self.offsets[k])
rotate(360 / #self.bgSprites)
end
if isRecording() then
self.angleOffset = self.angleOffset + 0.5
else
self.angleOffset = self.angleOffset + 0.5 * DeltaTime * 60
end
popMatrix()
fill(0)
fontSize(48)
font("Copperplate-Light")
text("FallDodge", WIDTH / 2, HEIGHT / 2)
fontSize(24)
fill(self.data.a)
text("Start", WIDTH / 2, HEIGHT / 2 - 96)
fill(self.data.b)
text("Highscores", WIDTH / 2, 96)
popMatrix()
popStyle()
end
function Menu:touched(touch)
local time = 0.25
pushStyle()
font("Copperplate-Light")
fontSize(24)
local w, h = textSize("Start")
if math.abs(WIDTH / 2 - touch.x) <= w and math.abs(HEIGHT / 2 - 96 - touch.y) <= h then
if touch.state == BEGAN or touch.state == MOVING then
if self.tweened.a == 0 then
if self.tweens.a ~= -1337 then
tween.stop(self.tweens.a)
end
self.tweens.a = tween(time, self.data, {a = 128})
self.tweened.a = 1
end
else
if self.tweened.a == 1 then
if self.tweens.a ~= -1337 then
tween.stop(self.tweens.a)
end
self.tweens.a = tween(time, self.data, {a = 0})
self.tweened.a = 0
state = 2
end
end
else
if self.tweens.a ~= -1337 and self.tweened.a == 1 then
tween.stop(self.tweens.a)
self.tweens.a = tween(time, self.data, {a = 0})
end
self.tweened.a = 0
end
local w, h = textSize("Highscores")
if math.abs(WIDTH / 2 - touch.x) <= w and math.abs(96 - touch.y) <= h then
if touch.state == BEGAN or touch.state == MOVING then
if self.tweened.b == 0 then
if self.tweens.b ~= -1337 then
tween.stop(self.tweens.b)
end
self.tweens.b = tween(time, self.data, {b = 128})
self.tweened.b = 1
end
else
if self.tweened.b == 1 then
if self.tweens.b ~= -1337 then
tween.stop(self.tweens.b)
end
self.tweens.b = tween(time, self.data, {b = 0})
self.tweened.b = 0
state = 4
end
end
else
if self.tweens.b ~= -1337 and self.tweened.b == 1 then
tween.stop(self.tweens.b)
self.tweens.b = tween(time, self.data, {b = 0})
end
self.tweened.b = 0
end
popStyle()
end
function Menu:keyboard(key)
end
--# Mushroom
Mushroom = class()
function Mushroom:init(game, x, y)
self.game = game
self.pos = vec2(x, y)
self.imgs = {
readImage("Platformer Art:Mushroom"),
readImage("Documents:DL-Asset-mushroom_red"),
}
self.img = self.imgs[math.random(1, #self.imgs)]
self.angle = 0
self:calcAngle()
self.bounceTime = 0
self.type = "mushroom"
end
function Mushroom:calcAngle()
if self.pos.x <= WIDTH / 2 then
self.angle = -90
else
self.angle = 90
end
end
function Mushroom:draw()
if math.abs(self.game.player.pos.y -self.pos.y) <= 70 and math.abs(self.game.player.pos.x -self.pos.x) <= 70 then
if self.bounceTime <= 30 then
self.bounceTime = self.bounceTime + 1
self.game.player.motY = self.game.player.motY - 1.4 --1.52
end
else
self.bounceTime = 0
end
pushStyle()
pushMatrix()
translate(self.pos.x, self.pos.y)
rotate(self.angle)
sprite(self.img)
popMatrix()
popStyle()
end
--# Player
Player = class()
function Player:init(game, x, y)
self.game = game
self.pos = vec2(x, y)
self.motX = 2
self.motY = 1
self.move = false
self.poses = {
readImage("Platformer Art:Guy Standing"),
readImage("Platformer Art:Guy Look Right"),
readImage("Platformer Art:Guy Jump"),
readImage("Documents:DL-Asset-hurt"),
readImage("Documents:DL-Asset-walk01"),
readImage("Documents:DL-Asset-walk02"),
readImage("Documents:DL-Asset-walk03"),
readImage("Documents:DL-Asset-walk04"),
readImage("Documents:DL-Asset-walk05"),
readImage("Documents:DL-Asset-walk06"),
readImage("Documents:DL-Asset-walk07"),
readImage("Documents:DL-Asset-walk08"),
readImage("Documents:DL-Asset-walk09"),
readImage("Documents:DL-Asset-walk10"),
readImage("Documents:DL-Asset-walk11"),
}
self.pose = 5
self.aestheticAngle = {a = 0}
self.tid = 0
self.t = {x = 0, y = 0, lastX = 0, lastY = 0, deltaX = 0, deltaY = 0, state = ENDED, id = -1}
self:lookScared()
self:loopNextWalkImg()
self.won = false
self.dir = 1
self.breakScared = false
self.breakWalk = false
self.onLedge = false
end
function Player:lookScared()
if not self.breakScared then
if self.pose == 3 then
self.pose = 4
tween.delay(2, function()
if self.pose == 4 then
self.pose = 3
end
end)
end
tween.delay(6 + math.random(0, 2), function()
self:lookScared()
end)
end
end
function Player:loopNextWalkImg()
if not self.breakWalk then
self:nextWalkImg()
tween.delay(0.1, function()
self:loopNextWalkImg()
end)
end
end
function Player:nextWalkImg()
if self.pose >= 5 then
self.pose = self.pose + 1
end
if self.pose == 16 then
self.pose = 5
end
end
function Player:draw()
if self.move and self.pos.y >= HEIGHT - 100 and not self.won then
self.won = true
game:win()
end
if self.t.id == self.tid and (self.t.state == BEGAN or self.t.state == MOVING) then
self.motX = 0.999 * self.motX + 0.001 * (self.t.x - self.pos.x)
end
if self.move then
if isRecording() then
if not self.onLedge then
self.motY = math.min(15, self.motY + 0.1)
self.pos.y = self.pos.y - self.motY
end
self.motX = math.max(-15, math.min(15, self.motX * 0.99))
self.pos.x = self.pos.x + self.motX
else
if not self.onLedge then
self.motY = math.min(15, self.motY + 0.1)
self.pos.y = self.pos.y - self.motY * DeltaTime * 60
end
self.motX = math.max(-15, math.min(15, self.motX * 0.99))
self.pos.x = self.pos.x + self.motX * DeltaTime * 60
end
self.pos.x = math.max(WIDTH * 0.2, math.min(WIDTH * 0.8, self.pos.x))
if self.pos.x == WIDTH * 0.2 or self.pos.x == WIDTH * 0.8 then
self.motX = self.motX / math.abs(self.motX) * 0.01
end
self.dir = self.motX / math.abs(self.motX)
end
self.game.offset.y = math.max(0, -self.pos.y + HEIGHT / 2)
pushStyle()
pushMatrix()
translate(self.pos.x, self.pos.y)
rotate(self.aestheticAngle.a)
sprite(self.poses[self.pose], 0, 0, self.dir * self.poses[self.pose].width, self.poses[self.pose].height)
popMatrix()
popStyle()
end
function Player:touched(touch)
if self.move then
if self.tid == 0 and touch.state == BEGAN then
self.tid = touch.id
self.t = touch
end
if touch.id == self.tid then
self.t = touch
end
if touch.id == self.tid and (touch.state == ENDED or touch.state == CANCELLED) then
self.tid = 0
end
end
end
--# RenderBG
RenderBG = class()
function RenderBG:init(game)
self.game = game
self.grass = readImage("Documents:DL-Asset-grass_full")
self.dirt = readImage("Documents:DL-Asset-dirt")
self.stone = readImage("Documents:DL-Asset-stone")
self.lavaTop = readImage("Documents:DL-Asset-lava_top")
self.lava = readImage("Documents:DL-Asset-lava_full")
self.objImgs = {
readImage("Platformer Art:Bush"),
readImage("Platformer Art:Fence Broken"),
readImage("Platformer Art:Fence"),
readImage("Platformer Art:Mushroom"),
readImage("Documents:DL-Asset-rock"),
}
self.objs = {}
for i = 1, math.random(30, 40) do
self.objs[i] = {x = math.random(), side = math.random(0, 1), img = math.random(1, #self.objImgs)}
end
local gdist = 200
self.bgMesh = mesh()
self.bgMesh.vertices = {
vec2(0, gdist), vec2(0, HEIGHT - gdist), vec2(WIDTH, HEIGHT - gdist),
vec2(0, gdist), vec2(WIDTH, gdist), vec2(WIDTH, HEIGHT - gdist),
}
self.bgMesh.colors = {
color(64), color(220, 255, 255), color(220, 255, 255),
color(64), color(64), color(220, 255, 255),
}
self.caveBg = mesh()
self.caveBg.vertices = {
vec2(0, -HEIGHT), vec2(0, gdist), vec2(WIDTH, gdist),
vec2(0, -HEIGHT), vec2(WIDTH, -HEIGHT), vec2(WIDTH, gdist),
}
self.caveBg.colors = {
color(64), color(64), color(64),
color(64), color(64), color(64),
}
end
function RenderBG:draw()
if self.game.offset.y < 200 then
background(220, 255, 255)
else
background(64)
end
--translate(0, -self.game.offset.y)
self.bgMesh:draw()
pushMatrix()
self.caveBg:draw()
popMatrix()
for x = 0, WIDTH * 0.2, 46 do
for y = math.floor(-self.game.offset.y / 46) * 46, math.floor(-self.game.offset.y / 46) * 46 + (HEIGHT - 145 + math.min(200, self.game.offset.y)), 46 do
if math.floor(y / 46) >= -8 then
sprite(self.dirt, x, y)
elseif math.floor(y / 46) == -256 then
sprite(self.lavaTop, x, y)
elseif math.floor(y / 46) <= -257 then
sprite(self.lava, x, y)
else
sprite(self.stone, x, y)
end
end
end
for x = 0, WIDTH * 0.2, 46 do
for y = math.floor(-self.game.offset.y / 46) * 46, math.floor(-self.game.offset.y / 46) * 46 + (HEIGHT - 145 + math.min(200, self.game.offset.y)), 46 do
if math.floor(y / 46) >= -8 then
sprite(self.dirt, WIDTH - x, y)
elseif math.floor(y / 46) == -256 then
sprite(self.lavaTop, WIDTH - x, y)
elseif math.floor(y / 46) <= -257 then
sprite(self.lava, WIDTH - x, y)
else
sprite(self.stone, WIDTH -x, y)
end
end
end
for x = 0, WIDTH, 46 do
for y = math.floor(-self.game.offset.y / 46) * 46, math.floor(-self.game.offset.y / 46) * 46 + (HEIGHT - 145 + math.min(200, self.game.offset.y)), 46 do
if math.floor(y / 46) == -256 then
sprite(self.lavaTop, x, y)
elseif math.floor(y / 46) <= -257 then
sprite(self.lava, x, y)
end
end
end
for x = 0, WIDTH * 0.2, 46 do
sprite(self.grass, x, HEIGHT - 170)
end
for x = 0, WIDTH * 0.2, 46 do
sprite(self.grass, WIDTH - x, HEIGHT - 170)
end
for k, v in ipairs(self.objs) do
sprite(self.objImgs[v.img], v.side * WIDTH * 0.85 + v.x * WIDTH * 0.15, HEIGHT - 100)
end
end
--# Replay
Replay = class()
function Replay:init()
self.bgSprites = {
readImage("Documents:DL-Asset-grass_full"),
readImage("Documents:DL-Asset-rock"),
readImage("Documents:DL-Asset-mushroom_red"),
readImage("Documents:DL-Asset-grass_full"),
readImage("Documents:DL-Asset-spring_pushed"),
readImage("Platformer Art:Guy Look Right"),
readImage("Documents:DL-Asset-grass_full"),
readImage("Platformer Art:Mushroom"),
}
self.offsets = {
50,
85,
85,
50,
75,
90,
50,
85,
}
self.angleOffset = 0
self.data = {a = 0, b = 0}
self.tweened = {a = 0, b = 0}
self.tweens = {a = -1337, b = -1337}
end
function Replay:draw()
pushStyle()
pushMatrix()
background(255)
pushMatrix()
translate(WIDTH / 2, HEIGHT / 2 + 196)
rotate(self.angleOffset)
for k, v in ipairs(self.bgSprites) do
sprite(v, 0, self.offsets[k])
rotate(360 / #self.bgSprites)
end
if isRecording() then
self.angleOffset = self.angleOffset + 0.5
else
self.angleOffset = self.angleOffset + 0.5 * DeltaTime * 60
end
popMatrix()
fill(0)
fontSize(48)
font("Copperplate-Light")
text("YOU WON", WIDTH / 2, HEIGHT / 2 + 96)
text("YOUR SCORE: " .. string.format("%18.0f", math.floor(states[2].score)), WIDTH / 2, HEIGHT / 2)
fontSize(24)
fill(self.data.a)
text("Replay", WIDTH / 2, HEIGHT / 2 - 96)
fill(self.data.b)
text("Highscores", WIDTH / 2, 96)
popMatrix()
popStyle()
end
function Replay:touched(touch)
local time = 0.25
pushStyle()
font("Copperplate-Light")
fontSize(24)
local w, h = textSize("Replay")
if math.abs(WIDTH / 2 - touch.x) <= w and math.abs(HEIGHT / 2 - 96 - touch.y) <= h then
if touch.state == BEGAN or touch.state == MOVING then
if self.tweened.a == 0 then
if self.tweens.a ~= -1337 then
tween.stop(self.tweens.a)
end
self.tweens.a = tween(time, self.data, {a = 128})
self.tweened.a = 1
end
else
if self.tweened.a == 1 then
if self.tweens.a ~= -1337 then
tween.stop(self.tweens.a)
end
self.tweens.a = tween(time, self.data, {a = 0})
self.tweened.a = 0
state = 2
states[2].score = 0
end
end
else
if self.tweens.a ~= -1337 and self.tweened.a == 1 then
tween.stop(self.tweens.a)
self.tweens.a = tween(time, self.data, {a = 0})
end
self.tweened.a = 0
end
local w, h = textSize("Highscores")
if math.abs(WIDTH / 2 - touch.x) <= w and math.abs(96 - touch.y) <= h then
if touch.state == BEGAN or touch.state == MOVING then
if self.tweened.b == 0 then
if self.tweens.b ~= -1337 then
tween.stop(self.tweens.b)
end
self.tweens.b = tween(time, self.data, {b = 128})
self.tweened.b = 1
end
else
if self.tweened.b == 1 then
if self.tweens.b ~= -1337 then
tween.stop(self.tweens.b)
end
self.tweens.b = tween(time, self.data, {b = 0})
self.tweened.b = 0
state = 4
end
end
else
if self.tweens.b ~= -1337 and self.tweened.b == 1 then
tween.stop(self.tweens.b)
self.tweens.b = tween(time, self.data, {b = 0})
end
self.tweened.b = 0
end
popStyle()
end
function Replay:keyboard(key)
end
--# Spring
Spring = class()
function Spring:init(game, x, y)
self.game = game
self.pos = vec2(x, y)
self.imgs = {
readImage("Documents:DL-Asset-spring_pushed"),
readImage("Documents:DL-Asset-spring_popped"),
}
self.baseImg = readImage("Documents:DL-Asset-stone_ledge_left")
self.pose = 1
self.img = self.imgs[self.pose]
self.dir = 1
self:calcDir()
self.bounceTime = 0
self.type = "spring"
end
function Spring:calcDir()
if self.pos.x <= WIDTH / 2 then
self.dir = 1
else
self.dir = -1
end
end
function Spring:draw()
if math.abs(self.game.player.pos.y -self.pos.y) <= 70 and math.abs(self.game.player.pos.x -self.pos.x) <= 70 then
if self.bounceTime <= 20 then
self.bounceTime = self.bounceTime + 1
self.game.player.motY = self.game.player.motY - 2.55 --1.52
self.pose = 2
end
if self.game.player.pos.y < self.pos.y - 20 then
self.game.player.motY = -self.game.player.motY * 0.5
self.game.player.pos.y = self.game.player.pos.y - 5
self.pose = 1
end
else
self.pose = 1
self.bounceTime = 0
end
pushStyle()
pushMatrix()
self.img = self.imgs[self.pose]
translate(self.pos.x, self.pos.y)
sprite(self.img)
translate(0, -70)
sprite(self.baseImg, 0, 0, self.dir * self.baseImg.width, self.baseImg.height)
popMatrix()
popStyle()
end
--# Util
function lineCount()
local lines = 0
for k, v in ipairs(listProjectTabs()) do
for i in (readProjectTab(v) .. "\n"):gmatch("(.-)\n") do
lines = lines + 1
end
end
print("Total lines of code: " .. string.format("%.f", lines))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment