Skip to content

Instantly share code, notes, and snippets.

@s-ol
Last active March 13, 2017 16:21
Show Gist options
  • Save s-ol/29843be42096d28d0fdc056f91116825 to your computer and use it in GitHub Desktop.
Save s-ol/29843be42096d28d0fdc056f91116825 to your computer and use it in GitHub Desktop.
Simple Loop Template
local lg, fs = love.graphics, love.filesystem
local DemoLoop = {}
DemoLoop.__index = DemoLoop
function DemoLoop.new()
local self = setmetatable({}, DemoLoop)
lg.setBackgroundColor(0, 0, 0, 0)
self.time = 0
return self
end
function DemoLoop:update(dt)
self.time = self.time + dt
if self.length and self.time > self.length then
self.time = self.time - self.length
return true
end
end
function DemoLoop:render(fps, dirname, overwrite)
if not fps then fps = 60 end
if not dirname then dirname = 'UnnamedLoop' end
fs.setIdentity "demöloop"
if overwrite then
for _, file in ipairs(fs.getDirectoryItems(dirname)) do
fs.remove(dirname .. "/" .. file)
end
fs.remove(dirname)
else
while fs.exists(dirname) do
dirname = dirname .. "_"
end
end
local dt = 1/fps
local fmt = dirname .. "/%06d.png"
fs.createDirectory(dirname)
print(fs.getSaveDirectory() .. "/" .. dirname)
function love.run()
local frame = 0
while true do
love.event.pump()
for name, a,b,c,d,e,f in love.event.poll() do
if name == "quit" then return end
love.handlers[name](a,b,c,d,e,f)
end
if self:update(dt) then break end
lg.clear(lg.getBackgroundColor())
lg.origin()
self:draw()
lg.newScreenshot(true):encode("png", fmt:format(frame))
lg.present()
frame = frame + 1
end
end
end
function DemoLoop:run()
function love.draw(...) return self:draw(...) end
function love.update(...) return self:update(...) end
end
return DemoLoop
local DemoLoop = require("demoloop")
local hsl2rgb -- define this function!
local TwistedLua = setmetatable({}, DemoLoop)
TwistedLua.__index = TwistedLua
function TwistedLua.new()
local self = setmetatable(DemoLoop.new(), TwistedLua)
love.math.setRandomSeed(21)
self.background = { hsl2rgb(love.math.random(), love.math.random()/3+.2, love.math.random()/4) }
love.graphics.setBackgroundColor(self.background)
hue = love.math.random()
self.shades = setmetatable({}, {
__index = function (shades, key)
local val = { hsl2rgb(hue, .7, key * .3 + .1) }
rawset(shades, key, val)
return val
end
})
self.length = math.pi*4
return self
end
function TwistedLua:draw()
width, height = love.graphics.getDimensions()
love.graphics.translate(width/2, height/2 + 70)
function draw(i)
love.graphics.push()
love.graphics.translate(0, -120*i)
love.graphics.scale(1, 0.5)
love.graphics.scale(1 - 0.1 * math.sin(self.time + i*2))
love.graphics.scale(0.8 - i * .4 * math.cos(self.time))
love.graphics.rotate(self.time/4)
love.graphics.rotate(i * .6 * math.cos(self.time))
love.graphics.setColor(self.shades[i])
love.graphics.rectangle("fill", -80, -80, 160, 160)
love.graphics.pop()
end
for i=0,1,1/(20 + 19 * math.sin(self.time / 2)) do
draw(i)
end
draw(1)
end
return TwistedLua
local i, loop = 2
while true do
local a = arg[i]
if not a then break end
local flag = a:match "^%-%-(.*)$"
if flag then
if flag == "debug" or flag == "render" then
_G[string.upper(flag)] = true
else
_G[flag] = arg[i+1]
i = i + 1
end
elseif a ~= "." then
loop = a
for n=i,1,-1 do table.remove(arg, n) end
break
end
i = i + 1
end
if not loop then
print("ERROR: no loop specified")
print("usage: love . [--FLAG] [--OPTION VALUE] <loop> ...")
print("","global options: fps, output, overwrite")
print("","global flags: debug, render")
love.event.push "quit"
else
package.path = "./?/init.lua;" .. package.path
local _, Loop = pcall(require, loop)
if not _ then
print("ERROR: failed to require loop")
print("", Loop)
love.event.push "quit"
return
end
local _
if Loop.new then
_, loop = pcall(Loop.new)
else
_, loop = pcall(Loop)
end
if not _ then
print("ERROR: failed to instantiate Loop")
print("implement either .__call or .new")
print("(or return a function)")
print("", loop)
love.event.push "quit"
return
end
if RENDER then
loop:render(fps, output, not no_overwrite)
else
loop:run()
end
end
#!/bin/sh
export MAGICK_TMPDIR="."
render() {
loop=`basename $1 .moon`
if [[ $loop == "demoloop" ]]; then
continue
fi
out=`love . --render --fps 30 --no_overwrite 1 "${@:2}" $loop`
echo retrieving files from $out
mkdir -p gifs
wd=`pwd`
pushd $out &> /dev/null # apparently having the filenames long breaks stuff?
convert -delay 3 -dispose Background *.png $wd/gifs/$loop.gif # either render as a gif
ffmpeg -y -v warning -framerate 30 -i '%06d.png' -crf 0 $wd/gifs/$loop.mp4 # or as a video
# (or both)
popd &> /dev/null
echo rendered gifs/$loop.gif
}
if [[ $1 == "all" ]]; then
for loop in *.moon; do
[[ "$loop" = demoloop.moon ]] && continue
render `basename $loop .moon`
done
elif [[ -n $1 ]]; then
render "$@"
else
echo "usage: '$(basename $0) <loop>' or '$(basename $0) all'"
exit 1
fi

Running

Run a loop in a file loep.lua with

 $ love . loep

Rendering

Render it with

$ ./render.sh loep

Writing

A loop can implement :draw() and :update(dt). A value self.time is incremented by dt automatically in DemoLoop:update so you can just use that to render with. Set a Loop.length or self.length to make it wrap around during render after that many seconds (see example).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment