Page 5 of 5

Re: flux: A fast, lightweight tweening library

Posted: Tue Jun 03, 2014 6:31 pm
by bdjnk
Hey rxi,

First, I just want to say, this is a phonomenal library. I did however run into one difficulty (which I've resolved) that I thought should perhaps be addressed in the library itself. The source of my trouble seems to be the inability to check if tweens are applied to an object (and how many).

Maybe some code will clarify. I had to write the following function:

Code: Select all

function tweenit(obj, vars)
        obj.tc = obj.tc + 1
        if obj.tween == nil then
                obj.tween = flux.to(obj, 0.2, vars)
                        :ease("linear"):oncomplete(
                                function()
                                        obj.tc = obj.tc - 1
                                        if obj.tc == 0 then
                                                obj.tween = nil
                                        end
                                end)
        else
        obj.tween = obj.tween:after(obj, 0.2, vars)
                :ease("linear"):oncomplete(
                                function()
                                        obj.tc = obj.tc - 1
                                        if obj.tc == 0 then
                                                obj.tween = nil
                                        end
                                end)
        end
end
This allowed me to respond to user input and either create a new tween chain, or add to an existing one, as appropriate. Basically, I don't know if the user is making additional moves (asking for more tweens) before the previous tweens are complete, or after.

I feel like I'm explaining this badly. See the attached love file.

Also, there may be entirely different ways (easier and more sensible ways even) of solving this issue. I just know that none of the more simplistic paths I explored worked.

Re: flux: A fast, lightweight tweening library

Posted: Thu Jun 05, 2014 4:48 pm
by rxi
bdjnk wrote:[...] The source of my trouble seems to be the inability to check if tweens are applied to an object (and how many).
I had a look at the code example you posted and the .love file and I'm still a little hazy on what exactly you're trying to do.

I think some of the issue may be your massive amount of spaces in your indentation making any nesting seeming worse than it is, you also repeat the callback function. A possibly neater way the code could have been written is as follows:

Code: Select all

function tweenit(obj, vars)
  obj.tc = obj.tc + 1
  local oncomplete = function()
    obj.tc = obj.tc - 1
    if obj.tc == 0 then
      obj.tween = nil
    end
  end
  if obj.tween then
    obj.tween = obj.tween:after(obj, 0.2, vars)
      :ease("linear")
      :oncomplete(oncomplete)
  else
    obj.tween = flux.to(obj, 0.2, vars)
      :ease("linear")
      :oncomplete(oncomplete)
  end
end
I didn't test this code so it may have a mistake, but hopefully you get the gist of it.

I'm not entirely sure how useful the information of how many tweens are active on an object would be. For example, if you create a tween then create a new tween on the same fields of the same object such as to override the original tween, the original tween still exists for the sake of its onupdate() and oncomplete() functions. You would have two tweens but only one would actually be doing anything. Would you want the library to report the count as 2, or just as 1? Would you want it to report delayed tweens? What if you decide to tween another parameter of the object in a different part of the code -- this would break any reliance you had on the library's tween count for that object. As I said, I'm unsure what the circumstance is where this information is useful.

Would you be able to provide another (or more) examples of the issue, ideally isolating the problem into a single self-contained program which does nothing but demonstrates the problem? I don't think I'm going to be able to help you otherwise.

Thanks!

Re: flux: A fast, lightweight tweening library

Posted: Thu Jun 12, 2014 4:49 pm
by bdjnk
rxi wrote:I'm not entirely sure how useful the information of how many tweens are active on an object would be. For example, if you create a tween then create a new tween on the same fields of the same object such as to override the original tween, the original tween still exists for the sake of its onupdate() and oncomplete() functions. You would have two tweens but only one would actually be doing anything. Would you want the library to report the count as 2, or just as 1? Would you want it to report delayed tweens? What if you decide to tween another parameter of the object in a different part of the code -- this would break any reliance you had on the library's tween count for that object. As I said, I'm unsure what the circumstance is where this information is useful.
Sorry for the delay. I may have misled you by saying I wanted a way to determine the number of tweens on an object. What I actually want is to :after() if a tween is in progress, and to flux.to() if one isn't yet.

Attached is a .love that illustrates the issue I'm having (spacebar toggles the bad/good modes, movement is controlled with the number pad). In bad mode I can end up at any position because each number pad press overwrites the previous tween using the current x, y coordinates, while in non-bad mode I can only ever end up on a multiple of 100 because each tween completes before the next begins.

The code is short, so here it is, with reasonable spacing (sorry about before, I use tabs and the formatting got iffy coming in from vim).

Code: Select all

local flux = require "flux"

function love.load()
  me = {x = 100, y = 100, px = 1, py = 1, t = nil, c = 0}
  bad = false
end

function love.update(dt)
  flux.update(dt)
end

local function dotween(dx, dy)
  me.px = me.px+dx me.py = me.py+dy
  if bad then flux.to(me, 0.5, {x = me.x+100*dx, y = me.y+100*dy})
  else
    me.c = me.c + 1
    me.t = me.t == nil and flux.to(me, 0.5, {x = me.px*100, y = me.py*100}):oncomplete(function() me.c = me.c - 1 if me.c == 0 then me.t = nil end end)
      or me.t:after(me, 0.5, {x = me.px*100, y = me.py*100}):oncomplete(function() me.c = me.c - 1 if me.c == 0 then me.t = nil end end)
  end
end

function love.keyreleased(key)
  if key == " " then bad = not bad
  elseif key == "kp1" then dotween(-1,  1)
  elseif key == "kp2" then dotween( 0,  1)
  elseif key == "kp3" then dotween( 1,  1)
  elseif key == "kp4" then dotween(-1,  0)
  elseif key == "kp6" then dotween( 1,  0)
  elseif key == "kp7" then dotween(-1, -1)
  elseif key == "kp8" then dotween( 0, -1)
  elseif key == "kp9" then dotween( 1, -1)
  end
end

function love.draw()
  love.graphics.rectangle("fill", me.x, me.y, 50, 50)
  love.graphics.print("me.x = "..me.x.."\nme.y = "..me.y.."\nme.c = "..me.c.."\nbad = "..tostring(bad), 10, 10)
end