在更新循环中实现轻松

Nim*_*har 1 objective-c easing

我想以某种减速方式将精灵从点y1动画到点y2.当它到达点y2时,物体的速度将为0,因此它将完全停止.

我知道这两点,我知道对象的起始速度.动画时间对我来说并不那么重要.如果需要,我可以决定.

例如:y1 = 0,y2 = 400,v0 = 250每秒像素(=起始速度)

我读到了关于缓动函数但我不明白如何在更新循环中实际实现它.这是我的更新循环代码,应该以某种方式实现缓动函数.

-(void)onTimerTick{
   double currentTime =  CFAbsoluteTimeGetCurrent() ;
   float timeDelta = self.lastUpdateTime - currentTime;
   self.lastUpdateTime = currentTime;

   float *pixelsToMove = ???? // here needs to be some formula using v0, timeDelta, y2, y1

   sprite.y +=  pixelsToMove;
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ist 6

定时功能为Bézier曲线

缓和定时功能基本上是Bézier曲线(0,0),(1,1)其中水平轴是"时间"而垂直轴是"变化量".由于贝塞尔曲线在数学上是如此

start*(1-t)^3 + c1*t(1-t)^2 + c2*t^2(1-t) + end*t^3 
Run Code Online (Sandbox Code Playgroud)

您可以插入任何时间值并获取应该应用的更改量.请注意,时间和变化都是标准化的(范围为0到1).

请注意,变量t 不是时间值,t是沿曲线的距离.时间值是沿曲线的点的x值.


下面的曲线是一个样本"缓和"曲线,它开始变慢,变速更快,最后变慢.

例如,如果三分之一的时间已经过去,您将计算相应的更改量,以更新动画属性的值

currentValue = beginValue + amountOfChange*(endValue-beginValue)
Run Code Online (Sandbox Code Playgroud)

Bézier曲线用于

说你是从动画的位置(50, 50),以(200, 150)在使用具有控制点的曲线(0.6, 0.0)(0.5, 0.9)与4秒的持续时间(控制点试图接近该图像的上文).

当动画1秒已经过去(总的持续时间的25%)的值沿所述曲线是:

(0.25,y) = (0,0)*(1-t)^3 + (0.6,0)*t(1-t)^2 + (0.5,0.9)*t^2(1-t) + (1,1)*t^3
Run Code Online (Sandbox Code Playgroud)

这意味着我们可以计算t为:

0.25 = 0.6*t(1-t)^2 + 0.5*t^2(1-t) + t^3
Run Code Online (Sandbox Code Playgroud)

Wolfram Alpha的告诉我t = 0.482359

如果输入的是t

y = 0.9*t^2*(1-t) + t^3
Run Code Online (Sandbox Code Playgroud)

我们将获得持续时间1秒的"变化量".

Wolfram Alpha再一次告诉我,y = 0.220626这意味着22%的价值在25%的时间后发生了变化.这是因为曲线开始缓慢(您可以在图像中看到它在开始时大部分是平坦的).

所以最后:1秒进入动画的位置

(x, y) = (50, 50) + 0.220626 * (200-50, 150-50)
(x, y) = (50, 50) + 0.220626 * (150, 100)
(x, y) = (50, 50) + (33.0939, 22.0626)
(x, y) = (50+33.0939, 50+22.0626)
(x, y) = (83.0939, 72.0626)
Run Code Online (Sandbox Code Playgroud)

我希望这个例子可以帮助您了解如何使用计时功能.