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.
Awesome!
+1 for a Lua translation of TweenLite/TweenMax = )
Hey pretty neat! Thanks a lot!
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.
Just call tween:pause(). That'll stop it from playing and also unregister it.
Sweet! Thank you sir!
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!
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.
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
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.
It would be really handy to have pauseAll and resumeAll functions like in transitionManager.
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
This is great news !
Could you add some gtween method example in your usage sample ?
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(); |
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.
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
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..)
@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})
@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 }) |
I had no idea about this trick ! Thank you so much :)
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 ?
@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.
Ok. Thx
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) |
FYI, you can now set gtween.pauseAll = true to pause all playing tweens.
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)".
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.
Thanks, that actually solves the problem even though I was assigning it to a local variable.
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.
[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(); |
Well, as I am already here, do you have a description of each easing?
Thanks!
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/
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
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!
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.
gtween is fantastic, it would be great if a group of tweens is paused insteads of all ?
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.
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!
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!
@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.
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" } |
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?
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).
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"}) |
No, you need to pass the tween itself rather than a string. For example, nextTween = gt_c3 (no quotes).
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).
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
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
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}) |
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.
Really cool,
Gracias viejo por tu aporte!!