Asset - Scripts TweenGMS - Tweening Engine

8BitWarrior

Member
TweenGMS 2 Beta 10 is now available.
I am considering this beta "feature locked" before a stable release. With that said, I may place this beta on the GameMaker Marketplace in the near future under a new "TweenGMS 2" listing.
 
Last edited:

8BitWarrior

Member
TweenGMS update v1.11 is now live on the GameMaker Marketplace. Please be aware that this version now requires GMS 2.3.7.

This update adds TPStruct() and TPInst(), making it easier to ease struct values or variables belonging to instances other than a tween's set target.

Tween callbacks have also be been modified:
1) Structs can now be passed as a callback target.
2) Methods passed to callbacks now use the assigned callback target as the calling environment. Please see the Update Log, Script Reference, or Starter Guide for more details.

[Update Log]
Code:
[!! Breaking Changes !!]
   
#1
GameMaker Studio 2.3.7 is now required.

#2   
Please be aware that target handling for tween callbacks has been modified.
Methods used as a callback script will now use the specified callback target, overriding its calling environment/self.
Previously, the callback target would not affect methods with a defined 'self'.
To maintain a method's existing 'self', please use the keyword [undefined] as the callback target.
You can find more information about this in the log below or under TweenAddCallback() in the Script Reference.
If upgrading an existing project, please validate that your tween callbacks still work as intended.


[Version 1.11]

- Added TPStruct() for easing struct properties
    * Note: This will not make use of optimised/custom property functions for easing struct values
    * e.g.
        some_struct = {value: 0}
        TweenFire(id, EaseInSine, 0, true, 0, 1, TPStruct(some_struct, "value"), 0, 100);
       
- Added TPInst() for easing values belonging to other specific instances
    * Note: Normalized properties are not supported -- "image_blend" will not work with this function
    * e.g.
        TweenFire(self, EaseInSine, 0, true, 0, 1, "x", 0, 10, TPInst(obj_Enemy, "x"), 0, 100);
       
- TweenAddCallback() now supports struct targets
    * e.g.
        some_struct = {value: 0}
        t = TweenFire(id, EaseInSine, 0, true, 0, 1, "x", 0, 100);
        TweenAddCallback(t, TWEEN_EV_FINISH, some_struct, func_PrintValue);

- Callback methods now use assigned targets as the calling environment
    * Methods were previously always using their 'self' environment
    * The use of function/script ids are not affected by this change
    * Mentioned below, the 'undefined' keyword can be used to keep the method's existing instance/struct environment
    * e.g.
        // Set up struct with method and fire a tween
        some_struct = { my_method: function(){ show_message(self); } }
        t = TweenFire(id, EaseInSine, 0, true, 0, 1, "x", 0, 100);
       
        // Add callback method, using obj_Player as calling environment instead of method's "self"
        TweenAddCallback(t, TWEEN_EV_FINISH, obj_Player, some_struct.my_method);

- Added the keyword 'undefined' as a valid callback target
    * This will use a function's or method's existing instance/struct 'self' as the callback target environment
    * If the method's 'self' is undefined, then the current environment's self will be used as the target
    * e.g.
        // Create a new struct with a value and method
        some_struct = {value: 100, my_method: function(){ show_message(value); }}
       
        // Fire a tween
        t = TweenFire(id, EaseInSine, 0, true, 0, 1, "x", 0, 100);
       
        // Add a callback but retain the method's 'self' as the calling target environment
        TweenAddCallback(t, TWEEN_EV_FINISH, undefined, some_struct.my_method
       
        // Omitting the target argument will do the same thing
        TweenAddCallback(t, TWEEN_EV_FINISH, , some_struct.my_method
       
        // With a function id, undefined will simply be the same as using 'self'
        TweenAddCallback(t, TWEEN_EV_FINISH, undefined, show_message, "Done!");
       
- Added "z" as a default optimised property
- Fixed various state checks returning 'undefined' instead of 'false'
- Changed internal naming of some properties to prevent chance of naming conflicts
 
Last edited:

Old2DGuy

Member
Just added this to my project, first run.....IT WORKED! :) But I can't find a reference of all the different ease's available (EaseInOutQuad, etc, etc) so I can give it a proper workout. lol.. But so far so good, thank you! :)
 

