GTween for Corona

61 replies [Last post]
josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

I ported Grant Skinner's GTween to Lua for Corona:

https://github.com/joshtynjala/gtween.lua

If you feel that Corona transitions don't offer some important features, gtween.lua might provide what you're missing.

Note: See my list of gtween parameters and methods that transition doesn't provide.

Replies

ramonhelena
User offline. Last seen 42 weeks 10 hours ago. Offline
Joined: 10 Feb 2011

Really cool,

Gracias viejo por tu aporte!!

coderebelbase's picture
coderebelbase
User offline. Last seen 3 weeks 2 days ago. Offline
Joined: 1 Feb 2010

Awesome!

+1 for a Lua translation of TweenLite/TweenMax = )

mroberti's picture
mroberti
User offline. Last seen 1 day 4 hours ago. Offline
Joined: 20 Nov 2010

Hey pretty neat! Thanks a lot!

mroberti's picture
mroberti
User offline. Last seen 1 day 4 hours ago. Offline
Joined: 20 Nov 2010

How would I go about handling cleanup on gtween when switching between scenes using the Director class? I tried exposing the 'unregisterTween' function in gtween, then manually unregistering my images with tweens:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        local function Destroy(event)
                Runtime:removeEventListener( "enterFrame", Main )
                if(image1.tween.isPlaying == true)then
                        gtween:unregisterTween(image1.tween)
                end
                if(image2.tween.isPlaying == true)then
                        gtween:unregisterTween(image2.tween)
                end
                if(image3.tween.isPlaying == true)then
                        gtween:unregisterTween(image3.tween)
                end
                image1:removeSelf()
                image2:removeSelf()
                image3:removeSelf()
                director:changeScene("screen2","flip")
        end

but I get a bunch of:

"...sers\mroberti\DOCUME~1\CORONA~2\Sandbox\9\gtween.lua:229: attempt to
perform arithmetic on local 'rangeVal' (a nil value)
stack traceback:"
errors.

It's like the tweens live-on despite the unregistering?
Appreciate any help I can get.

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

Just call tween:pause(). That'll stop it from playing and also unregister it.

mroberti's picture
mroberti
User offline. Last seen 1 day 4 hours ago. Offline
Joined: 20 Nov 2010

Sweet! Thank you sir!

J. A. Whye's picture
J. A. Whye
User offline. Last seen 12 hours 39 min ago. Offline
Joined: 25 Sep 2010

Since I'm not a Flash dev I have no idea what GTween is -- could you give me/us a brief idea of what it gives us that transition.to doesn't?

I'm always looking for better/cooler ways to do things and I don't want to miss out simply because I don't know what GTween is. :)

Thanks.

Jay

PS - Okay, I just looked at the sample code a little more and see "reflect = true" is just an awesome addition, all by itself. Anything else that's a standout reason to use it? Tnx!

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

There are several extra capabilities in gtween that transition doesn't offer (correct me if I'm wrong about any of them). Remember, this is not a complete list of gtween's capabilities. It's just the things that transition can't do.

Here some parameters you can set:

repeatCount - Repeat the tween a specific number of times.

reflect - This will reverse the tween every time it repeats.

autoPlay - Set this to false, and the tween won't play until you call play()

nextTween - After this tween finishes, another one plays. Set autoPlay = false on all tweens that are considered "next".

onChange - A function that is called every time the animation updates (basically, every frame). I like to use this to synchronize the animation of several objects at once and only use a single tween to do it.

Here are some methods you can call on a gtween instance. Useful if you need to interrupt and override the regular behavior.

pause() - If the tween is playing, it will be paused. It may be resumed again later. Calling this will also allow the tween to be garbage collected, so be sure to save it somewhere if you need it again later.

toBeginning() - Pauses and immediately returns to the beginning of the tween

toEnd() - Immediately advances to the end of the tween.

setPosition() - Immediately changes the position of the tween.

play() - If the tween isn't playing, and it hasn't reached the end, it will start playing. If you pause() the tween, you may resume it by calling play().

Finally, transition provides a rather limited set of easing functions. gtween comes with many more.

J. A. Whye's picture
J. A. Whye
User offline. Last seen 12 hours 39 min ago. Offline
Joined: 25 Sep 2010

