A game framework written with osu! in mind.
at master 187 lines 7.7 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5 6namespace osu.Framework.Graphics.Transforms 7{ 8 /// <summary> 9 /// An easing function corresponding to one of the <see cref="Easing"/> types. 10 /// </summary> 11 public readonly struct DefaultEasingFunction : IEasingFunction 12 { 13 private const double elastic_const = 2 * Math.PI / .3; 14 private const double elastic_const2 = .3 / 4; 15 16 private const double back_const = 1.70158; 17 private const double back_const2 = back_const * 1.525; 18 19 private const double bounce_const = 1 / 2.75; 20 21 // constants used to fix expo and elastic curves to start/end at 0/1 22 private static readonly double expo_offset = Math.Pow(2, -10); 23 private static readonly double elastic_offset_full = Math.Pow(2, -11); 24 private static readonly double elastic_offset_half = Math.Pow(2, -10) * Math.Sin((.5 - elastic_const2) * elastic_const); 25 private static readonly double elastic_offset_quarter = Math.Pow(2, -10) * Math.Sin((.25 - elastic_const2) * elastic_const); 26 private static readonly double in_out_elastic_offset = Math.Pow(2, -10) * Math.Sin((1 - elastic_const2 * 1.5) * elastic_const / 1.5); 27 28 private readonly Easing easing; 29 30 /// <summary> 31 /// Creates a new <see cref="DefaultEasingFunction"/> for an <see cref="Easing"/>. 32 /// </summary> 33 /// <param name="easing">The <see cref="Easing"/> type.</param> 34 public DefaultEasingFunction(Easing easing) 35 { 36 this.easing = easing; 37 } 38 39 public double ApplyEasing(double time) 40 { 41 switch (easing) 42 { 43 default: 44 return time; 45 46 case Easing.In: 47 case Easing.InQuad: 48 return time * time; 49 50 case Easing.Out: 51 case Easing.OutQuad: 52 return time * (2 - time); 53 54 case Easing.InOutQuad: 55 if (time < .5) return time * time * 2; 56 57 return --time * time * -2 + 1; 58 59 case Easing.InCubic: 60 return time * time * time; 61 62 case Easing.OutCubic: 63 return --time * time * time + 1; 64 65 case Easing.InOutCubic: 66 if (time < .5) return time * time * time * 4; 67 68 return --time * time * time * 4 + 1; 69 70 case Easing.InQuart: 71 return time * time * time * time; 72 73 case Easing.OutQuart: 74 return 1 - --time * time * time * time; 75 76 case Easing.InOutQuart: 77 if (time < .5) return time * time * time * time * 8; 78 79 return --time * time * time * time * -8 + 1; 80 81 case Easing.InQuint: 82 return time * time * time * time * time; 83 84 case Easing.OutQuint: 85 return --time * time * time * time * time + 1; 86 87 case Easing.InOutQuint: 88 if (time < .5) return time * time * time * time * time * 16; 89 90 return --time * time * time * time * time * 16 + 1; 91 92 case Easing.InSine: 93 return 1 - Math.Cos(time * Math.PI * .5); 94 95 case Easing.OutSine: 96 return Math.Sin(time * Math.PI * .5); 97 98 case Easing.InOutSine: 99 return .5 - .5 * Math.Cos(Math.PI * time); 100 101 case Easing.InExpo: 102 return Math.Pow(2, 10 * (time - 1)) + expo_offset * (time - 1); 103 104 case Easing.OutExpo: 105 return -Math.Pow(2, -10 * time) + 1 + expo_offset * time; 106 107 case Easing.InOutExpo: 108 if (time < .5) return .5 * (Math.Pow(2, 20 * time - 10) + expo_offset * (2 * time - 1)); 109 110 return 1 - .5 * (Math.Pow(2, -20 * time + 10) + expo_offset * (-2 * time + 1)); 111 112 case Easing.InCirc: 113 return 1 - Math.Sqrt(1 - time * time); 114 115 case Easing.OutCirc: 116 return Math.Sqrt(1 - --time * time); 117 118 case Easing.InOutCirc: 119 if ((time *= 2) < 1) return .5 - .5 * Math.Sqrt(1 - time * time); 120 121 return .5 * Math.Sqrt(1 - (time -= 2) * time) + .5; 122 123 case Easing.InElastic: 124 return -Math.Pow(2, -10 + 10 * time) * Math.Sin((1 - elastic_const2 - time) * elastic_const) + elastic_offset_full * (1 - time); 125 126 case Easing.OutElastic: 127 return Math.Pow(2, -10 * time) * Math.Sin((time - elastic_const2) * elastic_const) + 1 - elastic_offset_full * time; 128 129 case Easing.OutElasticHalf: 130 return Math.Pow(2, -10 * time) * Math.Sin((.5 * time - elastic_const2) * elastic_const) + 1 - elastic_offset_half * time; 131 132 case Easing.OutElasticQuarter: 133 return Math.Pow(2, -10 * time) * Math.Sin((.25 * time - elastic_const2) * elastic_const) + 1 - elastic_offset_quarter * time; 134 135 case Easing.InOutElastic: 136 if ((time *= 2) < 1) 137 { 138 return -.5 * (Math.Pow(2, -10 + 10 * time) * Math.Sin((1 - elastic_const2 * 1.5 - time) * elastic_const / 1.5) 139 - in_out_elastic_offset * (1 - time)); 140 } 141 142 return .5 * (Math.Pow(2, -10 * --time) * Math.Sin((time - elastic_const2 * 1.5) * elastic_const / 1.5) 143 - in_out_elastic_offset * time) + 1; 144 145 case Easing.InBack: 146 return time * time * ((back_const + 1) * time - back_const); 147 148 case Easing.OutBack: 149 return --time * time * ((back_const + 1) * time + back_const) + 1; 150 151 case Easing.InOutBack: 152 if ((time *= 2) < 1) return .5 * time * time * ((back_const2 + 1) * time - back_const2); 153 154 return .5 * ((time -= 2) * time * ((back_const2 + 1) * time + back_const2) + 2); 155 156 case Easing.InBounce: 157 time = 1 - time; 158 if (time < bounce_const) 159 return 1 - 7.5625 * time * time; 160 if (time < 2 * bounce_const) 161 return 1 - (7.5625 * (time -= 1.5 * bounce_const) * time + .75); 162 if (time < 2.5 * bounce_const) 163 return 1 - (7.5625 * (time -= 2.25 * bounce_const) * time + .9375); 164 165 return 1 - (7.5625 * (time -= 2.625 * bounce_const) * time + .984375); 166 167 case Easing.OutBounce: 168 if (time < bounce_const) 169 return 7.5625 * time * time; 170 if (time < 2 * bounce_const) 171 return 7.5625 * (time -= 1.5 * bounce_const) * time + .75; 172 if (time < 2.5 * bounce_const) 173 return 7.5625 * (time -= 2.25 * bounce_const) * time + .9375; 174 175 return 7.5625 * (time -= 2.625 * bounce_const) * time + .984375; 176 177 case Easing.InOutBounce: 178 if (time < .5) return .5 - .5 * new DefaultEasingFunction(Easing.OutBounce).ApplyEasing(1 - time * 2); 179 180 return new DefaultEasingFunction(Easing.OutBounce).ApplyEasing((time - .5) * 2) * .5 + .5; 181 182 case Easing.OutPow10: 183 return --time * Math.Pow(time, 10) + 1; 184 } 185 } 186 } 187}