8BitWarrior

Member
TweenGMS Pro v1.12 is now available on the GameMaker Marketplace. This includes a fix for GML's recent removal of "copy-on-write" for arrays (by default).

Code:
Update Notes:
- Updated code for GML's removal of array "copy-on-write"
- Improved JSDoc support for GMLive
- Disabled Feather (Should hide most false warnings)
- Removed unused internal "getter" functions
- TweensTarget() now supports [self] and [other]
- Various optimisations
 
Last edited:

8BitWarrior

Member
Just added this to my project, first run.....IT WORKED! :) But I can't find a reference of all the different ease's available (EaseInOutQuad, etc, etc) so I can give it a proper workout. lol.. But so far so good, thank you! :)
Which version of TweenGMS are you using?

For TweenGMS v1.11/v1.12 you should see a script called TGMS_EasingEquations inside the [Scripts] folders.
If using the TweenGMS 2 beta, you should see the script TGMS__2_EaseFunctions inside the main [TweenGMS 2 Beta] folder.

With that said, I'm assuming you may have already found them. :)
 

Old2DGuy

Member
Which version of TweenGMS are you using?

For TweenGMS v1.11/v1.12 you should see a script called TGMS_EasingEquations inside the [Scripts] folders.
If using the TweenGMS 2 beta, you should see the script TGMS__2_EaseFunctions inside the main [TweenGMS 2 Beta] folder.

With that said, I'm assuming you may have already found them. :)
Thank you for the reply. I've been working on some other stuff, but now that I know where the easings are....lol.... :p I'll starting playing with it more and see how it meshes with my game engine. Thx!
 

Old2DGuy

Member
hmm.. I'm hoping I missed it, but I can't find the following state functions, I'm really hoping they are there. I'm using v1.12 if that helps. Thank you.

PauseTween(all) or maybe PauseAllTweens().
ContinueTween(all) or ContinueAllTweens().
StopTween(all) or StopAllTweens();
 

8BitWarrior

Member
hmm.. I'm hoping I missed it, but I can't find the following state functions, I'm really hoping they are there. I'm using v1.12 if that helps. Thank you.

PauseTween(all) or maybe PauseAllTweens().
ContinueTween(all) or ContinueAllTweens().
StopTween(all) or StopAllTweens();
You can you the 'all' keywords to affect all tweens:
GML:
TweenPause(all);
TweenResume(all);
For affecting tweens related to specific targets or groups, you can read about them in the Script Reference under Tween Selection.

The TweenGMS 2 beta extends this functionality even further, but I won't go into that now. :)

Hoping this helps!
 

Old2DGuy

Member
I'm currently running IDE v2022.1.1.610 Runtime v2022.1.1.483.

I'm running Windows 7 and due to errors I will not be installing the latest ide/runtime until they fix some bugs causing it not to run. I updated to the latest version of Tween Pro Version 1.12 before knowing about the Win 7 problems in the latest GMS release. Is there a way to download 1.11?

These are the syntax errors I'm getting without even using any part of the system when I try to build.

Compile Scripts...
Error : gml_GlobalScript_TGMS_AutoProperties(13) : variable name expected

Error : gml_GlobalScript_TGMS_AutoProperties(13) : Symbol ) expected

Error : gml_GlobalScript_TGMS_AutoProperties(13) : unknown function atribute variable

Error : gml_GlobalScript_TGMS_AutoProperties(13) : got ')' expected '{'

Error : gml_GlobalScript_TGMS_System(387) : variable name expected

Error : gml_GlobalScript_TPUser(67) : variable name expected

Error : gml_GlobalScript_TGMS_DefaultProperties(82) : variable name expected
finished.
 

8BitWarrior

Member
I'm currently running IDE v2022.1.1.610 Runtime v2022.1.1.483.

