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.
Tiled world with smooth movement transitions
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Tiled world with smooth movement transitions
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.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.
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.
Re: Tiled world with smooth movement transitions
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".
Re: Tiled world with smooth movement transitions
That's the fourth formulation I suggested:
Code: Select all
return t == 1 and b or a + (b - a) * t
Code: Select all
return t < 0.5 and a + (b - a) * t or b - (b - a) * (1 - t)
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
Re: Tiled world with smooth movement transitions
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.pgimeno wrote: ↑Wed Aug 31, 2022 4:06 pmThat's the fourth formulation I suggested:
Code: Select all
return t == 1 and b or a + (b - a) * t
Any code samples/ideas by me should be considered Public Domain (no attribution needed) license unless otherwise stated.
Re: Tiled world with smooth movement transitions
See the post immediately before yours. Sometimes it's desirable that t > 1.
Re: Tiled world with smooth movement transitions
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:
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'.
Re: Tiled world with smooth movement transitions
Facepalm
Guess I'm still learning how to read.
Thanks!
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.
Re: Tiled world with smooth movement transitions
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
Re: Tiled world with smooth movement transitions
@pgimeno this function of yours here to calculate the magic factor:
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/7x8fwjgnptpgimeno wrote: ↑Fri Apr 29, 2016 1:43 amCode: 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
Who is online
Users browsing this forum: Ahrefs [Bot], dewgstrom and 4 guests