Tiled world with smooth movement transitions

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
darkfrei
Party member
Posts: 1168
Joined: Sat Feb 08, 2020 11:09 pm

Re: Tiled world with smooth movement transitions

Post by darkfrei »

So we can use the floatPosition where it's just a summary of previous floatPosition and dt*floatVelocity.
The stepPosition (in pixels) can be just integer as math.floor (floatPosition+0.5) or in tiles (where tileSize is 64 pixels) fine fraction as math.floor (floatPosition*64+0.5)/64. It looks smooth as float, but precise as integer.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: Tiled world with smooth movement transitions

Post by pgimeno »

RNavega wrote: Wed Aug 31, 2022 4:34 am @pgimeno thanks a lot for the insights on the variants of LERP. If I understood you right, it's okay to freely use the optimized form (a + (b-a) * t) in your game, provided that you:
1) Don't assume that the result will have the exact values of A or B, even if t is 0 or 1. It'll be extremely close (to the point of not being noticeable by the viewer), just not floating-point equal.
When t is 0 there's no problem at all: (b-a)*0 is guaranteed to be 0, and a+0 is guaranteed to be a. The problem appears only when t is 1, because b - a + a is not guaranteed to be b.

If you floor the result (which is pretty common when using it for graphics), the coordinate may be off by 1 pixel, and that will probably be noticeable. Fortunately it's not very likely that b - a + a does not equal b when both a and b are integer; that would only happen for very big a, in the order of 2^54 or more, and comparatively small b.
RNavega
Party member
Posts: 235
Joined: Sun Aug 16, 2020 1:28 pm

Re: Tiled world with smooth movement transitions

Post by RNavega »

pgimeno wrote: Wed Aug 31, 2022 11:06 am If you floor the result (which is pretty common when using it for graphics), the coordinate may be off by 1 pixel, and that will probably be noticeable.
Ah, I see what you mean, thanks man.
If you have like a pixel art game, and you set b to 10 but the interpolated result is 9.999(...) and gets truncated to 9, that will be noticeable.

The only solution I can think of would be to have the interpolation code special-case to return b directly -- the condition being if t >= 1.0, or if the interp. speed is positive (so the destination of t is 1) and its state is considered "finished".
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: Tiled world with smooth movement transitions

Post by pgimeno »

RNavega wrote: Wed Aug 31, 2022 1:54 pm The only solution I can think of would be to have the interpolation code special-case to return b directly -- the condition being if t >= 1.0, or if the interp. speed is positive (so the destination of t is 1) and its state is considered "finished".
That's the fourth formulation I suggested:

Code: Select all

return t == 1 and b or a + (b - a) * t
The third one is thoroughly tested for violations of monotonicity in the transition from t=0.49999999999999994 (the number just before 0.5) to t=0.5 and none was discovered. This one gives the exact values when t = 0 and t = 1.

Code: Select all

return t < 0.5 and a + (b - a) * t or b - (b - a) * (1 - t)
As for limiting t, that may not be desirable in some applications. Lerp is often used for tweening, where the easing is provided by a function that takes a linear t in 0..1 and transforms it to non-linear for lerping. For example:

Code: Select all

local function ease_smoothstep(t)
  return 3*t^2-2*t^3
end

function tween.smoothstep(a, b, t)
  return lerp(a, b, ease_smoothstep(t))
end

local function ease_outback(t)
  t = 1-t
  return 1-t*t*(t+(t-1)*1.701540198866824)
end

function tween.outback(a, b, t)
  return lerp(a, b, ease_outback(t))
end
The last one, outback, goes a bit past b and then comes back to land on b (that weird magic number is adjusted so that it goes exactly 10% past b); to do that, the easing function produces, and thus the lerp function receives, t > 1.
User avatar
milon
Party member
Posts: 472
Joined: Thu Jan 18, 2018 9:14 pm

Re: Tiled world with smooth movement transitions

Post by milon »

pgimeno wrote: Wed Aug 31, 2022 4:06 pm
RNavega wrote: Wed Aug 31, 2022 1:54 pm The only solution I can think of would be to have the interpolation code special-case to return b directly -- the condition being if t >= 1.0, or if the interp. speed is positive (so the destination of t is 1) and its state is considered "finished".
That's the fourth formulation I suggested:

Code: Select all

return t == 1 and b or a + (b - a) * t
Is there any particular reason to use == instead of >= in the above? I would think >= is more robust, depending on implementation. It's probably got the exact same computational expense too, but correct me if I'm wrong.
Any code samples/ideas by me should be considered Public Domain (no attribution needed) license unless otherwise stated.
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: Tiled world with smooth movement transitions

Post by pgimeno »

milon wrote: Tue Sep 06, 2022 2:37 pm Is there any particular reason to use == instead of >= in the above? I would think >= is more robust, depending on implementation. It's probably got the exact same computational expense too, but correct me if I'm wrong.
See the post immediately before yours. Sometimes it's desirable that t > 1.
RNavega
Party member
Posts: 235
Joined: Sun Aug 16, 2020 1:28 pm

