Skip to content

Instantly share code, notes, and snippets.

@debreuil
Created February 3, 2015 22:50
Show Gist options
  • Save debreuil/95de1292289166e16e3a to your computer and use it in GitHub Desktop.
Save debreuil/95de1292289166e16e3a to your computer and use it in GitHub Desktop.
Pixate spring implementation
// Evaluates one tick of a spring using the Runge-Kutta Algorithm.
// This is generally a bit mathy, here is a reasonable intro for those interested:
// http://gafferongames.com/game-physics/integration-basics/
// (double)stepSize: the duration between steps. This should be around 1/60th of a second. Values too large will not work as the spring adjusts itself over time based on previous values, so if values are larger than 1/60th of a second this method should be called for each whole 1/60th of a second segment plus the remainder.
// external variables
// (double) _curT: How far along the spring the current value is, 0 being start and 1 being end. Because this is a spring that value will go beyond 1 and then back below 1 etc, as it 'springs'.
// (double) _tVelocity: the current velocity of the spring.
// (BOOL) _stopSpring: indicates the spring has settled to minimum amount and should be considered the last 'tick'
- (void)evaluateRK:(double)stepSize
{
double x = _curT - 1;
double v = _tVelocity;
double aDx = v;
double aDv = [self accelerateX:x vel:v];
double bDx = v + aDv * (stepSize * 0.5);
double bDv = [self accelerateX:x + aDx * (stepSize * 0.5) vel:bDx];
double cDx = v + bDv * (stepSize * 0.5);
double cDv = [self accelerateX:x + bDx * (stepSize * 0.5) vel:cDx];
double dDx = v + cDv * stepSize;
double dDv = [self accelerateX:x + cDx * stepSize vel:dDx];
double dxdt = 1.0 / 6.0 * (aDx + 2.0 * (bDx + cDx) + dDx);
double dvdt = 1.0 / 6.0 * (aDv + 2.0 * (bDv + cDv) + dDv);
double aftX = x + dxdt * stepSize;
double aftV = v + dvdt * stepSize;
_curT = 1 + aftX;
double finalVelocity = aftV;
double netFloat = aftX;
double net1DVelocity = aftV;
double netValueIsLow = fabs(netFloat) < _tolerance;
double netVelocityIsLow = fabs(net1DVelocity) < _tolerance;
_tVelocity = finalVelocity;
// never turn spring back on
if(!_stopSpring)
{
_stopSpring = netValueIsLow && netVelocityIsLow;
}
}
- (double) accelerateX:(double)x vel:(double)v
{
return -_tensionValue * x - _frictionValue * v;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment