95. Tweens – what are they?
The word “tween” is short for in between, and comes from the early days of film animation. Skilled artists would draw the key pictures in a sequence, leaving gaps, and then copyists would draw the inbetween pictures, using the key pictures as a guide. This was known as tweening.
Tweens in Codea are very similar. They help you move stuff around the screen. You tell Code where you want to start and stop, and how to interpolate in between, and Codea handles all the calculations from there.
But you should be very clear that tweens don’t draw your objects for you, and they don’t animate anything. They only calculate interpolated values between a start and an end value.
Basic tween
So let’s take a very basic tween. Suppose we want to move a circle from (x1,y1) to (x2,y2) over a period of s seconds.
We could do it ourselves, by putting code into the draw function to calculate how long we have been moving, and interpolating between x1 and x2, and y1 and y2.
But this is how you do it with a tween..
function setup() pos=vec2(100,150) --starting position x2,y2=400,300 --ending position tween(5,pos,{x=x2,y=y2}) --define tween end function draw() background(40, 40, 50) fill(200) ellipse(pos.x,pos.y,100) --x,y are calculated for you end
Basically, the tween does all the calculations of x and y for you, so all you need to do is draw the circle. A simple tween takes three parameters
- the number of seconds
- a table of variables to interpolate
- a table of end values for the variables
.
So in the example above, we have asked the tween to move from x=100 y=150, to x=400 y=300, over a period of 5 seconds. This means that all we need to do in the draw function, is to actually draw the ellipse using the x and y values in the pos table, because the tween will keep adjusting them until they reach the end values.
So tweens are like little scripts or macros, that handle the messy interpolations for you. They don’t actually draw objects on the screen, however. They interpolate values, that is all.
If I just wanted to animate the x value and keep the y value the same, I could write
tween(5,pos,{x=x2}) --define tween
Note that while pos actually has two values, x and y, the tween is told to only animate the x value. So what it does is take the list of end values (the third parameter), and look for those items in the list of variables (the second parameter), ignoring any variables that don’t have an end value.
The documentation (here is pretty detailed, and it has a good example, too, part of which I’ve copied below.
--first define a table of details to animate box = { x = 10, y = 10, width = 20, height = 20, fillColor = color(255) } --the first tween interpolates x and y tween(1, box, {x = 100, y = 100}) --this tween interpolates the colour tween(1, box, {fillColor = color(255,0,0)})
See how a table called box is defined, with a lot of items. Then the first tween interpolates just the x and y items in box (because ending values are only given for x and y). The second tween only has ending values for the colour, so only the colour will be interpolated.
Easing options
Normally, you would move smoothly between two points. But tweens give you other options. You can add a fourth parameter to your tween, which tells the tween how to interpolate. All of these options have the prefix tween.easing.
Easing? What is that?
Easing is an animation term that describes how the animation starts (and maybe ends).
Easing in – the animation starts slowly and speeds up
Easing out – the animation starts quickly and slows down
If you look at the documentation, you’ll see quite a number of easing options. The first is linear, which is just a straight line interpolation.
Then there are three Quad (for Quadratic) easing options, one In, one Out, and one OutIn. If you try them, you’ll see that In starts slowy, Out starts fast, and OutIn starts fast, slows and then speeds up again (why would you want this one? I don’t know).
After Quad, there are three Cubic, Quart and Quint options. What is this about? These control how fast the animation speeds up (or slows down). A quintic (Quint) curve is much steeper than a quadratic (Quad) curve, because it contains x^5 , so any change in x has a big impact on the y value. So a Quint easing will start off really slow and then really speed up fast. So all of these options just let you choose how slowly you start off.
I won’t go through all the options, but I will mention there are Bounce and Elastic options that will make the interpolated values bounce or wobble around. The best way to understand them is to try using them with a simple example like this
function setup() pos=vec2(100,150) --starting position tween(5,pos,{x=400,y=500},tween.easing.bounceIn) --define tween end function draw() background(220) ellipse(pos.x,pos.y,100) --x,y are calculated for you end
Looping
The Codea tween functions also allow you to repeat the animation loop. The default is to run the tween sequence just once, but you can also set it to repeat forever, or to go back and forwards forever (called pingpong for obvious reasons).
What I’m going to explain next will be a little confusing, so I’m going to give several examples to try to make it clearer. I’ll explain them all underneath
tween(5,pos,{x=400,y=500}) --1 tween(5,pos,{x=400,y=500},tween.easing.quadIn) --2 tween(5,pos,{x=400,y=500}, --3 {loop=tween.loop.pingpong,easing=tween.easing.quadIn}) tween(5,pos,{x=400,y=500}, --4 {loop=tween.loop.pingpong})
tween 1 is a simple tween which interpolates smoothly, in a straight line.
tween 2 has an easing that makes the interpolation slow at first, then faster. The easing parameter is added after the others.
tween 3 has the same easing, and also a pingpong loop, which means the interpolation will keep running forwards, then backwards, forever. However, note that the easing and loop items are in a little table instead of being separate. Why, I don’t know, but if you want to specify a loop, you need to put it in a table, and if you want to specify easing as well, then that has to go in the same table.
tween 4 has a loop but no easing. I just thought I’d show you in case you wondered. So a loop always has to be in a table, whereas an easing doesn’t need to be (unless there is a loop as well).
Sequences and paths
You can chain tweens together so they run one after another. You can also define a path that the tween should take, ie it doesn’t need to be in a straight line.
I won’t explain these because I think the documentation is clear enough, and if you need to use these, then you are hardly likely to need my help.
Callbacks (or what happens when the tween ends?)
Quite often, you will want something to happen when a tween ends – eg stop drawing whatever you have been moving, or something else. You can tell the tween to run a function when it finishes, and that function can then do whatever you want. Here is an example that will run the Finished function when the tween is done.
tween(5,pos,{x=400,y=500},tween.easing.quadIn,Finished())
You can also stop a tween, using an id provided when you define a tween, like so
id=tween(5,pos,{x=400,y=500},tween.easing.quadIn,Finished()) tween.stop(id)
Note – The documentation doesn’t include an option to restart where you left off, but there is one, called tween.play(id).
So what are tweens for?
Well, I guess that’s up to your imagination. They are clearly useful for repetitive movements, and for games where you want some bounce or wobble in the movement, or perhaps for things like flying sparks.
Thanks Ignatz!! I can finally use them to animate games.
Thanks Ignatz! I was really intimidated by Tweens before i read this tut. Btw, where is the documentation for chaining Tweens please? @.@
Yes, tweens aren’t so scary, they basically just do the math for you.
The documentation is here
http://twolivesleft.com/Codea/Reference/Animation.html#tween.sequence
Thanks a lot!
@Ignazt, Several functions contained in tween.lua are not present in the code editor. – tween.play(id) – tween.hasExpired(id) – tween.update(dt)
Thanks for that. These are not in the Codea documentation for tweens, though. I have tested tween.play, and it works. I’ve logged this as a documentation flaw.
😉 tween.hasExpired(id) return true or false
Why isn’t this working out??
function setup()
box = { x = 10}
tween(1, box, {x=WIDTH/2})
end
function draw()
background(0, 0, 0, 255)
fill(255, 0, 0, 255)
ellipse(x,HEIGHT/2,100) –or ellipse(box[1],HEIGHT/2,100)
end
Both of them don’t work.
It needs to be
ellipse(box.x, ……
ie box.x rather than x
Oh!! thanks.
When I run the example with the box table I get – error: [string “–tween.lua …”]:133: attempt to perform arithmetic on local ‘v’ (a userdata value).
I get the same thing when running the code in the codea reference example for Tweens.
That’s a bit puzzling, because from what I can see, your error is on line 133 – but there are fewer than 20 lines in the examples – and also, the examples don’t use v at all. Do you have other code as well?
If I just copy and paste the 8 lines of code in your example with the table called box into setup it gives me that error. I then thought well maybe I have to tell it to draw the rect based on the variables given. So I put in rect in the draw function using box.x and box.y and got the same error. So I tried putting it all in draw and still got the same error. If I copy the code out of the tween example in the codea referance section, I get the same error. It is pretty weird because at no time did I have more than a few lines of code. I’m sure I’m just missing something, being a complete beginner, but I know I don’t have anywhere near that many lines. Oh, and before I forget to say it I really love your blog, it is incredibly helpful and beautifully paced.
I’m not sure what’s happening, but it sounds as though you have other code as well as what you’re pasting.
Don’t copy the code into the existing setup function. Instead, delete ALL the code and then replace it with what you’re pasting in.
And thank you for the compliment. I guess it means that you and I learn at about the same pace 😉
It is so strange. This is everything in that project;
function setup()
box = { x = 10, y = 10,
width = 20, height = 20,
fillColor = color(255) }
tween(1, box, {x = 100, y = 100})
tween(1, box, {fillColor = color(255,0,0)})
end
There is nothing else, just these few lines. When I press play, I get the same message. I even deleted the function setup so that it only had the copied code in there and I get the same error.
I have the same problem as Circussmith. I tried what you said, and it won’t work. I am most likely even more of a beginner than him, but I grasp the concept.
Please help
You can’t tween a whole colour because it is an “object” – you have to tween the individual r,g,b elements. So instead of
box = { fillColor = color(255) }
tween(1, box, {fillColor = color(255,0,0)})
you need this
box = { r=255, g=255, b=255 }
tween(1, box, {g=0, b=0})
–and then put this in the draw function
fillColor = color(box.r, box.g, box.b )
So you can only tween numbers