Thanks, Josh, just the kind of list I was looking for.

I saw you post this originally a couple weeks ago but since I didn't know what it was just kind of forgot about it. I'm glad I came across it again and asked -- I think this will be a really good addition to my toolbox.

Thanks!

Jay

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

I pushed an update to gtween.lua today. It now includes all the easing functions from the ActionScript version. Some of my favorites include Back, Bounce, and Elastic. For a full list, see the readme in the gtween.lua Github repo.

Usage:

1
2
3
4
5
6
7
gtween.new(target, 1.0,
{
        x = 100
},
{
        ease = gtween.easing.outBack
})

Remember, GTween's easing functions should be passed to the ease property, while Corona's built-in easing functions should be passed to the transitionEase property instead.

arbt
User offline. Last seen 4 days 11 hours ago. Offline
Joined: 14 Oct 2010

It would be really handy to have pauseAll and resumeAll functions like in transitionManager.

xxxfanta's picture
xxxfanta
User offline. Last seen 6 days 2 hours ago. Offline
Joined: 25 Dec 2010

isn't gtween:pause() actually pausing ALL transitions?
I was actually searching for a way to unregister (and therefore hopefully delete) transitions from a single object..

Let's say I have a dozen enemies flying at me and when they are shot, they will be removed and I want there transition to be canceled and removed from the memory aswell.
Is there a way to make it with gtween?

Thanks in advance,
Chris

Antheor
User offline. Last seen 6 hours 13 min ago. Offline
Joined: 22 Sep 2010

This is great news !

Could you add some gtween method example in your usage sample ?

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

No, pause() only targets a single instance. Notice that a colon is used to make the call, which means that it's a method with self passed as a hidden first parameter. You can use pause() like this:

1
2
local myTween = gtween.new(target, 0.25, {x = 100});
myTween:pause();

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

Hmm... I see that GTween in ActionScript actually has a pauseAll static variable. I guess I missed that. I'll try to add it (or something similar) soon.

Antheor
User offline. Last seen 6 hours 13 min ago. Offline
Joined: 22 Sep 2010

Is it possible to add parameters to your onChange. For example :

1
2
3
4
5
6
7
8
9
local function redSquareMove_onChange( tween, pos )
        blueSquare.x = redSquare.x + pos
        blueSquare.y = redSquare.y
        blueSquare.alpha = 1 - redSquare.alpha
end
 
-- ...in gtween parameters
onChange = redSquareMove_onChange(150)
-- ... that obviously doesn't work

Thx for any hints

xxxfanta's picture
xxxfanta
User offline. Last seen 6 days 2 hours ago. Offline
Joined: 25 Dec 2010

Thanks for that josh!
For now I've had to put all objects into a table (it was no problem to stop them, but actually to start them again after i paused them..)

xxxfanta's picture
xxxfanta
User offline. Last seen 6 days 2 hours ago. Offline
Joined: 25 Dec 2010

@Antheor

You could either use a global variable or try to use closures (not sure if that'll work)
Something like:
gtween....(...{onChange = function() return blueSquare( 150 ) end})

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

@Antheor You can add extra parameters to the tween itself. The AS3 version has a "data" property specifically for that purpose, but Lua is more flexible, so you can call them anything you want.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
local function redSquareMove_onChange( tween )
        blueSquare.x = redSquare.x + tween.data
        blueSquare.y = redSquare.y
        blueSquare.alpha = 1 - redSquare.alpha
end
gtween.new(redSquare, 1.5,
{
        x = 260,
        y = 260,
        alpha = 0
},
{
        data = 150,
        transitionEase = easing.outQuad,
        repeatCount = math.huge,
        reflect = true,
        onChange = redSquareMove_onChange
})

Antheor
User offline. Last seen 6 hours 13 min ago. Offline
Joined: 22 Sep 2010

I had no idea about this trick ! Thank you so much :)

Antheor
User offline. Last seen 6 hours 13 min ago. Offline
Joined: 22 Sep 2010

I 'm playing with your sample code.
I'd like to add some code each time the rectangle makse a loop (ends the move or return back to the initial position), but onComplete is not a solution since it's launched only once.

Is there a way here ?

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