I'm running Windows 7 and due to errors I will not be installing the latest ide/runtime until they fix some bugs causing it not to run. I updated to the latest version of Tween Pro Version 1.12 before knowing about the Win 7 problems in the latest GMS release. Is there a way to download 1.11?
finished.
Hmm.... I can take a look into this.
Here is a link to files for version 1.11.

[Update]
Running on v2022.1.1.483, I am not seeing the same error under Windows 10. I don't have a Windows 7 machine to test on.
Have you tried clearing the compiler cache and trying again? Do any of the target platforms compile?
 
Last edited:

Old2DGuy

Member
Thank you for your reply. I just installed 1.11 and now getting these errors. Is the tween system expecting any default room settings, etc? Strange how I didn't have these errors before so perhaps there is something in my code causing a conflict? I have no other extensions added except for yours.

I'm still new to GMS and even though I have an indie license, I'm only testing / building via Windows VM for now.

Compile Scripts...
Error : gml_GlobalScript_TGMS_AutoProperties(7) : variable name expected
Error : gml_GlobalScript_TGMS_AutoProperties(7) : Symbol ) expected
Error : gml_GlobalScript_TGMS_AutoProperties(7) : unknown function atribute variable
Error : gml_GlobalScript_TGMS_AutoProperties(7) : got ')' expected '{'
Error : gml_GlobalScript_TGMS_System(387) : variable name expected
Error : gml_GlobalScript_TGMS_DefaultProperties(79) : variable name expected
finished.
 

8BitWarrior

Member
Thank you for your reply. I just installed 1.11 and now getting these errors. Is the tween system expecting any default room settings, etc? Strange how I didn't have these errors before so perhaps there is something in my code causing a conflict? I have no other extensions added except for yours.
You shouldn't have to do anything for things to "just work". Does this happen with a freshly created project and fresh import of TweenGMS?
 

Old2DGuy

Member
You shouldn't have to do anything for things to "just work". Does this happen with a freshly created project and fresh import of TweenGMS?
Thanks, I just created a blank new project, added your scripts and it created the build no problem. So it must be something with my project. Crazy....will do some testing. Thanks for taking the time to reply, much appreciated!
 

Old2DGuy

Member
wow...that took a bit of turning things off/on until I found the problem. I had a sprite named "target" and that does not bode well with your tween system. lol.. But it is interesting that sprite names could conflict with your tween system. But at least it's working now. :)
 

8BitWarrior

Member
wow...that took a bit of turning things off/on until I found the problem. I had a sprite named "target" and that does not bode well with your tween system. lol.. But it is interesting that sprite names could conflict with your tween system. But at least it's working now. :)
Oh wow... I didn't expect that! lol
I'll aim to see what's going on with that. Thanks for letting me know.
 

8BitWarrior

Member
Ok! I believe I found the issue.

It seems that there is a GMS 2 bug where having a function parameter named the same as an asset name will cause the function to error and not compile.
GML:
// Having an asset also named 'par_name' will cause a build error
function Some_Function(par_name)
{
    show_message(par_name);
}
I'll aim to report this as a bug to YoYo Games.
At the least, this gives me a reason to change the naming convention of my function parameters.
 
Last edited:

8BitWarrior

Member
Perfect, this will latch into my engine just fine. :)

Is there also a TweenRemove(all) ? I would use that at the end of a level, app exit, etc, etc.

Thanks!
Tweens associated with non-persistent targets will be automatically destroyed when its target is destroyed or when the room is changed. If a room is persistent, then tween's associated with targets belonging to that room will be automatically removed from the main processing list. When returning to the persistent room, those tweens will be added back to the main processing list.

If you still need to manually delete all tweens, you can do that with:
GML:
TweenDestroy(all);
To validate the number of tweens in the system, you can use TweenSystemCount().
 

8BitWarrior

