我正在尝试在代码中模拟动画效果(几乎所有语言都可以,因为它似乎是数学而不是语言)。本质上,它是质量 Spring 系统的仿真。我一直在看WPF/Silverlight的ElasticEase
,这似乎与我要寻找的非常接近,但并不完全相同。
首先,这就是我要寻找的东西-一个物体,走了一定的几秒钟,撞到一个位置,立即减速了几秒钟,以使其在施加阻尼的同一点静止。因此,要形象化,可以说我有一个600w/900h的 Canvas ,并且有一个正方形,开始在TranslateTransform.Y
中从900px变为150px。它需要4秒钟才能达到150像素的高度(每秒187.5像素),在此阶段它立即受到阻尼,仅在0.4秒钟(每秒87.5像素)的情况下再移动约35像素,达到115像素的高度,然后反弹1秒钟,达到163像素的高度(每秒48px和48px),然后回升到146px(每秒17px和17px),依此类推,直到碰撞将其减慢到最终的静止位置150px。阻塞时间为16秒。
我上面描述的示例是此处的左上方蓝色矩形:
这是我预先知道的-像素距离和从点A到点B所需的秒数,即发生遮挡的秒数。像质量这样的事情似乎并不重要。
我已经尝试过ElasticEase
,问题似乎是我无法在4秒钟内不放松地移动对象,然后在接下来的16秒钟内“弹跳”。即使我将.Springiness
设置为一个非常高的数字(如20),它也总是太多。
ILSpy show的功能如下:
protected override double EaseInCore(double normalizedTime)
{
double num = Math.Max(0.0, (double)this.Oscillations);
double num2 = Math.Max(0.0, this.Springiness);
double num3;
if (DoubleUtil.IsZero(num2))
{
num3 = normalizedTime;
}
else
{
num3 = (Math.Exp(num2 * normalizedTime) - 1.0) / (Math.Exp(num2) - 1.0);
}
return num3 * Math.Sin((6.2831853071795862 * num + 1.5707963267948966) * normalizedTime);
}
我在DropBox的压缩文件夹中包括2个视频和一个Excel文件。我猜这个问题将随着人们提出更明确的问题而更多地在进行中。
(免责声明:关于其中大部分内容,我不知道我在说什么)
最佳答案
跳过物理学,直接进入方程式。
参数:
“这是我事先知道的-从点A到点B所需的像素距离[D]和秒数[T0],以及振荡[T1]的秒数。”另外,我将添加为自由参数:振荡的最大大小Amax,阻尼时间常数Tc和帧速率Rf,即在什么时候需要一个新的位置值。我假设您不想永远计算这个,所以我只做10秒,Ttotal,但是有各种合理的停止条件...
代码:
这是代码(在Python中)。最主要的是在def Y(t)
中找到的等式:
from numpy import pi, arange, sin, exp
Ystart, D = 900., 900.-150. # all time units in seconds, distance in pixels, Rf in frames/second
T0, T1, Tc, Amax, Rf, Ttotal = 5., 2., 2., 90., 30., 10.
A0 = Amax*(D/T0)*(4./(900-150)) # basically a momentum... scales the size of the oscillation with the speed
def Y(t):
if t<T0: # linear part
y = Ystart-(D/T0)*t
else: # decaying oscillations
y = Ystart-D-A0*sin((2*pi/T1)*(t-T0))*exp(-abs(T0-t)/Tc)
return y
y_result = []
for t in arange(0, Ttotal, 1./Rf): # or one could do "for i in range(int(Ttotal*Rf))" to stick with ints
y = Y(t)
y_result.append(y)
这个想法是线性运动到点,然后是衰减的振荡。振荡由
sin
提供,衰减由exp
乘以提供。当然,更改参数以获得所需的任何距离,振荡大小等。笔记:
冒着使它变得太长的风险,我意识到我可以在GIMP中制作gif,因此它是这样的:
如果有兴趣的话,我可以发布完整的代码来绘制图表,但是基本上,我只是在每个时间步使用不同的D和T0值调用Y。如果我要再次执行此操作,则可以增加阻尼(即降低Tc),但这有点麻烦,所以我将其保留。
关于wpf - Spring 质量系统的阻尼效应(或这是ElasticEase吗?),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7365090/