如何使一个立方缓进缓出的曲线动态地改变目标位置

使用 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,那么我们有一个新的目标需要达到。

我目前处理像上面这样的情况的方法是重置我们的“时间”变量,并将“mins”更改为我们当前的值;在上述情况下,它是 0.75 等等。但是,这会产生一个非常明显的动画“停止”或“冻结”现象,因为它被完全重置了。

我的问题是,如何让它在没有停止的情况下变得更有前瞻性?我希望它能够从一个目标数字平稳地过渡到另一个目标数字。

点赞
用户6834680
用户6834680
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”为0.5,“maxs”为1
local inside_spline = true
while inside_spline do
   local goal_has_changed = false
   for time = 0, 1, 0.015625 do  -- time = 0...1
      -- 到了下一帧要绘制的时间
      goal_has_changed = 当目标改变时设置为ture
      if goal_has_changed then
         -- time == 0.5 ->  s == 0.75,突然“maxs”被拉到0.25
         Recalculate_Old_Spline(0.25-- 0.25是新目标
         -- 重新计算后,“time”必须从零开始
         break  -- 退出循环
      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
2019-02-22 11:42:25