## Tween engine

Share your ZGE-development tips and techniques here!

Moderator: Moderators

Ats
Posts: 257
Joined: Fri Sep 28, 2012 10:05 am
Contact:

### Tween engine

I think ZGE was missing some tweening examples. So I wrote one, based on the Pico-8 Tween engine by egordorichev. I've put almost everything in a model so it can be used and removed easily. But maybe there a better way to do that.

Code: Select all

``````<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" CameraPosition="0 0 40" FileVersion="2">
<ZLibrary Comment="Tween Functions">
<Source>
<![CDATA[//
// Inspired by https://www.lexaloffle.com/bbs/?pid=52681&tid=31274

const float back = 1.70158;

float tween_easing(float t, string type)
{
float s = back;
switch (type)
{
case "linear":

return t;
break;

return -1*t*(t-2);
break;

return t*t;
break;

t = t*2;
if (t<1) return 0.5*t*t;
return -0.5*((t-1)*(t-3)-1);
break;

case "back_in":

return t*t*((s+1)*t-s);
break;

case "back_out":

t-=1;
return t*t*((s+1)*t+s)+1;
break;

case "back_in_out":

s = back;
t *= 2;
if (t<1)
{
s *= 1.525;
return 0.5*(t*t*((s+1)*t-s));
}
t -= 2;
s *= 1.525;
return 0.5*(t*t*((s+1)*t+s)+2);
break;
}

return t; // return linear if error in type string
}

void tween_init(model t, model m, string ease, float start, float end, float duration, float delay)
{
t.TweenModel = m;          // Attached model to the tween
t.TweenEase = ease;        // See list of easings in Tween Definitions
t.TweenStart = start;      // Start value
t.TweenDiff = end - start; // End value
t.TweenTime = duration;    // Duration of the tween (in seconds)
t.TweenDelay = delay;      // Delay before starting the tween (in seconds)
t.TweenProgress = 0;
}]]>
</Source>
</ZLibrary>
<ZExpression Comment="Tween Definitions">
<Expression>
<![CDATA[//
TweenNames = "linear";
TweenNames = "back_in";
TweenNames = "back_out";
TweenNames = "back_in_out";]]>
</Expression>
</ZExpression>
<ZExpression>
<Expression>
<![CDATA[App.CameraPosition.Z = 40;

model m, t;
for (int i=0; i<TweenNames.SizeDim1; i++)
{
m = createModel(Ball);
m.Position.X = -12 + i * 4;
m.Position.Y = -10;

t = createModel(Tween);
tween_init(t, m, TweenNames[i], m.Position.Y, 10, 1, 1);
}]]>
</Expression>
</ZExpression>
<Content>
<Mesh Name="SphereMesh">
<Producers>
<MeshSphere/>
</Producers>
</Mesh>
<Model Name="Ball">
<OnRender>
<RenderMesh Mesh="SphereMesh"/>
</OnRender>
</Model>
<Model Name="Tween">
<Definitions>
<Variable Name="TweenEase" Type="2"/>
<Variable Name="TweenDelay"/>
<Variable Name="TweenTime"/>
<Variable Name="TweenStart"/>
<Variable Name="TweenProgress"/>
<Variable Name="TweenDiff"/>
<Variable Name="TweenModel" Type="3"/>
</Definitions>
<OnUpdate>
<ZExpression>
<Expression>
<![CDATA[//
float i;

if (CurrentModel.TweenDelay > 0)
{
CurrentModel.TweenDelay -= App.DeltaTime;
i = CurrentModel.TweenStart;
}
else
{
CurrentModel.TweenProgress += App.DeltaTime / CurrentModel.TweenTime;
i = CurrentModel.TweenStart + CurrentModel.tweenDiff * tween_easing(clamp(CurrentModel.TweenProgress, 0, 1), CurrentModel.TweenEase);
}

// See how can I pass some parameters to move the model on another axis, or rotate it or return some floats to the TweenModel
CurrentModel.TweenModel.Position.Y = i;

if (CurrentModel.TweenProgress >= 1)
{
// Do something on tween end. That's the part where I would like to pass a function
model t = createModel(Tween);
tween_init(t, CurrentModel.TweenModel, CurrentModel.TweenEase, CurrentModel.TweenModel.Position.Y, CurrentModel.TweenModel.Position.Y *= -1, 1, 1);

@RemoveModel();
}]]>
</Expression>
</ZExpression>
</OnUpdate>
</Model>
<Array Name="TweenNames" Type="2" SizeDim1="7"/>
</Content>
</ZApplication>
``````
While i'ts working, I'm still searching a clever way to use the tween on a peculiar position axis, or rotation...
And my second concern is: is it possible to pass a function so it can be called when the tween ends? You'll see that in Tween (Model) OnUpdate.
Thanks !
Last edited by Ats on Tue Aug 07, 2018 9:57 am, edited 1 time in total.

