Actionscript 3 基于速度的动态滚动(动量)持续时间?

Actionscript 3 基于速度的动态滚动(动量)持续时间?,actionscript-3,math,scroll,velocity,Actionscript 3,Math,Scroll,Velocity,我试图实现列表对象的动态滚动,但在基于速度确定要应用的摩擦量(持续时间)时遇到问题 我的applyFriction()方法根据duration属性均匀地降低滚动对象的速度。但是,对每个动作使用相同的持续时间(即:1秒)并不自然 对于速度较小(即:5-10像素)的运动,1秒的持续时间看起来很好,但对于速度较大(即:100+像素)的运动,在1秒的持续时间内施加摩擦力,滚动对象将看起来变慢,停止得更快 本质上,我试图为每个运动确定适当的持续时间,这样小的和大的速度都将共享一个匹配的摩擦力,这样运动的物

我试图实现列表对象的动态滚动,但在基于速度确定要应用的摩擦量(持续时间)时遇到问题

我的applyFriction()方法根据duration属性均匀地降低滚动对象的速度。但是,对每个动作使用相同的持续时间(即:1秒)并不自然

对于速度较小(即:5-10像素)的运动,1秒的持续时间看起来很好,但对于速度较大(即:100+像素)的运动,在1秒的持续时间内施加摩擦力,滚动对象将看起来变慢,停止得更快

本质上,我试图为每个运动确定适当的持续时间,这样小的和大的速度都将共享一个匹配的摩擦力,这样运动的物体看起来总是有一个恒定的“重量”

是否有基于不同速度确定运动持续时间的通用算法



注意:我正在ActionScript 3.0中编程,并使用Tween类在一段时间内降低移动对象的速度。

一个更好的摩擦力模型是摩擦力与速度成比例。需要一个常数来确定力和加速度(质量,或多或少)之间的关系。将这些关系写成差分方程

F[n] = -gamma * v[n-1]
a[n] = F[n]/m
v[n] = v[n-1] + dt * a[n]
     = v[n-1] + dt * F[n] / m
     = v[n-1] - dt * gamma * v[n-1] / m
     = v[n-1] * (1 - dt*gamma/m)
所以,如果你想让你的减速看起来平滑自然,而不是线性降低你的速度,你需要选择一个略小于1的常数,然后用这个常数重复乘以速度。当然,这只是渐进地接近零,所以你可能想要有一个阈值,低于这个阈值,你只需要将速度设置为零

例如:

v_epsilon = <some minimum velocity>;
k_frict = 0.9; // play around with this a bit

while (v > v_epsilon) {
    v = v * k_frict;
    usleep(1000);
}

v = 0;
v_epsilon=;
k_frict=0.9;//玩一下这个
while(v>v_ε){
v=v*k_摩擦;
usleep(1000);
}
v=0;
我想你会发现这看起来更自然

如果你想用线性减速来近似这个,那么你需要使你花在减速上的时间与初始速度的自然对数成比例。这看起来不太对劲,但会比你现在拥有的好一些


(为什么是自然对数?因为与速度成比例的摩擦力建立了一阶微分方程,它给出了exp(-t/tau)类响应,其中tau是系统的特征。在这样的系统中,从任意速度到给定极限的衰减时间与ln(v_init)成比例。)

我以前研究过这个问题:为什么安卓动量滚动感觉不如iPhone好

幸运的是:

具有动量滚动和减速的flick列表


当我开始研究这个问题时,我没有仔细注意iPhone上滚动的工作方式。我只是假设减速是基于,也就是说,一个移动的物体受到摩擦,一段时间后被迫停止。过了一会儿,我意识到这实际上是iPhone(以及后来的iOS设备,如iPad)的做法。我用相机拍摄了几十个不同iOS应用程序的滚动运动,在相同的时间后,所有的滚动都会停止,而不管列表的大小或电影的速度如何。轻弹的速度(决定滚动的初始速度)只决定列表将在哪里停止,而不是何时停止

这使他得到了大大简化的数学:

amplitude = initialVelocity * scaleFactor;
step = 0;

ticker = setInterval(function() {
    var delta = amplitude / timeConstant;
    position += delta;
    amplitude -= delta;
    step += 1;
    if (step > 6 * timeConstant) {
        clearInterval(ticker);
    }
}, updateInterval);
事实上,这就是减速在苹果自己的库(现在)中的实现方式。对于每个动画滴答声(16.7毫秒,目标为60帧/秒),它会将滚动速度降低一倍
0.95
。这对应于325毫秒的时间常数。如果你是一个数学怪人,那么很明显你会意识到滚动速度的指数性质会导致位置的指数衰减。通过一点涂鸦,最终你会发现

325 = -16.7ms / ln(0.95)
提出动议:


您的问题是关于要使用的持续时间。我喜欢iPhone的感觉(相对于Android)。我认为你应该使用:


的确模拟摩擦会产生很多奇怪的行为,例如,粘滞(摩擦力完全等于外部施加的力,直到超过阈值)、阻力(v^2),等等。
- (1000 ms / 60) / ln(0.95) * 6 = 1950 ms