Tween Question (Part Deux..)

Experimenting a bit more with the tween function and was wondering how this works ‘under the hood’.

a) How does Codea keep track of ‘active tweens’ during each update cycle? Is there an internal table of ‘TweenIds’ that are exposed and can be queried or is this something we have to keep track of ourselves?

b) If I stop a Tween animation before it completes with ‘tween.stop’ (e.g. a tweened sprite being hit and destroyed in a game) does this automatically get garbage collected at somepoint or do we have to force this to occur by setting the TweenId to ‘nil’? I’m trying to work out a best practice method for exiting a tween gracefully and cleaning up after itself, else I fear this simply keeps it in memory.

c) In respect to speed, has anyone done any benchmarks regarding a large number of multiple tweens running simultaneously?

Any thoughts? :smiley:

a) Codea keeps a table of active tweens which it updates internally. I believe the table is not exposed.

b) If you stop a tween — and no longer keep a reference to its ID in your code — it will be garbage collected.

c) Speed would be interesting to see. The tween library is entirely Lua based (we will be putting our tween.lua on Github so people can look at it and potentially make it better).

Hi @Simeon - thanks for this. :slight_smile:

I’m in the process of doing some speed tests with multiple tweens and seeing what the performance is like and will report back. Would be interesting to see the code for this at some point.

From its functionality, i suspect it’s likely to have to cover a lot of ground and might not be necessarily optimised for speed - but let’s see.

I did some FPS tests with multiple Tweens running for 10 seconds from the bottom of the screen to the top. I did 2 runs on each tween count. Here’s the results I got.


# Tweens           1st run   2nd run

  50              59.6375   59.9082   FPS
 100              53.0186   52.5563
 150              39.8047   40.5957
 200              33.2133   32.7913
 250              27.6686   28.0826
 300              23.8152   23.6842
 500              15.7165   15.4772
1000               8.6732    8.8125

Thanks @dave1707 , were these with Sprites or Meshes? Did a similar quick test last night (with meshes) and the performance was much better than these - around 60fps for a few hundred. I’ll re-run it again and post my timings.

.@dave1707 I did the test without any graphics — just N tweens running for 10 seconds, each one interpolating two values [x,y]. These were my results:


easing = tween.easing.linear

# Tweens                FPS
   50                    60
  100                    60
  500                    52
 1000                    28.5


easing = tween.easing.quadInOut

# Tweens                FPS
   50                    60
  100                    60
  500                    46.5
 1000                    26


easing = tween.easing.elasticInOut

# Tweens                FPS
   50                    60
  100                    60
  500                    36.5
 1000                    19.6

As you can see, the complexity of the easing function plays a big part.

Also note that interpolating a single value is faster than two values — 1000 elasticInOut tweens interpolating a single value gives me ~30 FPS on iPad 3.

@Simeon - I guess I can live without any of the easing functions for a lot of stuff, I guess the tween.lua lib does is a ‘simple drop through’ if it doesn’t detect an easing parameter. Whats the performance like on your test without any easing? I guess thats the best case scenario?

.@andymac3d no easing is the same as linear — it’s the simplest way for the tween library to interpolate between two values.

Most of the time you’d want something like quadInOut, which gives you smooth acceleration and deceleration. Elastic and bounce are good for making things pop and jump.

I wouldn’t hold back on using them, spawning 1000, or even 100 simultaneous tweens seems like a very unusual thing to do. Even 10 is quite a lot to instantiate simultaneously.

If you just use them where you need they will not have any performance penalty.

Yes, I guess 1000s are overkill! ;-). Just curious how far to push the hardware really when using tweens - I agree that significantly less will be more than sufficient for most things!

I am writing something that does use a fair few (>100) simultaneous animation events so I’m keen to see how this performs in practice in comparison to my…ahem… ‘less sophisticated’ animation lib.

I think I’ll be using tween from now on… :wink:

Here’s the program I used for my timings. The Tweens are mostly default values and the graphics simple. I changed this from my original a little to try and speed it up.


displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)

function setup()
    tab={}
    average=false
    tot=0
    count=0

    for z=1,50 do    -- change # of tweens, 50, 100, etc.
        table.insert(tab,{x=5*z,y=100})
        tween(10,tab[z],{x=5*z,y=900})
    end
end

function draw()
    background(40, 40, 50)
    fill(255)
    for z=1,#tab do
        ellipse(tab[z].x,tab[z].y,5)
    end
    if average then    -- show average FPS
        text(#tab.." Tweens          Average FPS  "..tot/count,300,1000)
    elseif #tab>0 and tab[1].y==900 then
        average=true
    else
        count = count + 1
        tot=tot+1/DeltaTime
    end
end