[英]How would I go about implementing a stopwatch with different speeds?
理想情況下,我希望有類似於秒表類的東西,但有一個名為Speed
的額外屬性,它將決定計時器改變分鍾的速度。 我不太確定如何實現這一點。
編輯
因為人們似乎不太明白我為什么要這樣做。 考慮玩足球比賽或任何體育比賽。 半分是以分鍾為單位測量的,但是比賽的時間范圍顯着降低,即在約2.5分鍾內播放45分鍾的一半。
對它進行子類化,調用超類方法來完成它們的正常工作,但是將所有返回值乘以Speed。
我會按原樣使用秒表 ,然后將結果相乘,例如:
var Speed = 1.2; //Time progresses 20% faster in this example
var s = new Stopwatch();
s.Start();
//do things
s.Stop();
var parallelUniverseMilliseconds = s.ElapsedMilliseconds * Speed;
你的簡單“乘法”不起作用的原因是它不會加速時間的流逝 - 這個因素適用於所有已經過去的時間,以及經過的時間。
因此,如果您將速度因子設置為3
然后等待10分鍾,那么您的時鍾將正確讀取30分鍾。 但是,如果您隨后將因子更改為2
,則您的時鍾將立即讀取20分鍾,因為乘法應用於已經過去的時間。 這顯然不正確。
我不認為秒表是你想用“系統時間”測量的類。 我想你想測量它yoruself,並將經過的時間存儲在你自己的變量中。
假設您的目標項目確實是一個游戲,您可能會在代碼中的某個地方進行“游戲循環”。 每次循環時,您都可以使用常規秒表對象來測量實際經過的時間。 將該值乘以您的加速因子並將其添加到單獨的游戲時間計數器。 這樣,如果減少速度因子,則只減少應用於傳遞時間的因子,而不是減少已經記錄的時間。
如果需要,您可以將所有這些行為包裝到您自己的秒表類中。 如果你這樣做,那么我建議你計算/累計“每次請求時”和“每次因素改變時”的經過時間。 所以你有一個這樣的類(注意我已經跳過了字段聲明和一些簡單的私有方法以簡潔 - 這只是一個粗略的想法):
public class SpeedyStopwatch
{
// This is the time that your game/system will run from
public TimeSpan ElapsedTime
{
get
{
CalculateElapsedTime();
return this._elapsedTime;
}
}
// This can be set to any value to control the passage of time
public double ElapsedTime
{
get { return this._timeFactor; }
set
{
CalculateElapsedTime();
this._timeFactor = value;
}
}
private void CalculateElapsedTime()
{
// Find out how long (real-time) since we last called the method
TimeSpan lastTimeInterval = GetElapsedTimeSinceLastCalculation();
// Multiply this time by our factor
lastTimeInterval *= this._timeFactor;
// Add the multiplied time to our elapsed time
this._elapsedTime += lastTimeInterval;
}
}
根據現代物理學 ,您需要做的是讓計時器“更快”,這樣可以加速運行軟件的計算機。 我不是說它執行計算的速度,而是物理速度。 你得到的光速(常數C)越接近你的計算機的速度越大,所以當你接近光速時,時間將“加速”為你。
聽起來你實際上正在尋找的是一個事件調度程序,你可以在其中指定某些事件必須在模擬時間內的特定點發生,並且你希望能夠改變實時和模擬時間之間的關系(可能是動態的)。 當您在運行模擬過程中開始更改時間速度時,您可能會遇到邊界情況,您可能還需要處理實際需要更長時間才能返回的情況(您的線程沒有獲得時間片)只要您願意,您實際上可能無法實現您定位的模擬時間。)
例如,假設您希望每50毫秒模擬時間至少更新一次模擬。 您可以將模擬調度程序實現為一個隊列,您可以在其中推送事件並使用正常Stopwatch類的縮放輸出來驅動調度程序。 該過程看起來像這樣:
Push (simulate at t=0) event to event queue
Start stopwatch
lastTime = 0
simTime = 0
While running
simTime += scale*(stopwatch.Time - lastTime)
lastTime = stopwatch.Time
While events in queue that have past their time
pop and execute event
push (simulate at t=lastEventT + dt) event to event queue
這可以推廣到以不同間隔發生的不同類型的事件。 您仍然需要處理事件隊列膨脹的邊界情況,因為模擬無法跟上實時。
我不完全確定你要做什么(一分鍾總是有60秒?),但我會利用Thread.Sleep()來完成你想要的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.