Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Writing our own Tween easing (and looping?) functions

edited February 2015 in Questions Posts: 2,020

I just noticed on the wiki page for Codea's Tween API that we can write our own easing functions for Tween.

This is the template from the wiki page:

-- t is the current time -- d is the duration of the animation -- b is the initial animated value -- c is the change in the animated value by the end of the animation function myEasing(t, b, c, d) local result ... -- Code to calculate result return result end

It seems to be fairly close to this:

What I wanted to ask is, would it also be possible to write a tween looping function in a similar way? Specifically I would like to write a pingpong.once function. If so, what would the template look like? (It'd be great if we could see the source for the existing pingpong function, assuming it is implemented in Lua)



  • Jmv38Jmv38 Mod
    Posts: 3,297

    i know it is not exactly what you ask for, but just in case you only need a pingpong once function, try this:

    -- pingpongOnce
    -- Use this function to perform your initial setup
    function setup()
        a = {x=100,y=100,w=50,h=50}
        pingpongOnce(2, a, {x=300} )
    function pingpongOnce(time, subject, target,...)
        local back = {}
        for k,v in pairs(target) do back[k] = subject[k] end
        tween(time, subject, target,...)
        local arg = arg or {}
        tween.delay(time,function() tween(time, subject, back,unpack(arg)) 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
        -- Do your drawing here
        rect(a.x, a.y, a.w, a.h)
  • edited February 2015 Posts: 2,020

    @Jmv38 Wow, that is very clever.


    Thank you!

  • dave1707dave1707 Mod
    Posts: 9,725

    This is easier for me to understand and does the same thing.

    function setup() p1={x=50,y=50} p2={x=400,y=600} p3={x=50,y=50} rec={x=50,y=50,w=50,h=50} tween1() end function tween1() tween.path(5,rec,{p1,p2,p3}) end function draw() background(40, 40, 50) fill(255) rect(rec.x,rec.y,rec.w,rec.h) end
  • Jmv38Jmv38 Mod
    Posts: 3,297

    i agree

  • dave1707dave1707 Mod
    Posts: 9,725

    @Jmv38 Actually, it can be shortened by eliminating p3 and just reusing p1 in the tween.path since we're going back to the starting point.

    function setup() p1={x=50,y=50} p2={x=400,y=600} rec={x=50,y=50,w=50,h=50} tween1() end function tween1() tween.path(5,rec,{p1,p2,p1}) end function draw() background(40, 40, 50) fill(255) rect(rec.x,rec.y,rec.w,rec.h) end
  • Posts: 2,020

    @dave1707 I keep forgetting about tween.path... I'm experimenting with it now. Although maybe a tween.sequence might be closer to a pingpong.once as path adds a spline

  • Posts: 2,020

    This is slightly off-topic, but one thing that I think is odd about tweens is that when they're called as part of a class, and you want the callback to be a function of that class, you have to wrap it in an anonymous function. ie:

    tween(1, self, {pos=newpos}, tween.easing.SineInOut, self:myFunction()) --the function is called immediately, rather than after the tween
    tween(1, self, {pos=newpos}, tween.easing.SineInOut, self.myFunction(self)) --ditto
    tween(1, self, {pos=newpos}, tween.easing.SineInOut, self.myFunction) --function is called at the right time, but doesn't have access to self, returns an error if self is called
    tween(1, self, {pos=newpos}, tween.easing.SineInOut, function() self:myFunction() end) --success! function must be wrapped in an anonymous function to execute properly

    It just seems slightly wasteful, given that advice on optimising Lua recommends not repeatedly creating closures:

    Or are repeated anonymous functions (ie you have lots of tweens firing at once) not such an issue performance wise? Am I worrying unnecessarily here?

  • SimeonSimeon Admin Mod
    Posts: 5,718

    @yojimbo2000 it's necessary in order to bind self to the function. If you wrote your function as a static method (i.e., no access to self) then you could just pass the function name.

  • Posts: 2,020

    @Simeon and is it possible to add our own looping functions, like we can with easing?

Sign In or Register to comment.