@Antheor No, there doesn't appear to be a callback for that. However, you might be able to check for that case in your onChange callback. I think that you can do something like this:

1
2
3
4
5
6
local function tween_onChange(tween)
    if tween.calculatedPosition == 0 or tween.calculatedPosition == tween.duration then
        -- tween has just reflected
    end
    -- other stuff
end

You may need a special case for the first run. I'm not sure. I haven't tried this.

Antheor
User offline. Last seen 6 hours 13 min ago. Offline
Joined: 22 Sep 2010

Ok. Thx

arbt
User offline. Last seen 4 days 11 hours ago. Offline
Joined: 14 Oct 2010

While we wait for the functions to be implemented in GTween, here's a sample code on how to get it working:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
local redSquare = display.newRect( 0, 0, 100, 100 )
redSquare:setFillColor( 255, 0, 0 )
redSquare.x = 60
redSquare.y = 60
 
local blueSquare = display.newRect( 0, 0, 100, 100 )
blueSquare:setFillColor( 0, 0, 255 )
blueSquare.x = 170
blueSquare.y = 60
blueSquare.alpha = 0
 
-- Add all tweens to a table
local tweens = {}
 
tweens.redSquare = gtween.new(redSquare, 1.5,
{
        x = 260,
        y = 260,
        alpha = 0
},
{
        transitionEase = easing.outQuad,
        repeatCount = math.huge,
        reflect = true,
})
 
tweens.blueSquare = gtween.new(blueSquare, 1.5,
{
        x = 260,
        y = 160,
        alpha = 0.5
},
{
        transitionEase = easing.outQuad,
        repeatCount = math.huge,
        reflect = true,
})
 
function pauseAllTweens()
    for k, v in pairs(tweens) do
        v:pause()
    end
end
 
function resumeAllTweens()
    for k, v in pairs(tweens) do
        v:play()
    end
end
 
timer.performWithDelay(1000, pauseAllTweens, 1)
timer.performWithDelay(3000, resumeAllTweens, 1)

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

FYI, you can now set gtween.pauseAll = true to pause all playing tweens.

arbt
User offline. Last seen 4 days 11 hours ago. Offline
Joined: 14 Oct 2010

Latest version of the library is not working for me. I'm using the exact same code but I get "attempt to call field 'new' (a nil value)".

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

Thanks for the heads-up. I didn't test this form of require(), which I assume you were doing:

require("gtween")

I always assign it to a local variable, like this:

local gtween = require("gtween")

It should be working correctly now.

arbt
User offline. Last seen 4 days 11 hours ago. Offline
Joined: 14 Oct 2010

Thanks, that actually solves the problem even though I was assigning it to a local variable.

yuewah
User offline. Last seen 22 weeks 6 days ago. Offline
Joined: 4 Dec 2010

gtween is very useful, it would be good if how many tween is still playing become public. btw, I have modified your code to meet my requirement, but i hope it can officially support it.

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

[UPDATED POSTING]
I got my error here. I should call ease = gtween.easing.inOutQuadratic, instead of transitionEase = easing.inOutQuadratic

Am I missing something? Besides the in/outBounce, all other transitions play the same as linear. I have tried all of them but no differences were noticed.

my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
local gtween = require("gtween")
 
--linear
local function ease1()
        
        if not circle1 then
                circle1 = display.newCircle(20, 60, 10 )
                circle1:setFillColor(255,0,0,255)
        else
                circle1.y = 60
        end
 
        --transition.to(circle1, {time=3000, y=460})
        gtween.new(circle1, 3,{ y = 460},{      transitionEase = easing.outElastic })
end
ease1();

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

Well, as I am already here, do you have a description of each easing?
Thanks!

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

Most of them are named after their mathematical equations. Basically, the name is the description. For most people, that's not really the clearest way to understand them, though. I recommend looking for a visualization that demonstrates each of them so that you can compare them yourself.

Here's one visualizer that's pretty cool:
http://hosted.zeh.com.br/tweener/docs/en-us/misc/transitions.html

Here's another good one that does it differently:
http://www.gizma.com/easing/

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

What is the best way to return to the original position (before the tween) when the tween ends?

I tried to add a call to "blue:toBeginning()" just after the tween but it didn't start the tweening.

