tick method
- double dt
Advances by dt seconds. Returns whether value changed - false
once the chase has come to rest (after snapping exactly onto the
target once), so the owner can skip downstream work instead of
re-rendering epsilon motion every frame under a motionless
finger.
The frame is integrated in slices: semi-implicit Euler at this stiffness is stable only for steps under ~sqrt(stiffness)/0.83 seconds, and a 30 fps frame is already past that - one whole-frame step would make the chase diverge with growing oscillation instead of converging.
Implementation
bool tick(double dt) {
if (_resting || dt <= 0) {
return false;
}
final double maxStep = 0.25 / math.sqrt(stiffness);
final double damping = 2 * math.sqrt(stiffness);
double remaining = dt;
while (remaining > 0) {
final Offset delta = _target - value;
if (delta.distanceSquared < 0.01 && velocity.distanceSquared < 0.25) {
value = _target;
velocity = .zero;
_resting = true;
return true;
}
final double h = remaining < maxStep ? remaining : maxStep;
velocity += (delta * stiffness - velocity * damping) * h;
value += velocity * h;
remaining -= h;
}
return true;
}