Member
TweenGMS v1.20 is now available on the GameMaker Marketplace.
This version removes property functions from the global namespace to prevent conflicts with other GameMaker libraries (e.g. Scribble).
Because of this, property strings are now required for default variable properties (e.g. "x", "speed", "image_angle"). This does not not affect your own custom property setter scripts/functions.

I've also begun to transition the name to "TweenGMS Legacy" in preparation of TweenGMS 2.

Additional changes can be seen below...

Code:
[Version 1.20]

- Removed function setter/getting functions (x__ / __x, image_angle__ / __image_angle, etc..)
    * Property strings ("x", "image_angle") are now required
    * This clears up conflicts with other libraries in the global namespace

- TPUser() user events no longer need to use the TWEEN_USER_TARGET macro
    * The calling target environment is now used automatically

- TPExt() can now take methods
    * Note that they are stripped of their calling environment

- Changed name to TweenGMS Legacy
    * This is in preparation for TweenGMS 2
    
- TGMS_BuildProperty() now requires a GETTER function to be provided
- Error will no longer occur if instance associated with TPInst() is destroyed
- Removed again 'Syntax Errors' for pre-feather environment
- Added system functions to Feather @ignore list
- Updated system initialization
- Removed function TGMS_Null__()
- Documentation tweaks
 

8BitWarrior

Member
TweenGMS 2 has been rebranded as "TweenGMX".
You can now find the beta for it on the GameMaker Marketplace:
TweenGMX Beta

While being mostly backwards compatible with TweenGMS, it offers many new features.
You can find me discussing some of these features in a video HERE.

TweenGMX_200.png
 

8BitWarrior

Member
If you are using the TweenGMX beta, I highly encourage updating to beta 13 which recently released.

GameMaker is changing how 'id' is handled. It will no longer be a real number but a reference. This change is currently in the GameMaker beta channel and will break previous versions of TweenGMX.

Update Log:
- Updated code to support GameMaker's runtime change for 'id'
- Fixed TweenPlay() definition not showing ease parameter
- Fixed mangling of implied struct targets for tweens and callbacks
- Fixed TweenCreate() not setting implied target for "off-rail" calls
- TweenCreate() optionally no longer requires any arguments
- Fixed target selection missing multiple instances with object index
- Changed system enums to macros to avoid naming conflicts
 
Last edited:

8BitWarrior

Member
TweenGMX Beta 14 is now available on the GameMaker Marketplace.
Please note that TweenGMS and TweenGMX are no longer being supported on Itch.io, so please move over to the GM Marketplace version if you haven't already.

Code:
    [CHANGES]
    - Fixed tweens being mistakenly destroyed when instance target deactivated
    - Fixed normalized durations potentially producing nan values
    - Improved Feather support (still in progress but should report less errors)
    - Added missing documentation for various functions in script reference
 

hippyman

Member
TweenGMX Beta 14 is now available on the GameMaker Marketplace.
Please note that TweenGMS and TweenGMX are no longer being supported on Itch.io, so please move over to the GM Marketplace version if you haven't already.

Code:
    [CHANGES]
    - Fixed tweens being mistakenly destroyed when instance target deactivated
    - Fixed normalized durations potentially producing nan values
    - Improved Feather support (still in progress but should report less errors)
    - Added missing documentation for various functions in script reference
I have to really commend you for how long you been working on this. I'm sure it's been extremely helpful to so many people throughout the years.
 

8BitWarrior

Member
TweenGMX Beta 15 is now available on the GameMaker Marketplace!
Apart from some minor tweaks, this seems like a close candidate for a stable release.
I would like to release an official stable release in October.
Code:
[ TweenGMX Beta 15 Update Notes]   

- Fixed some issues with Feather
- Improved performance for TweenJust*() functions
- Fixed crash if system not initialized before TGMX_2_EaseFunctions() is called
- o_SharedTweener should no longer be "managed" by default for multiplayer sessions
- Potential fix for Android YYC crash related to TweenDefaultSet()
- Fixed crash for Android YYC related to EaseOutQuart()
- TweenIsPlaying() & TweenIsActive() again support checking all tweens or an array of tweens
- TweenDestroyWhenDone() now only requires 1 argument
 

