模拟阻尼运动

游戏里面经常有转盘活动, 为了让转盘表现自然一点, 就需要自己模拟阻尼运动, 分为三个过程: 匀加速运动, 匀速运动, 匀减速运动

设定最高速度为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行不到的代码, 实际上可以当做一个面试题目

posted @ 2017-08-29 17:49  egmkang  阅读(...)  评论(... 编辑 收藏