理想的には、 Stopwatchクラスに似ていSpeed
ますが、タイマーが分を変更する速度を決定するという追加のプロパティが必要です。これをどのように実装するのかよくわかりません。
編集
なぜ私がこれをやりたいのか、人々はよく理解していないようです。サッカーゲームやその他のスポーツゲームをプレイすることを検討してください。半分は分単位で測定されますが、ゲームがプレイされる時間枠は大幅に短くなります。つまり、45分の半分が約2.5分でプレイされます。
理想的には、 Stopwatchクラスに似ていSpeed
ますが、タイマーが分を変更する速度を決定するという追加のプロパティが必要です。これをどのように実装するのかよくわかりません。
編集
なぜ私がこれをやりたいのか、人々はよく理解していないようです。サッカーゲームやその他のスポーツゲームをプレイすることを検討してください。半分は分単位で測定されますが、ゲームがプレイされる時間枠は大幅に短くなります。つまり、45分の半分が約2.5分でプレイされます。
それをサブクラス化し、スーパークラスメソッドを呼び出して通常の作業を行いますが、必要に応じてすべての戻り値に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 分を示します。それは明らかに正しくありません。
ストップウォッチは「システム時間」を測定したいクラスではないと思います。自分で測定して、経過時間を自分の変数に保存したいと思います。
ターゲット プロジェクトが実際にゲームであると仮定すると、コードのどこかに "ゲーム ループ" が含まれている可能性があります。ループのたびに、通常のストップウォッチ オブジェクトを使用して、経過したリアルタイム時間を測定できます。その値にスピードアップ係数を掛けて、別のゲーム時間カウンターに追加します。そうすれば、速度係数を減らしても、既に記録した時間ではなく、経過時間に適用される係数だけが減ります。
必要に応じて、このすべての動作を独自のストップウォッチ クラスにラップできます。それを行う場合は、「要求されるたび」と「要因が変更されるたび」の両方で経過時間を計算/累積することをお勧めします。したがって、次のようなクラスがあります (簡潔にするために、フィールド宣言といくつかの単純なプライベート メソッドをスキップしたことに注意してください。これは大まかな考えです)。
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;
}
}
あなたが実際に探しているのは、イベント スケジューラです。特定のイベントがシミュレートされた時間の特定の時点で発生する必要があることを指定し、リアルタイムとシミュレートされた時間の間の関係を (おそらく動的に) 変更できるようにする必要があるようです。シミュレーションを実行する過程で時間の速度を変更し始めると、境界ケースに遭遇する可能性があり、また、実時間が通常よりも戻るのに時間がかかる場合 (スレッドがタイム スライスを取得しなかった場合) に対処する必要がある場合もあります。そのため、目標としているシミュレートされた時間を実際に達成できない場合があります。)
たとえば、シミュレーション時間 50 ミリ秒ごとに少なくとも 1 回、シミュレーションを更新したいとします。シミュレーション スケジューラは、イベントをプッシュするキューとして実装し、通常の 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
これは、さまざまな間隔で発生するさまざまな種類のイベントに一般化できます。シミュレーションがリアルタイムに追いつかないため、イベント キューがバルーニングしている境界ケースに対処する必要があります。
現代の物理学によると、タイマーを「速く」するために必要なことは、ソフトウェアが実行されているコンピューターの速度を上げることです。計算の速さではなく、物理的な速さです。光の速度 (定数 C ) に近づくほど、コンピューターの時間の経過速度が速くなります。そのため、光の速度に近づくと、時間は「スピードアップ」します。
何をしようとしているのか完全にはわかりませんが(1分は常に60秒ではありませんか?)、Thread.Sleep()を使用して目的を達成します。