I tried also to call it thru the onChange function but, again, no success.

thanks,
Alex

mroberti's picture
mroberti
User offline. Last seen 1 day 4 hours ago. Offline
Joined: 20 Nov 2010

I think the 'reflect' flag/call does that. It says it returns to the original position...above it says "reflect - This will reverse the tween every time it repeats." The above examples are using infinite loops. I assume it'd work for a "one off" too. I haven't ever used it....hope that helps some!

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

toBeginning() will reset the tween, but it won't change anything on the target. You need to play it again to make it affect the target.

I would define an onComplete callback and reset the original values there. You could either hard code them, or maybe get them from the initValues variable.

yuewah
User offline. Last seen 22 weeks 6 days ago. Offline
Joined: 4 Dec 2010

gtween is fantastic, it would be great if a group of tweens is paused insteads of all ?

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

That sounds like something that is best managed outside GTween. Just keep your "group" in an array and loop through it to pause them individually.

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

Josh,

Maybe you can help me here. Is there a way to pause/delete all tween before I move to another page using director?

Currently I am using gtween.pauseAll = true. Unfortunately, all tweens of the following page don't fire (even adding a gtween.playAll = true in the beginning of the code.

Any ideas on how to delete all the tween of page 1 before to jump to page 2?

Thanks!

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

I am receiving the following error in one of the pages of my project:

Runtime error
/Users/mac/Documents/Kwik/James/build/gtween.lua:100: attempt to perform arithmetic on field '?' (a nil value)
stack traceback:
[C]: ?
/Users/mac/Documents/Kwik/James/build/gtween.lua:100: in function 'init'
/Users/mac/Documents/Kwik/James/build/gtween.lua:395: in function 'setPosition'
/Users/mac/Documents/Kwik/James/build/gtween.lua:52: in function
?: in function <?:214>
Runtime error
/Users/mac/Documents/Kwik/James/build/gtween.lua:400: attempt to perform arithmetic on local 'rangeVal' (a nil value)
stack traceback:
[C]: ?
/Users/mac/Documents/Kwik/James/build/gtween.lua:400: in function 'setPosition'
/Users/mac/Documents/Kwik/James/build/gtween.lua:52: in function
?: in function <?:214>
Kwik/James/build/gtween.lua:42>
?: in function <?:214>

any ideas on what is happening?
Thanks!

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

@d3mac123 There's no way to automatically pause all tweens when changing screens with director. If you set gtween.pauseAll = true, it won't get rid of them. It's just a quick way to pause everything temporarily. You'll need to keep track of your tweens for a specific screen and pause them manually on change.

For the error you're seeing, I'm guessing that one of your starting values is nil. It could be a typo or it could be that you forgot to initialize some value before tweening it.

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

It is happening when a tween is running and it is also a button to change pages. I pause it and use the director change scene. It seems that the pause is not clearing the tween.

This is my button:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
local onLayer1Touch = function(event) 
          if event.phase=="release" and Layer1.isActive then 
                disposeAudios() 
                gt_Layer1:pause(); 
                director:changeScene( "page_7", "moveFromRight" ) 
          end 
end
Layer1 = ui.newButton{ 
           defaultSrc="p6_Layer1.png", 
           defaultX = 796, 
           defaultY = 504, 
           overSrc="p6_Layer1.png", 
           overX = 796, 
           overY = 504, 
           onEvent=onLayer1Touch, 
           id="Layer1Button" 
       } 

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

Josh, any chance you give me a direction here?

I need to move an object with gtween from point A to D, stopping in points B, C first. So, I have a table with all end points (x and y) and I am looping the .x and .y positions. The issue is I cannot control the duration of the movement. I would like to say, from point A to D, it will take 5 seconds. However, when I play the animations goes directly from point A to D.

