Создание кубической кривой замедления динамически меняет положение цели - PullRequest
0 голосов
/ 22 февраля 2019

Используя 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.Теперь, давайте также предположим, что внезапно «maxs» резко поднялся до 0,25, так что теперь у нас есть новая цель, которую нужно достичь.

Мой текущий подход к обработке ситуаций, подобных приведенным выше, состоит в том, чтобы сбросить наше «время»переменная и измените «мин» на наше текущее значение;в приведенном выше случае 0,75 и т. д. Однако это приводит к очень заметным «остановкам» или «остановкам» в анимации, поскольку они полностью сбрасываются.

У меня вопрос, какя могу сделать это динамически без этой остановки?Я бы хотел, чтобы он плавно перешел от одного номера цели к другому.

1 Ответ

0 голосов
/ 22 февраля 2019
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
...