A game framework written with osu! in mind.
at master 2.4 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 osu.Framework.Extensions.TypeExtensions; 5using System; 6using System.Diagnostics; 7 8namespace osu.Framework.Timing 9{ 10 public class StopwatchClock : Stopwatch, IAdjustableClock 11 { 12 private double seekOffset; 13 14 /// <summary> 15 /// Keep track of how much stopwatch time we have used at previous rates. 16 /// </summary> 17 private double rateChangeUsed; 18 19 /// <summary> 20 /// Keep track of the resultant time that was accumulated at previous rates. 21 /// </summary> 22 private double rateChangeAccumulated; 23 24 public StopwatchClock(bool start = false) 25 { 26 if (start) 27 Start(); 28 } 29 30 public double CurrentTime => stopwatchCurrentTime + seekOffset; 31 32 /// <summary> 33 /// The current time, represented solely by the accumulated <see cref="Stopwatch"/> time. 34 /// </summary> 35 private double stopwatchCurrentTime => (stopwatchMilliseconds - rateChangeUsed) * rate + rateChangeAccumulated; 36 37 private double stopwatchMilliseconds => (double)ElapsedTicks / Frequency * 1000; 38 39 private double rate = 1; 40 41 public double Rate 42 { 43 get => rate; 44 set 45 { 46 if (rate == value) return; 47 48 rateChangeAccumulated += (stopwatchMilliseconds - rateChangeUsed) * rate; 49 rateChangeUsed = stopwatchMilliseconds; 50 51 rate = value; 52 } 53 } 54 55 public new void Reset() 56 { 57 resetAccumulatedRate(); 58 base.Reset(); 59 } 60 61 public new void Restart() 62 { 63 resetAccumulatedRate(); 64 base.Restart(); 65 } 66 67 public void ResetSpeedAdjustments() => Rate = 1; 68 69 public bool Seek(double position) 70 { 71 // Determine the offset that when added to stopwatchCurrentTime; results in the requested time value 72 seekOffset = position - stopwatchCurrentTime; 73 return true; 74 } 75 76 public override string ToString() => $@"{GetType().ReadableName()} ({Math.Truncate(CurrentTime)}ms)"; 77 78 private void resetAccumulatedRate() 79 { 80 rateChangeAccumulated = 0; 81 rateChangeUsed = 0; 82 } 83 } 84}