代码之家  ›  专栏  ›  技术社区  ›  James

我该如何使用不同速度的秒表?

  •  4
  • James  · 技术社区  · 15 年前

    理想情况下我想要类似于 Stopwatch 类,但具有一个名为 Speed 这将决定计时器更改分钟的速度。我不太确定我将如何着手实现这一点。

    编辑

    因为人们似乎不太明白 为什么? 我想这么做。考虑玩足球或任何运动游戏。半场以分钟为单位,但比赛的时间段明显较短,即45分钟的半场约2.5分钟。

    6 回复  |  直到 15 年前
        1
  •  2
  •   Dan Puzey    15 年前

    你简单的“乘法”不起作用的原因是它不能加速时间的流逝——这个因素适用于 已经通过 以及时间 正在通过 .

    所以,如果你把速度系数设为 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;
        }
     }
    
        2
  •  7
  •   Andrew McGregor    15 年前

    对它进行子类化,调用超类方法来完成它们通常的工作,但根据需要将所有返回值乘以速度。

        3
  •  3
  •   Nick Craver    15 年前

    我会用 Stopwatch 按原样,然后将结果相乘,例如:

    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;
    
        4
  •  0
  •   Muad'Dib    15 年前

    根据 modern physics ,你需要做的是让你的计时器“更快”是加速你的软件运行的计算机。我不是指它执行计算时的速度,而是物理速度。当你接近光速(常数c)的时候,你的电脑时间流逝的速率就越大,所以当你接近光速的时候,时间会为你“加速”。

        5
  •  0
  •   Dan Bryant    15 年前

    听起来您可能实际上在寻找的是一个事件调度程序,其中您指定某些事件必须在模拟时间的特定点发生,并且您希望能够更改实时和模拟时间之间的关系(可能是动态的)。在运行模拟的过程中,当您开始改变时间的速度时,您可能会遇到边界情况,并且您可能还必须处理实时返回时间比正常返回时间长的情况(您的线程没有得到您想要的时间切片,因此您可能实际上无法实现您要瞄准的模拟时间)

    例如,假设您希望至少每50毫秒的模拟时间更新一次模拟。您可以将模拟调度程序实现为一个队列,在该队列中推送事件并使用普通秒表类的缩放输出来驱动调度程序。过程如下:

    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
    

    这可以推广到不同时间间隔发生的不同类型的事件。您仍然需要处理事件队列膨胀的边界情况,因为模拟无法跟上实时性。

        6
  •  -2
  •   Jim B    15 年前

    我不完全确定你想做什么(不是一分钟总有60秒?),但我将使用thread.sleep()来完成您想要的。