Создание кубической кривой замедления динамически меняет положение цели
Используя Lua, я сделал функцию для кубической (ослабление /"ускорение", затем ослабление /"замедление" впоследствии) интерполяции от одного числа к другому; SimpleSpline принимает число от 0 до 1 (время, когда анимация запускается, проще всего положить), а SimpleSplineBetween делает то же самое, но сохраняет его между двумя заданными минимальными / максимальными значениями.
function SimpleSpline( v )
local vSquared = v*v
return (3 * vSquared - 2 * vSquared * v)
end
function SimpleSplineBetween( mins, maxs, v )
local fraction = SimpleSpline( v )
return (maxs * fraction + mins * (1 - fraction))
end
Все отлично работает. Однако я столкнулся с небольшой проблемой. Я хотел бы, чтобы это было немного более динамичным. Например, предположим, что мои "mins" равны 0,5, а мои "maxs" равны 1, тогда у меня есть переменная времени, которую я передаю как V; мы скажем, что это 0,5, поэтому наше текущее значение интерполяции составляет 0,75. Теперь, давайте также предположим, что внезапно "макс" поднялся до 0,25, так что теперь у нас есть новая цель, которую нужно достичь.
Мой текущий подход к обработке ситуаций, подобных описанным выше, состоит в том, чтобы сбросить нашу переменную time и заменить min на наше текущее значение; в приведенном выше случае 0,75 и т. д. Однако это приводит к очень заметному "останову" или "остановке" в анимации, поскольку она полностью сбрасывается.
У меня вопрос, как я могу сделать это динамично без этой остановки? Я бы хотел, чтобы он плавно перешел от одного номера ворот к другому.
1 ответ
local Start_New_Spline, Calculate_Point_on_Spline, Recalculate_Old_Spline
do
local current_spline_params
local function Start_New_Spline(froms, tos)
current_spline_params = {d=0, froms=froms, h=tos-froms, last_v=0}
end
local function Calculate_Point_on_Spline(v) -- v = 0...1
v = v < 0 and 0 or v > 1 and 1 or v
local d = current_spline_params.d
local h = current_spline_params.h
local froms = current_spline_params.froms
current_spline_params.last_v = v
return (((d-2*h)*v+3*h-2*d)*v+d)*v+froms
end
local function Recalculate_Old_Spline(new_tos)
local d = current_spline_params.d
local v = current_spline_params.last_v
local h = current_spline_params.h
local froms = current_spline_params.froms
froms = (((d-2*h)*v+3*h-2*d)*v+d)*v+froms
d = ((3*d-6*h)*v+6*h-4*d)*v+d
current_spline_params = {d=d, froms=froms, h=new_tos-froms, last_v=0}
end
end
Пример использования в соответствии с вашими ценностями:
Start_New_Spline(0.5, 1) -- "mins" is 0.5, "maxs" is 1
local inside_spline = true
while inside_spline do
local goal_has_changed = false
for time = 0, 1, 0.015625 do -- time = 0...1
-- It's time to draw next frame
goal_has_changed = set to true when goal is changed
if goal_has_changed then
-- time == 0.5 -> s == 0.75, suddenly "maxs" is jerked up to 0.25
Recalculate_Old_Spline(0.25) -- 0.25 is the new goal
-- after recalculation, "time" must be started again from zero
break -- exiting this loop
end
local s = Calculate_Point_on_Spline(time) -- s = mins...maxs
Draw_something_at_position(s)
wait()
end
if not goal_has_changed then
inside_spline = false
end
end