游戏里面经常有转盘活动, 为了让转盘表现自然一点, 就需要自己模拟阻尼运动, 分为三个过程: 匀加速运动, 匀速运动, 匀减速运动
设定最高速度为MaxSpeed, SpeedUp1(匀加速运动的加速度), SpeedUp2(匀减速运动的加速度), Expect(期望停留的弧度点)
其实模拟只需要把两个加运动的区间模拟出来, 剩下的就是匀速运动的区间.
1 public struct DampingMotion 2 { 3 /// <param name="maxSpeed">最大速度</param> 4 /// <param name="speedUp1">加速运动1</param> 5 /// <param name="speedUp2">减速运动2</param> 6 /// <param name="expected">期望停留在某个弧度</param> 7 public DampingMotion(double maxSpeed, double speedUp1, double speedUp2, double expected) 8 { 9 this.maxSpeed = maxSpeed; 10 this.speedUp1 = speedUp1; 11 this.speedUp2 = speedUp2; 12 this.expected = expected; 13 14 time1 = maxSpeed / speedUp1; 15 time3 = maxSpeed / speedUp2; 16 distance1 = speedUp1 * Math.Pow(time1, 2) / 2; 17 distance3 = speedUp2 * Math.Pow(time3, 2) / 2; 18 distance2 = expected - (distance1 + distance3) % (Math.PI * 2) + Math.PI * 4; 19 time2 = distance2 / maxSpeed; 20 } 21 22 //单位是秒 23 public double GetRotate(double time) 24 { 25 if (time >= 0 && time < time1) 26 { 27 return Math.Pow(time, 2) / 2 * speedUp1; 28 } 29 if (time >= time1 && time < time1 + time2) 30 { 31 return distance1 + (time - time1) * maxSpeed; 32 } 33 if (time >= time1 + time2 && time < time1 + time2 + time3) 34 { 35 var f = time - (time1 + time2); 36 return distance1 + distance2 + ( 37 speedUp2 * Math.Pow(time3, 2) / 2 - 38 speedUp2 * Math.Pow((time3 - f), 2) / 2 39 ); 40 } 41 return distance1 + distance2 + distance3; 42 } 43 44 public double maxSpeed; 45 public double speedUp1; 46 public double speedUp2; 47 public double expected; 48 49 public double time1; //第一段匀加速的时间 50 public double time2; //第二段匀速运动时间 51 public double time3; //第三段匀减速运动时间 52 private double distance1; 53 private double distance2; 54 private double distance3; 55 }
构造好之后, 只需要调用GetRotate函数, 就可以获取某一个时间转盘停留的弧度
这样一个50行不到的代码, 实际上可以当做一个面试题目