Как мне реализовать секундомер с разными скоростями? - PullRequest
4 голосов
/ 18 мая 2010

В идеале я хотел бы иметь что-то похожее на класс Секундомер , но с дополнительным свойством под названием Speed, которое будет определять, как быстро таймер меняет минуты. Я не совсем уверен, как мне поступить в реализации этого.

Редактировать

Поскольку люди, кажется, не совсем понимают , почему Я хочу сделать это. Попробуйте поиграть в футбол или любую спортивную игру. Половины измеряются в минутах, но временные рамки, в которые проходит игра, значительно меньше, то есть 45-минутная половина играется примерно за 2,5 минуты.

Ответы [ 6 ]

7 голосов
/ 18 мая 2010

Подкласс этого, вызовите методы суперкласса, чтобы сделать их обычную работу, но умножьте все возвращаемые значения на Speed ​​соответственно.

3 голосов
/ 18 мая 2010

Я бы использовал Секундомер как есть, а затем просто умножил результат, например:

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;
2 голосов
/ 18 мая 2010

Причина, по которой ваше простое «умножение» не работает, заключается в том, что оно не ускоряет течение времени - этот коэффициент применяется ко всему времени, когда прошло , а также ко времени, когда проходит .

Итак, если вы установите коэффициент скорости на 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;
    }
 }
0 голосов
/ 18 мая 2010

Похоже, что вы действительно ищете планировщик событий, в котором вы указываете, что определенные события должны происходить в определенные моменты в смоделированном времени, и вы хотите иметь возможность изменять отношения между реальным временем и симулированным временем (возможно динамически). Вы можете столкнуться с граничными случаями, когда вы начинаете изменять скорость времени в процессе выполнения симуляции, и вам также может потребоваться иметь дело со случаями, когда реальное время занимает больше времени, чем обычно (ваш поток не получил временной интервал как только вы захотите, так что вы не сможете достичь смоделированного времени, на которое вы нацелены.)

Например, предположим, что вы хотите обновить симуляцию хотя бы раз в 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

Это можно обобщить для различных типов событий, происходящих с разными интервалами. Вам все еще нужно иметь дело с граничным случаем, когда очередь событий раздувается, потому что симуляция не может идти в ногу с реальным временем.

0 голосов
/ 18 мая 2010

Согласно современной физике , вам нужно сделать так, чтобы таймер работал «быстрее», чтобы ускорить работу компьютера, на котором работает ваше программное обеспечение. Я имею в виду не скорость, с которой он выполняет вычисления, а физическую скорость. Чем ближе вы приближаетесь к скорости света (константе C), тем больше скорость, с которой время проходит для вашего компьютера, поэтому, когда вы приближаетесь к скорости света, время «ускоряется» для вас.

0 голосов
/ 18 мая 2010

Я не совсем уверен, что вы собираетесь делать (разве минута не всегда имеет 60 секунд?), Но я бы использовал Thread.Sleep (), чтобы выполнить то, что вы хотите.

...