Kjell
Posts: 1715
Joined: Sat Feb 23, 2008 11:15 pm

### Re: Tween engine

Hi Ats,

Looks familiar ... K

Ats
Posts: 257
Joined: Fri Sep 28, 2012 10:05 am
Contact:

### Re: Tween engine

lol I didn't find that in the forum. Thanks !

Ats
Posts: 257
Joined: Fri Sep 28, 2012 10:05 am
Contact:

### Re: Tween engine

I'm trying to make a portable tween engine, based on the Pico-8 Tween engine by egordorichev. I've put almost everything in a model so it can be used and removed easily. But maybe there a better way to do that.

Code: Select all

``````<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" CameraPosition="0 0 40" FileVersion="2">
<ZLibrary Comment="Tween Functions">
<Source>
<![CDATA[//
// Inspired by https://www.lexaloffle.com/bbs/?pid=52681&tid=31274

const float back = 1.70158;

float tween_easing(float t, string type)
{
float s = back;
switch (type)
{
case "linear":

return t;
break;

return -1*t*(t-2);
break;

return t*t;
break;

t = t*2;
if (t<1) return 0.5*t*t;
return -0.5*((t-1)*(t-3)-1);
break;

case "back_in":

return t*t*((s+1)*t-s);
break;

case "back_out":

t-=1;
return t*t*((s+1)*t+s)+1;
break;

case "back_in_out":

s = back;
t *= 2;
if (t<1)
{
s *= 1.525;
return 0.5*(t*t*((s+1)*t-s));
}
t -= 2;
s *= 1.525;
return 0.5*(t*t*((s+1)*t+s)+2);
break;
}

return t; // return linear if error in type string
}

void tween_init(model t, model m, vec3 pos, vec3 rot, string ease, float start, float end, float duration, float delay)
{
t.TweenModel = m;          // Attached model to the tween
t.TweenPosition = pos;     // vector3 to activate position axis (ex: (1,0,1) to move on Position.X and Z)
t.TweenRotation = rot;     // vector3 to activate rotation axis (ex: (0,1,0) to move on Rotation.Y)
t.TweenEase = ease;        // See list of easings in Tween Definitions
t.TweenStart = start;      // Start value
t.TweenDiff = end - start; // End value
t.TweenTime = duration;    // Duration of the tween (in seconds)
t.TweenDelay = delay;      // Delay before starting the tween (in seconds)
t.TweenProgress = 0;
}]]>
</Source>
</ZLibrary>
<ZExpression Comment="Tween Definitions">
<Expression>
<![CDATA[//
TweenNames = "linear";
TweenNames = "back_in";
TweenNames = "back_out";
TweenNames = "back_in_out";]]>
</Expression>
</ZExpression>
<ZExpression>
<Expression>
<![CDATA[App.CameraPosition.Z = 40;

model m, t;
for (int i=0; i<TweenNames.SizeDim1; i++)
{
m = createModel(Ball);
m.Position.X = -12 + i * 4;
m.Position.Y = -10;

t = createModel(Tween);
tween_init(t, m, vector3(0,1,0), vector3(1,0,0), TweenNames[i], m.Position.Y, 10, 1, 1);
}]]>
</Expression>
</ZExpression>
<Content>
<Mesh Name="StuffMesh">
<Producers>
<MeshBox/>
</Producers>
</Mesh>
<Model Name="Ball">
<OnRender>
<RenderMesh Mesh="StuffMesh"/>
</OnRender>
</Model>
<Model Name="Tween">
<Definitions>
<Variable Name="TweenEase" Type="2"/>
<Variable Name="TweenDelay"/>
<Variable Name="TweenTime"/>
<Variable Name="TweenStart"/>
<Variable Name="TweenProgress"/>
<Variable Name="TweenDiff"/>
<Variable Name="TweenModel" Type="3"/>
<Variable Name="TweenPosition" Type="7"/>
<Variable Name="TweenRotation" Type="7"/>
</Definitions>
<OnUpdate>
<ZExpression>
<Expression>
<![CDATA[//
float i;

if (CurrentModel.TweenDelay > 0)
{
CurrentModel.TweenDelay -= App.DeltaTime;
i = CurrentModel.TweenStart;
}
else
{
CurrentModel.TweenProgress += App.DeltaTime / CurrentModel.TweenTime;
i = CurrentModel.TweenStart + CurrentModel.tweenDiff * tween_easing(clamp(CurrentModel.TweenProgress, 0, 1), CurrentModel.TweenEase);
}

// Is it possible to pass a parameter pointer in order to get rid of those two vector3?
if (CurrentModel.TweenPosition.X) CurrentModel.TweenModel.Position.X = i;
if (CurrentModel.TweenPosition.Y) CurrentModel.TweenModel.Position.Y = i;
if (CurrentModel.TweenPosition.Z) CurrentModel.TweenModel.Position.Z = i;
if (CurrentModel.TweenRotation.X) CurrentModel.TweenModel.Rotation.X = i;
if (CurrentModel.TweenRotation.Y) CurrentModel.TweenModel.Rotation.Y = i;
if (CurrentModel.TweenRotation.Z) CurrentModel.TweenModel.Rotation.Z = i;

if (CurrentModel.TweenProgress >= 1)
{
// Do something on tween end. That's the part where I would like to pass a function
model t = createModel(Tween);
tween_init(t, CurrentModel.TweenModel, vector3(0,1,0), vector3(1,0,0), CurrentModel.TweenEase, CurrentModel.TweenModel.Position.Y, CurrentModel.TweenModel.Position.Y *= -1, 1, 1);

@RemoveModel();
}]]>
</Expression>
</ZExpression>
</OnUpdate>
</Model>
<Array Name="TweenNames" Type="2" SizeDim1="7"/>
</Content>
</ZApplication>

