flux: A fast, lightweight tweening library

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: flux: A fast, lightweight tweening library

Post by kikito »

This library is really nagging me to update tween.lua.

But I must resist. Not ... yet.
When I write def I mean function.
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: flux: A fast, lightweight tweening library

Post by Jasoco »

Do it. Create a better competitor so you two can fight over who reigns over the Löve animation library universe.

But keep them fairly interchangeable so when I decide to dump one of them for the other I don't have to do much recoding.
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

Re: flux: A fast, lightweight tweening library

Post by Ranguna259 »

Don't forget to help each other, competition is no fun when one side is trying to totaly crush the other ;)
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
rxi
Prole
Posts: 47
Joined: Sun Mar 02, 2014 10:22 pm

Re: flux: A fast, lightweight tweening library

Post by rxi »

Ranguna259 wrote:Love it and I have a suggestion, how about an onupdatebefore and an onupdateafter ? This would really come in handy for zooming as I need the value of a number before and after the tweening update.
I'd suggest just having a local in the scope of the function called "last" and setting the current value to that at the end of the onupdate() function. I'm not convinced there would be much benefit to having onupdatebefore/after functions.

Code: Select all

local t = { x = 20 }
local last = t.x
flux.to(t, 5, { x = 30 }):onupdate(
  function()
    print("last:", last)
    print("current:", t.x)
    last = t.x
  end)
Let me know if this isn't what you meant!
Jasoco wrote:Do it. Create a better competitor so you two can fight over who reigns over the Löve animation library universe.
Not just Löve, both flux and tween.lua don't depend on any part of Löve and work wherever Lua is available. I completely agree with the sentiment, though, improvements to either library will no doubt encourage the other. I'm also glad with how much the two libraries differ, in that there isn't too much overlap in things, despite them aiming for the same goal.
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

Re: flux: A fast, lightweight tweening library

Post by Ranguna259 »

That wouldn't work because the first time onupdate() ran then the variable last would be nil, you don't have to add the onupdatebefore if you don't want, I've already edited your code so that it works the way I want it :)

Here's the modified code, I just added the onupdatebefore function to the tween table:

Code: Select all

--
-- flux
--
-- Copyright (c) 2014, rxi
--
-- 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.2" }
flux.__index = flux

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

local easing = {
  quad = "p * p",
  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)
  local load = loadstring or load
  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)
    if type(x) ~= "function" and not getmetatable(x).__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,
                         "bad easing type '$x'")
tween.delay = makesetter("_delay",
                         function(x) return type(x) == "number" end,
                         "bad delay time; expected number")
tween.onstart = makefsetter("_onstart")
tween.onupdate = makefsetter("_onupdate")
tween.onupdatebefore = makefsetter("_onupdatebefore")
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._ease = "quadout"
  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
  self:oncomplete(function() flux.add(self.parent, t) end)
  return t
end



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


function flux:to(obj, time, vars)
  return flux.add(self, tween.new(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
      if t._onupdatebefore then t._onupdatebefore() 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


function flux:add(tween)
  -- Add to object table, create table if it does not exist
  local obj = tween.obj
  self[obj] = self[obj] or {}
  self[obj][tween] = true
  -- Add to array
  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 pairs(self) do
    if v == x then
      return flux.remove(self, i)
    end
  end
end



local bound = {
  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(bound, flux)

return bound
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
rxi
Prole
Posts: 47
Joined: Sun Mar 02, 2014 10:22 pm

Re: flux: A fast, lightweight tweening library

Post by rxi »

Ranguna259 wrote:That wouldn't work because the first time onupdate() ran then the variable last would be nil...
Huh? No it wouldn't. Check my code snippet again. This is the output I get from it:

Code: Select all

$ love .
last:	20
current:	21.60944
last:	21.60944
current:	22.8732636
last:	22.8732636
current:	22.9574336
last:	22.9574336
current:	23.06111
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

Re: flux: A fast, lightweight tweening library

Post by Ranguna259 »

Oh right, you define last before you call flux.to, yeah that'd work, it becomes kind of messy but it'd work :P
Thanks :awesome:
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
User avatar
substitute541
Party member
Posts: 484
Joined: Fri Aug 24, 2012 9:04 am
Location: Southern Leyte, Visayas, Philippines
Contact:

Re: flux: A fast, lightweight tweening library

Post by substitute541 »

Currently using tween.lua for my game but I *might* move to flux in the event I make huge complex tweens.

Also, this reminds me of a Java Tweening library I used in LibGDX before. They look pretty similar.
Currently designing themes for WordPress.

Sometimes lurks around the forum.
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

Re: flux: A fast, lightweight tweening library

Post by Ranguna259 »

How do you remove tweens ?
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
rxi
Prole
Posts: 47
Joined: Sun Mar 02, 2014 10:22 pm

Re: flux: A fast, lightweight tweening library

Post by rxi »

Ranguna259 wrote:How do you remove tweens ?
Already went over this in an earlier reply. Haven't added it to the documentation yet as I was possibly going to add a different way of doing it.
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests