Tod*_*ain 12 silverlight wpf animation physics
我试图在代码中模拟动画效果(几乎任何语言都可以,因为它似乎是数学而不是语言).从本质上讲,它是质量弹簧系统的仿真.我一直在看WPF/Silverlight ElasticEase,这看起来非常接近我正在寻找的东西,但并不完全.
首先,这里就是我要找的-一个对象,旅游若干秒,创下了位置,并立即下降放缓至ocsillate一定的秒数在涂敷阻尼的相同点休息.所以为了想象这个,让我说我有一个600w/900h的画布,我有一个正方形,开始动画从900px到150px TranslateTransform.Y.它需要4秒内达到150像素高度(每秒187.5px),在该阶段它被immediated阻尼并且仅行进大约35px更0.4秒(每秒87.5px)至115px高度,然后向下篮板1秒至163px高度(48px和48px每秒),然后回升到146px(17px和17px每秒),依此类推,直到ocillations减慢到最后150px的休息位置.ocirlation时间是16秒.
我上面描述的例子是左上角的蓝色矩形:

这是我事先知道的 - 像素距离和从A点到B点所需的秒数,即ocirlation的秒数.像质量这样的东西似乎并不重要.
我已经尝试ElasticEase了,问题似乎是我无法让对象在没有缓和4秒的情况下旅行,然后在接下来的16秒内"反弹".该.Springiness也总是太多,即使我将其设置为像20一个非常高的数字.
ILSpy展示其功能如下:
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);
}
Run Code Online (Sandbox Code Playgroud)
我在DropBox的压缩文件夹中包含了2个视频和一个Excel文件.我想这个问题将更多的是正在进行的工作,因为人们会提出更多澄清问题.
(免责声明:当涉及到大部分内容时,我不知道我在谈论什么)
跳过物理学,然后直接进入等式.
参数:"这是我事先知道的 - 像素距离[D]和从A点到B点所需的秒数[T0],振荡的秒数[T1]."另外,我ll作为自由参数添加:振荡的最大大小,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)
Run Code Online (Sandbox Code Playgroud)
这个想法是线性运动到达点,然后是衰减振荡.振荡由sin衰减和衰减提供exp.当然,更改参数以获得您想要的任何距离,振动大小等.

笔记:
冒这么长的风险,我意识到我可以在GIMP中制作一个gif,所以这就是它的样子:

如果有兴趣的话,我可以发布完整的代码来制作图,但基本上我只是为每个时间步用不同的D和T0值调用Y. 如果我再次这样做,我可以增加阻尼(即减少Tc),但这有点麻烦,所以我将其保留原样.
我和@ tom10一样思考着.(我也考虑IEasingFunction了一个IList<IEasingFunction>,但是从现有的行为中破解所需的行为会很棘手).
// Based on the example at
// http://msdn.microsoft.com/en-us/library/system.windows.media.animation.easingfunctionbase.aspx
namespace Org.CheddarMonk
{
public class OtakuEasingFunction : EasingFunctionBase
{
// The time proportion at which the cutoff from linear movement to
// bounce occurs. E.g. for a 4 second movement followed by a 16
// second bounce this would be 4 / (4 + 16) = 0.2.
private double _CutoffPoint;
public double CutoffPoint {
get { return _CutoffPoint; }
set {
if (value <= 0 || value => 1 || double.IsNaN(value)) {
throw new ArgumentException();
}
_CutoffPoint = value;
}
}
// The size of the initial bounce envelope, as a proportion of the
// animation distance. E.g. if the animation moves from 900 to 150
// and you want the maximum bounce to be no more than 35 you would
// set this to 35 / (900 - 150) ~= 0.0467.
private double _EnvelopeHeight;
public double EnvelopeHeight {
get { return _EnvelopeHeight; }
set {
if (value <= 0 || double.IsNaN(value)) {
throw new ArgumentException();
}
_EnvelopeHeight = value;
}
}
// A parameter controlling how fast the bounce height should decay.
// The higher the decay, the sooner the bounce becomes negligible.
private double _EnvelopeDecay;
public double EnvelopeDecay {
get { return _EnvelopeDecay; }
set {
if (value <= 0 || double.IsNaN(value)) {
throw new ArgumentException();
}
_EnvelopeDecay = value;
}
}
// The number of half-bounces.
private int _Oscillations;
public int Oscillations {
get { return _Oscillations; }
set {
if (value <= 0) {
throw new ArgumentException();
}
_Oscillations = value;
}
}
public OtakuEasingFunction() {
// Sensible default values.
CutoffPoint = 0.7;
EnvelopeHeight = 0.3;
EnvelopeDecay = 1;
Oscillations = 3;
}
protected override double EaseInCore(double normalizedTime) {
// If we get an out-of-bounds value, be nice.
if (normalizedTime < 0) return 0;
if (normalizedTime > 1) return 1;
if (normalizedTime < _CutoffPoint) {
return normalizedTime / _CutoffPoint;
}
// Renormalise the time.
double t = (normalizedTime - _CutoffPoint) / (1 - _CutoffPoint);
double envelope = EnvelopeHeight * Math.Exp(-t * EnvelopeDecay);
double bounce = Math.Sin(t * Oscillations * Math.PI);
return envelope * bounce;
}
protected override Freezable CreateInstanceCore() {
return new OtakuEasingFunction();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是未经测试的代码,但如果有问题,调试应该不会太糟糕.我不确定需要将哪些属性(如果有的话)添加到XAML编辑器的属性中才能正确处理它们.
| 归档时间: |
|
| 查看次数: |
1637 次 |
| 最近记录: |