Allow me to start with some very important basics: the difference between Speed and Steps.

Speed = Distance / Second. Assume that Distance is the same. One second just is the same on any device everywhere in the world. Hence, Speed is the same on any device.

Its units = Pixels / Second.

You will find Speed as property in the behaviors. Speed for Bullet, by instance is in Pixels / Second. Hence a bullet moves at the same speed on any device.

Steps = Distance / Tick. No tick is the same length on every device. Depends on the FPS the game is running in. So you cant call this 'speed'.

The relation between Speed and Steps is simple. It is just :

Steps = Speed * dt.

So if you bring the same sprite in a layout. One with a bullet behavior with a speed property of 400. And the other you move with 'move forward' in steps 400 * dt. You will see that they move at the same speed.

In my example, the speed is written as an instance variable on Sprite 'thing'. It is in Pixel / Second units.

Since i gonna use 'lerp' i need Steps. Meaning an amount of pixels to move every tick so that the resulting speed = thing.speed.

In my example i only move over X to simplify the example. It is basically the same for Y.

Also, lerp is in the form of lerp(A,B,%). In the example A and B are static. It is a whole other story when A and/or B are dynamic, like a camera chasing a player. % stand for a number between 0 and 1 (2 will overshoot the destination by B-A). 0 = start position. 0.5 = half way. 1 = end position.

Since A and B are static, i know the distance that will be moved. And since i nailed the speed .. The time it will take to move that distance = distance / speed.

If i read your post, that is what you gonna need.

So i know the time, now i can just start a timer. When you start a timer ("tag"), its Expression Object.Timer.CurrentTime("tag") gives me the elapsed time in seconds.thousands.

This timer ticks the same seconds away on any device (when its FPS stays above the minimum allowed).

But now the lerp(A,B,%) needs a % between 0 and 1. So if we start a timer for 5 seconds, we need to normalize this to a range (0 - 1). Now 5 / 5 = 1. Simple as that. So normalized CurrentTime = Object.Timer.CurrentTime("tag") / the time it will take in the end.

That is what i stored in the local variable t.

So t = Sprite.Timer.CurrentTime("tag") / Sprite.ExpectedTime and returns a number between 0 an 1

So the lerp is now as simple as lerp(Sprite.StartX, Sprite.StartX + distance, t) for a linear movement.

Since t is calculated coming from a timer that runs the same on any device, t is truly ALWAYS non frame independent.

t = pixels / tick. It is Steps derived from Speed.

t is not the same number on any device, simple because the lerp is executed more times / second on a fast device compared to a slow device.

So, now we have linear covered.

The others are just the same. They just change t (the steps) with a non linear mathematical formula.

They change t in a way that zero is still zero and 1 is still 1 in the range (0 - 1)

That is the value dtt. I like 'dt' more as name for that value, but that is taken by the system.

So if you look at the quad ...

dtt = t<0.5 ? 2*t*t : -1+(4-2*t)*t

When t = lower then 0.5 (it goes in a range from 0 to 1), so when it is not halfway yet ... this returns ...

2*t*t (halfway this = 2 * 0.5 * 0.5 .. or still 0.5)

More then half it returns

-1+(4-2*t)*t

Those formulas you just find on the internet. I did. Figuring them out is to much math for me. But i can copy past / adapt.

Hope that helps.