Re: Tiled world with smooth movement transitions

Post by RNavega »

milon wrote: Tue Sep 06, 2022 2:37 pm Is there any particular reason to use == instead of >= in the above? I would think >= is more robust, depending on implementation. It's probably got the exact same computational expense too, but correct me if I'm wrong.
What Pedro meant with that example is that it's important for some effects for t to under/overshoot the [0, 1] range, like the "ease in/out back" easings:

Image

However, if you must keep your t in the [0, 1] range, you can still have these out-of-range easings if you use another internal t that only your interpolation helper knows about, with rules like these:
- The input t is expected to be in the [0, 1] range, and anything outside of that is undefined behavior / error.
- The internal t (t' if you will) can have any value, it can under/overshoot etc. and is the result of the input t being interpolated with some easing function.
- When checking if the lerp is finished, test the input t. To calculate the lerp, use t'.
User avatar
milon
Party member
Posts: 472
Joined: Thu Jan 18, 2018 9:14 pm

Re: Tiled world with smooth movement transitions

Post by milon »

pgimeno wrote: Tue Sep 06, 2022 7:28 pm
milon wrote: Tue Sep 06, 2022 2:37 pm Is there any particular reason to use == instead of >= in the above? I would think >= is more robust, depending on implementation. It's probably got the exact same computational expense too, but correct me if I'm wrong.
See the post immediately before yours. Sometimes it's desirable that t > 1.
Facepalm
Guess I'm still learning how to read. :crazy:
Thanks!

RNavega wrote: Tue Sep 06, 2022 9:22 pm
milon wrote: Tue Sep 06, 2022 2:37 pm Is there any particular reason to use == instead of >= in the above? I would think >= is more robust, depending on implementation. It's probably got the exact same computational expense too, but correct me if I'm wrong.
What Pedro meant with that example is that it's important for some effects for t to under/overshoot the [0, 1] range, like the "ease in/out back" easings...
Thanks for the detailed reply. I honestly just missed the second half of his post somehow. But it's a nice explanation that beautifully shows the concept! :)
Any code samples/ideas by me should be considered Public Domain (no attribution needed) license unless otherwise stated.
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: Tiled world with smooth movement transitions

Post by pgimeno »

This is an example of use of the actual outback function I had in mind (the formula I posted above). It has humorous uses; you can imagine an accompanying screeching tyre sound. In this post I give a formula to calculate a different outback constant given a percent of overshoot: viewtopic.php?p=198129#p198129 (see calc_outback_param).

Code: Select all

local timer = 0
local total_time = 2
local stop_time = 1

local start_x, end_x, y = 0, 650, 300

local function lerp(a, b, t)
  return t < 0.5 and a + (b - a) * t or b + (a - b) * (1 - t)
end

local function ease_outback(t)
  t = 1-t
  return 1-t*t*(t+(t-1)*1.701540198866824)
end

local function tween_outback(a, b, t)
  return lerp(a, b, ease_outback(t))
end

local frame=0
function love.update(dt)
--  dt = i==0 and 0 or 1/15; frame=frame+1;love.graphics.captureScreenshot(("screenshot%02d.png"):format(frame))
  timer = timer + dt
  if timer >= total_time then
    timer = timer - total_time
  end
end

function love.draw()
  local t = timer / stop_time
  if t > 1 then t = 1 end
  love.graphics.circle("fill", tween_outback(start_x, end_x, t), y, 15)

  love.graphics.rectangle("fill", start_x, y + 20, 1, 20)
  love.graphics.print("Start\nposition", start_x, y + 50)
  love.graphics.rectangle("fill", end_x, y + 20, 1, 20)
  love.graphics.print("Target\nposition", end_x, y + 50)
end
Attachments
outback.gif
outback.gif (3.91 KiB) Viewed 2569 times
RNavega
Party member
Posts: 235
Joined: Sun Aug 16, 2020 1:28 pm

Re: Tiled world with smooth movement transitions

Post by RNavega »

@pgimeno this function of yours here to calculate the magic factor:
pgimeno wrote: Fri Apr 29, 2016 1:43 am

Code: Select all

function calc_outback_param(h)
  local P = (91.125*h + 410.0625*h^2 + 307.546875*h^3
             + 0.5*math.sqrt(33215.0625*h^2*(h + 1))
            )^(1/3)
  return 2.25*h + (13.5*h + 15.1875*h^2)/P + P/3
end
Do you know the reasoning behind it? When I was researching this a while ago I only found a Japanese blog post explaining how it's the factor for a polynomial curve, something like that. It was too complicated for me so I used an online web plotter like Desmos to calibrate the parameter (adjusting the overshoot), a graph like this: https://www.desmos.com/calculator/7x8fwjgnpt
Post Reply

Who is online

Users browsing this forum: No registered users and 17 guests