// Based on https://github.com/chmike/fpsqrt public static Fixed65536 Sqrt(Fixed65536 v) { if (v.value65536 < 0) { throw new InvalidOperationException(); } uint r = (uint)v.value65536; uint b = 0x40000000; uint q = 0; while (b > 0x40) { uint t = q + b; if (r >= t) { r -= t; q = t + b; // equivalent to q += 2*b } r <<= 1; b >>= 1; } q >>= 8; return(new Fixed65536((int)q)); }
public static PackedVelocity ToReachHeight(int height, int gravity256) { // v^2 = u^2 + 2as // v = 0 at top of jump // 0 = u^2 + 2as // u = sqrt(-2as) // For fixed-point gravity and velocity (this is the old version): // // u*256 = sqrt(-2 (a*256)/256 s) * 256 // u*256 = sqrt(-2 (a*256) s) * 16 // Using fixed-point sqrt: // // u*256 = sqrt(-2 (a*256)/256 s) * 256 // u*256 = sqrt(-2 (a*256) s) * 16 // u*256 = FPSR(-2 (a*256) s)/65536 * 16 // u*256 = FPSR(-2 (a*256) s)/65536 * 16 // u*256 = FPSR(-2 (a*256) s) / 4096 // u*256 = FPSR(-2 (a*256) s) >> 12 int velocity256 = Fixed65536.Sqrt(-2 * gravity256 * height).value65536 >> 12; // NOTE: TEMP: Validate that my maths is more-or-less correct (matches old code) -AR Debug.Assert(System.Math.Abs(velocity256 - (int)System.Math.Round(System.Math.Sqrt(-2.0 * gravity256 * height) * 16)) < 10); return(new PackedVelocity(velocity256)); }
/// <summary>Round up for positive values</summary> public Fixed65536 PositiveRoundUp(Fixed65536 toNearest) { int tn = toNearest.value65536; return(new Fixed65536(((value65536 + tn - 1) / tn) * tn)); }