# TIC-80

tiny computer for making, playing and sharing tiny games · By Nesbox

# I have connected a tweening library Flux to the TIC-80 :)

A topic by alrado created Mar 07, 2017 Views: 286
Viewing posts 1 to 1

A fast, lightweight tweening library for Lua with easing functions and the ability to group tweens together.

The github page for flux is over here.

```-- title:  Tween demo
-- desc:   simple tween demo
-- script: lua

-- flux
-- This library is free software; you can redistribute it and/or modify it
-- under the terms of the MIT license. See LICENSE for details.

local flux = { _version = "0.1.5" }
flux.__index = flux

flux.tweens = {}
flux.easing = { linear = function(p) return p end }

local easing = {
cubic   = "p * p * p",
quart   = "p * p * p * p",
quint   = "p * p * p * p * p",
expo    = "2 ^ (10 * (p - 1))",
sine    = "-math.cos(p * (math.pi * .5)) + 1",
circ    = "-(math.sqrt(1 - (p * p)) - 1)",
back    = "p * p * (2.7 * p - 1.7)",
elastic = "-(2^(10 * (p - 1)) * math.sin((p - 1.075) * (math.pi * 2) / .3))"
}

local makefunc = function(str, expr)
return load("return function(p) " .. str:gsub("%\$e", expr) .. " end")()
end

for k, v in pairs(easing) do
flux.easing[k .. "in"] = makefunc("return \$e", v)
flux.easing[k .. "out"] = makefunc([[
p = 1 - p
return 1 - (\$e)
]], v)
flux.easing[k .. "inout"] = makefunc([[
p = p * 2
if p < 1 then
return .5 * (\$e)
else
p = 2 - p
return .5 * (1 - (\$e)) + .5
end
]], v)
end

local tween = {}
tween.__index = tween

local function makefsetter(field)
return function(self, x)
local mt = getmetatable(x)
if type(x) ~= "function" and not (mt and mt.__call) then
error("expected function or callable", 2)
end
local old = self[field]
self[field] = old and function() old() x() end or x
return self
end
end

local function makesetter(field, checkfn, errmsg)
return function(self, x)
if checkfn and not checkfn(x) then
error(errmsg:gsub("%\$x", tostring(x)), 2)
end
self[field] = x
return self
end
end

tween.ease  = makesetter("_ease",
function(x) return flux.easing[x] end,
tween.delay = makesetter("_delay",
function(x) return type(x) == "number" end,
tween.onstart     = makefsetter("_onstart")
tween.onupdate    = makefsetter("_onupdate")
tween.oncomplete  = makefsetter("_oncomplete")

function tween.new(obj, time, vars)
local self = setmetatable({}, tween)
self.obj = obj
self.rate = time > 0 and 1 / time or 0
self.progress = time > 0 and 0 or 1
self._delay = 0
self.vars = {}
for k, v in pairs(vars) do
if type(v) ~= "number" then
error("bad value for key '" .. k .. "'; expected number")
end
self.vars[k] = v
end
return self
end

function tween:init()
for k, v in pairs(self.vars) do
local x = self.obj[k]
if type(x) ~= "number" then
error("bad value on object key '" .. k .. "'; expected number")
end
self.vars[k] = { start = x, diff = v - x }
end
self.inited = true
end

function tween:after(...)
local t
if select("#", ...) == 2 then
t = tween.new(self.obj, ...)
else
t = tween.new(...)
end
t.parent = self.parent
return t
end

function tween:stop()
flux.remove(self.parent, self)
end

function flux.group()
return setmetatable({}, flux)
end

function flux:to(obj, time, vars)
end

function flux:update(deltatime)
for i = #self, 1, -1 do
local t = self[i]
if t._delay > 0 then
t._delay = t._delay - deltatime
else
if not t.inited then
flux.clear(self, t.obj, t.vars)
t:init()
end
if t._onstart then
t._onstart()
t._onstart = nil
end
t.progress = t.progress + t.rate * deltatime
local p = t.progress
local x = p >= 1 and 1 or flux.easing[t._ease](p)
for k, v in pairs(t.vars) do
t.obj[k] = v.start + x * v.diff
end
if t._onupdate then t._onupdate() end
if p >= 1 then
flux.remove(self, i)
if t._oncomplete then t._oncomplete() end
end
end
end
end

function flux:clear(obj, vars)
for t in pairs(self[obj]) do
if t.inited then
for k in pairs(vars) do t.vars[k] = nil end
end
end
end

-- Add to object table, create table if it does not exist
local obj = tween.obj
self[obj] = self[obj] or {}
self[obj][tween] = true
table.insert(self, tween)
tween.parent = self
return tween
end

function flux:remove(x)
if type(x) == "number" then
-- Remove from object table, destroy table if it is empty
local obj = self[x].obj
self[obj][self[x]] = nil
if not next(self[obj]) then self[obj] = nil end
-- Remove from array
self[x] = self[#self]
return table.remove(self)
end
for i, v in ipairs(self) do
if v == x then
return flux.remove(self, i)
end
end
end

local Tween = {
to      = function(...) return flux.to(flux.tweens, ...) end,
update  = function(...) return flux.update(flux.tweens, ...) end,
remove  = function(...) return flux.remove(flux.tweens, ...) end,
}
setmetatable(Tween, flux)

-------------------------------------------------------------------
-- demo code
"quartinout", "quintin", "quintout", "quintinout", "expoin", "expoout", "expoinout", "sinein", "sineout", "sineinout",
"circin", "circout", "circinout", "backin", "backout", "backinout"}

TIME=1500
START_Y=15
FINISH_Y=50
START_COLOR=0
FINISH_COLOR=15
DELAY=500

local lastTime=0
local counter=0
local easeType = TYPES[counter]
local tween=nil

logo={
x=104,
y=START_Y,
color=START_COLOR,
msg="easing type: ",
easeType="",
draw = function ()
spr(1+(time()%1000)/500,logo.x,logo.y,-1,4)
local fullMsg=counter..". "..logo.msg..logo.easeType
local msgX=(240-print(fullMsg,-100,-100))/2
print(fullMsg,msgX,136-logo.y,logo.color)
end
}

function startTween()
if(tween ~=nil) then tween:stop() end
counter = counter+1
counter = counter>#TYPES and 1 or counter
easeType = TYPES[counter]
logo.easeType = easeType
tween=Tween.to(logo,TIME,{y=FINISH_Y,color=FINISH_COLOR}):ease(easeType):onupdate(logo.draw):delay(DELAY)
:after(logo,TIME,{y=START_Y,color=START_COLOR}):ease(easeType):onupdate(logo.draw):oncomplete(startTween)
end

startTween()

function TIC()
cls(12)
poke(0x3FF8,logo.color)
print("Flux - tweening library",55,4,logo.color)

Tween.update(time()-lastTime)
lastTime=time()
end

```