Mehdi

Member
@8BitWarrior
Sorry to ask: How have you added chaining tween in your interactive example?
I tried to do the same and used 4 different tweens and chained them by means of TweenMore. However I can't do the looping. I mean after chaining the last tween to the first, the loop seems stopped and can't continue.

A short example code of your own chaining example in the interactive demo would be greatly appreciated.
 

8BitWarrior

Member
@8BitWarrior
A short example code of your own chaining example in the interactive demo would be greatly appreciated.
With TweenGMX 1.0 almost finished, I'd like to put more time into the examples. I am wondering if I should make a tutorial video on chained tweens. 🤔

If I recall correctly, I used TweenCreate for the base tween in the current example. This means that the tween (and chained tweens added to it) will persist after it finishes. But if the base tween used TweenFire, then all the chained tweens will be destroyed as soon as they finish.

I hope this points in the right direction.
I'd like to look into this some more.

Thanks for the input!

Edit:
And in case you haven't seen the examples project, you can find the latest TweenGMX Examples project here.

It includes code for the chained example.
 

Mehdi

Member
It includes code for the chained example.
Thank you for your reply. However the demo didn't include the chaining.
After all, your script is amazing and I will try to find some way by myself while waiting for your future excellent videos.
 

8BitWarrior

Member
Thank you for your reply. However the demo didn't include the chaining.
Oh, right!
I have quickly put together an example which I hope helps you.
Please note, this example uses TweenGMX. If using TweenGMS, it will need to be modified.
You can try putting this into the Create Event of an object.

GML:
// Set x/y movement boundaries
x1 = 100;
y1 = 100;
x2 = room_width-100;
y2 = room_height-100;

// Set our instance's starting x/y position
x = x1;
y = y1;

// Create a persistent base tween -- This will let us restart it later using TweenPlay()
base_tween = TweenCreate(self, "io", 0, true, 0, 1.0, "x", x1, x2);

// Chain more tweens from base tween, using lazy tween ids {0}
// (Passing 0 as a tween id will reference previously created tweens)
TweenMore(0, self, "io", 0, true, 0, 1.0, "y", y1, y2);
TweenMore(0, self, "io", 0, true, 0, 1.0, "x", x2, x1);
TweenMore(0, self, "io", 0, true, 0, 1.0, "y", y2, y1);

// Add a "finish" callback to the last tween, restarting the base tween
TweenAddCallback(0, "finish", self, TweenPlay, base_tween);

// Start playing our base tween
TweenPlay(base_tween);
Let me know if you can get this working :)
 
Last edited:

Mehdi

Member
@8BitWarrior
Don't we have a post-delay? I mean similar to current delay that happens before tweening, can we have a delay after finishing the move? This way we could have patrolling with a slight pause before reversing.
 

8BitWarrior

Member
@8BitWarrior
Don't we have a post-delay? I mean similar to current delay that happens before tweening, can we have a delay after finishing the move? This way we could have patrolling with a slight pause before reversing.
Yes! You can find documentation about a tween's "rest" setting here:
TGMX Reference Guide: CONTINUE AND REST

A simple way to do this is by setting the "rest" value for a tween:

GML:
tween = TweenFire(self, "io", "patrol", true, 0.0, 1.0, "x", 0, 100);
TweenSet(tween, "rest", 60);

// Or have a different rest time for each direction by passing an array with two values
TweenSet(tween, "rest", [60,120]);
But you can also do this inline by passing the tween's delay as an array, with the first value being the starting delay, and the second value being the continue rest time:
GML:
delay = 0.0;
rest = 1.0;
TweenFire(self, "io", "patrol", true, [delay, rest], 1.0, "x", 0, 100);

