step method

void step(
  1. double dt, {
  2. required double speed,
  3. required bool grounded,
})

Advances the bob and the recoil by one simulation step.

speed is the player's horizontal speed, and grounded whether their feet are down: a weapon that keeps swaying while the player is in mid-air is the detail that makes a jump feel weightless.

Implementation

void step(double dt, {required double speed, required bool grounded}) {
  if (grounded && speed > 0.2) {
    _bobPhase += dt * _bobSpeed * (speed / 6.0).clamp(0.3, 1.8);
    _bobOffset = math.sin(_bobPhase) * _bobAmount;
  } else {
    // Eased back to centre rather than snapped: stopping dead mid-swing is
    // more noticeable than the sway itself.
    _bobOffset += (0.0 - _bobOffset) * easeFactor(8.0, dt);
  }

  if (_recoil > 0.0) {
    _recoil -= _recoilRecovery * dt;
    if (_recoil < 0.0) _recoil = 0.0;
  }

  _holder.setPosition(
    _restPosition.x,
    _restPosition.y + _bobOffset,
    // Back towards the eye, and slightly up: a straight backwards kick reads
    // as the weapon shrinking.
    _restPosition.z + _recoil * _recoilKick,
  );
  _holder.setRotation(
    Quaternion.axisAngle(Vector3(1.0, 0.0, 0.0), _recoil * 0.22),
  );
}