This is the code I am using (i tried timers on onComplete without success and i couldn't go further with the onChange):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
local gtween = require("gtween")
 
xcoords = { 65.9484777517564,260.7962529274,67.4473067915691 }
ycoords = { 705,405,153 }
 
Background = display.newImageRect( "p1_Background.png", 683, 1018 ); 
Background.x = 340; Background.y = 451; Background.alpha = 1 
 
bee = display.newImageRect( "p1_bee.png", 47, 51 ); 
bee.x = 118; bee.y = 847; bee.alpha = 1 
 
 
local sec = 5 --seconds or the animation duration
local msec = sec / (#xcoords - 0) --duration divided by the number of path points
 
local coordCount = 1
 
 
 
local function moveObject()
        if coordCount <= #xcoords then
                        print("Coordcount:",coordCount)
                                gt_c= gtween.new( bee, msec, { x = xcoords[ coordCount ], y = ycoords[ coordCount ], rotation = 0, xScale = 1, yScale = 1, alpha=1}, {ease = gtween.easing.linear, repeatCount = 1, reflect = false,  delay=0}) 
                --bee.x = xcoords[ coordCount ]
                --bee.y = ycoords[ coordCount ]
                        coordCount = coordCount + 1
 
       else
                Runtime:removeEventListener( "enterFrame", moveObject )
        end
end
 
Runtime:addEventListener( "enterFrame", beginBeeMove )

Any ideas on how I can "pause" the time between points?

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

I can't quite tell what's wrong with the code, as it appears that some relevant parts might be missing. It looks like you're starting each tween on consecutive enterframes, though, so they might all be playing at the same time. Personally, I would recommend a different approach.

Consider using the nextTween property. This will allow you to play a set of tweens in a sequence. Just loop through each set of coordinates and create a tween for each one. Be sure to keep track of the previous tween so that you can set previousTween.nextTween = currentTween. Also, ensure that you set currentTween.autoPlay = false for all but the first one so that they don't all play at once.

To pause between points, add a delay to the start of each tween (except, again, the first one).

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

Thanks Josh. I tried this but it did not work (is this the correct way to play the nextTween?):

1
2
3
gt_c3= gtween.new( bee, msec, { x = xcoords[ 3 ], y = ycoords[ 3 ], rotation = 0, xScale = 1, yScale = 1, alpha=1}, {ease = gtween.easing.linear, repeatCount = 1, reflect = false,  delay=0, autoPlay = false})
gt_c2= gtween.new( bee, msec, { x = xcoords[ 2 ], y = ycoords[ 2 ], rotation = 0, xScale = 1, yScale = 1, alpha=1}, {ease = gtween.easing.linear, repeatCount = 1, reflect = false,  delay=0, autoPlay = false, nextTween="gt_c3"})
gt_c= gtween.new( bee, msec, { x = xcoords[ 1 ], y = ycoords[ 1 ], rotation = 0, xScale = 1, yScale = 1, alpha=1}, {ease = gtween.easing.linear, repeatCount = 1, reflect = false,  delay=0, nextTween="gt_c2"})

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

No, you need to pass the tween itself rather than a string. For example, nextTween = gt_c3 (no quotes).

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

It is working now, thanks. Now i have to work on the math to guarantee the correct speed between each point (distant points are animating in the same speed of closest ones).

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

josh, can you send me a private email at alex at asouza.com?

i need to make some additions to gtween and i would like to know if you could that for me (i will pay for it).

thanks!
alex

d3mac123
User offline. Last seen 4 weeks 2 days ago. Offline
Joined: 12 Feb 2010

josh, can you send me a private email at alex at asouza.com?

i need to make some additions to gtween and i would like to know if you could that for me (i will pay for it).

thanks!
alex

jesterxl's picture
jesterxl
User offline. Last seen 13 weeks 2 days ago. Offline
Joined: 20 Jan 2011

Hey Josh, I seem to be having problems using time less than 1 second. It seems like the tween doesn't finish. Does this make sense?

For example, if you change .5 to 1, it works, but .5 seems to ... well, halt.

1
2
3
4
require "gtween"
local img = display.newImage("player.png")
img.x = 400
gtween.new(img, .5, {x=0}, {transitionEase=gtween.easing.outBounce})

josh6's picture
josh6
User offline. Last seen 23 weeks 3 days ago. Offline
Joined: 17 Feb 2011

Durations less than a second work for me. However, it's probably the easing function. Anything in gtween.easing.* needs to be passed to the "ease" property. "transitionEase" is only for the built-in easing functions that come with Corona's transitions. I didn't really look into the details, but the arguments are different.

Viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.