You can even have different rest delays for each "direction" of the tween by passing a 3rd value to the array:
GML:
delay = 0.0;
rest_1 = 1.0;
rest_2 = 2.0;
TweenFire(self, "io", "patrol", true, [delay, rest_1, rest_2], 1.0, "x", 0, 100);
You can also have different durations for each tween direction by passing the duration as an array with 2 values:
GML:
delay = 0.0;
rest_1 = 1.0;
rest_2 = 2.0;
dur_1 = 1.0;
dur_2 = 2.0;
TweenFire(self, "io", "patrol", true, [delay, rest_1, rest_2], [dur_1, dur_2], "x", 0, 100);
I hope this helps! Happy new year. :)
 
Last edited:

Mehdi

Member
Yes! You can find documentation about a tween's "rest" setting here:
TGMX Reference Guide: CONTINUE AND REST

A simple way to do this is by setting the "rest" value for a tween:

GML:
tween = TweenFire(self, "io", "patrol", true, 0.0, 1.0, "x", 0, 100);
TweenSet(tween, "rest", 60);

// Or have a different rest time for each direction by passing an array with two values
TweenSet(tween, "rest", [60,120]);
But you can also do this inline by passing the tween's delay as an array, with the first value being the starting delay, and the second value being the continue rest time:
GML:
delay = 0.0;
rest = 1.0;
TweenFire(self, "io", "patrol", true, [delay, rest], 1.0, "x", 0, 100);

You can even have different rest delays for each "direction" of the tween by passing a 3rd value to the array:
GML:
delay = 0.0;
rest_1 = 1.0;
rest_2 = 2.0;
TweenFire(self, "io", "patrol", true, [delay, rest_1, rest_2], 1.0, "x", 0, 100);
You can also have different durations for each tween direction by passing the duration as an array with 2 values:
GML:
delay = 0.0;
rest_1 = 1.0;
rest_2 = 2.0;
dur_1 = 1.0;
dur_2 = 2.0;
TweenFire(self, "io", "patrol", true, [delay, rest_1, rest_2], [dur_1, dur_2], "x", 0, 100);
I hope this helps! Happy new year. :)
Wow, I wonder why Yoyo hasn't offered you a job position yet!
Wish you a perfect new year!
 
I've been using TWEENGMX and I've found it quite impressive for my tweening needs. Nice work!

However, I've found a bug with the use of TWEEN_NULL. The documentation states that TWEEN_NULL should be able to be used in tween functions without causing an error. I've found this to be true in all cases I've tried it except when it gets passed to TweenMoreScript. Then I get the following error:

trying to index a variable which is not an array
at gml_Script_TweenMoreScript (line 433) - TweenAddCallback(_ogTween[TGMX_T_ID], TWEEN_EV_FINISH, SharedTweener(), TweenPlay, _newTween);


My current workaround has been to use TweenExists to check the tween before running any TweenMoreScript commands.
 

8BitWarrior

Member
However, I've found a bug with the use of TWEEN_NULL. The documentation states that TWEEN_NULL should be able to be used in tween functions without causing an error. I've found this to be true in all cases I've tried it except when it gets passed to TweenMoreScript.
Thanks for bringing to this my attention!
A release candidate for TweenGMX v1.0 just went live on the GM Marketplace. I'll aim to get this fixed for the first stable release. :)
 

8BitWarrior

Member
TweenGMX v1.0.1 has been released on the GameMaker Marketplace!
It includes various bug fixes and optimizations, as well as a couple of new minor features.
Code:
- Reduced overhead for tween calls
- Improved performance for tweens with more than 10 properties
- Other minor optimisations
- Fixed TweenPlay() when using "off-rail" override with "-tags"
- Fixed TweenMore() crash when attempting to use TP*() function as first "off-rail" argument
- Fixed EaseOutExpo and EaseInOutExpo failing to fully reach destination values
- Fixed TweenEvent*() functions to support "event" strings as intended
- Fixed TweenSet() not properly handling multi-tween selection
- Error will now be reported if max argument count exceeded for callbacks
- Added more info for error when invalid key is used for duration calculation  
- TweenExists() and TweenIs*() functions now have multi 'tween[s]' support    
- Added TweensFetch() function for returning an array of tweens belonging to a group, target, or all
 
Top