``````
While i'ts working, I'm still searching a clever way to use the tween on a peculiar position axis, or rotation...

Edit: @Kjell, I've added two arguments to pass around in the tween_init. Two vector3 to choose which Position or Rotation Axis to move on. But that would be better if I could pass the parameter pointer instead of the parameter value. Just like in HaxeFlixel.

And my second concern is: is it possible to pass a function so it can be called when the tween ends? You'll see that in Tween (Model) OnUpdate.

Edit: The answer is no, so I'll stop with that and move to something else...

Kjell
Posts: 1715
Joined: Sat Feb 23, 2008 11:15 pm

### Re: Tween engine

Hi Ats,
Ats wrote:I'm trying to make a portable tween engine, based on the Pico-8 Tween engine by egordorichev. I've put almost everything in a model so it can be used and removed easily.
I'm a bit puzzled as to why you'd want to wrap this in a model .. but maybe that's just me? Anyway, don't use strings in a switch-statement unless you absolutely have to. Instead, you can define a bunch of constant integers in your library ( if you want descriptive function-calls ) like this ..

Code: Select all

``````const int EASE_LINEAR = 0,
EASE_BACK_IN = 4,
EASE_BACK_OUT = 5,
EASE_BACK_INOUT = 6;``````
Ats wrote:I've added two arguments to pass around in the tween_init. Two vector3 to choose which Position or Rotation Axis to move on. But that would be better if I could pass the parameter pointer instead of the parameter value.
Vector arguments are automatically passed as reference ( which are basically safe pointers ) as demonstrated in the following example.

Code: Select all

``````<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
<ZLibrary>
<Source>
<![CDATA[//

void move(vec3 v)
{
v.x += App.DeltaTime;
}]]>
</Source>
</ZLibrary>
<SpawnModel Model="Foo"/>
<Content>
<Model Name="Foo">
<OnUpdate>
<ZExpression>
<Expression>
<![CDATA[//

move(CurrentModel.Position);]]>
</Expression>
</ZExpression>
</OnUpdate>
<OnRender>
<RenderSprite/>
</OnRender>
</Model>
</Content>
</ZApplication>``````
K