views:

121

answers:

6

Ideally I would like to have something similar to the Stopwatch class but with an extra property called Speed which would determine how quickly the timer changes minutes. I am not quite sure how I would go about implementing this.

Edit

Since people don't quite seem to understand why I want to do this. Consider playing a soccer game, or any sport game. The halfs are measured in minutes, but the time-frame in which the game is played is significantly lower i.e. a 45 minute half is played in about 2.5 minutes.

A: 

I'm not entirely sure what you're looking to do (doesn't a minute always have 60 seconds?), but I'd utilize Thread.Sleep() to accomplish what you want.

Jim B
+6  A: 

Subclass it, call through to the superclass methods to do their usual work, but multiply all the return values by Speed as appropriate.

Andrew McGregor
I was doing something similar to this but the minute calculation wasn't working properly if I changed the speed throughout execution.
James
When you change the speed, calculate the time-so-far and reset the internal timer. When you want to read the time, multiply the last interval with the speed and add that time-so-far.
Hans Kesting
@Hans: Could you post an answer with an example?
James
@Andrew: Multiply *what* exactly. The ticks? Milliseconds? Elapsed time?
James
@James: Suppose your rule is, "2 minutes per minute real minute". I would multiply `ElapsedTicks` by 2. However, this means 3 minutes will have passed after 90 seconds. If you prefer 2 minutes to have passed after 90 seconds, multiply by `(int)Elapsed.TotalMinutes`. All that being said, at this point Andrew and Hans have given you more than enough information to start on. Instead of asking for further help now, try and implement it yourself. If it doesn't work, ask for help then. I feel like at this point just using common sense and thought should be enough to apply Andrew's solution.
Brian
@Brian: The point I was trying to make was the answer was a bit `generic` what he has explained is the *concept* which is what I already know, its the how I was after which other answers have explained.
James
+3  A: 

I would use the Stopwatch as it is, then just multiply the result, for example:

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;
Nick Craver
A: 

According to modern physics, what you need to do to make your timer go "faster" is to speed up the computer that your software is running one. I don't mean the speed at wich it performs calculations, but the physical speed. The close you get to the speed of light ( the constant C ) the greater the rate at which time passes for your computer, so as you approach the speed of light, time will "speed up" for you.

Muad'Dib
What do you mean by "modern physics"? Have they changed recently? :)
Nick Craver
lol post Albert Einstein
Muad'Dib
That would cause the computer's clock to run slower as perceived by the observer. You, not the computer, would have to move faster by a considerable margin.
Brian Gideon
Wait a minute...my computer is faster...I work faster..!! This explains my increase in mass !!!! holy crap. Phew...the wife had me ready for the the gym. Saved by relativity...cool.
Rusty
+1  A: 

The reason your simple "multiplication" doesn't work is that it doesn't speeding up the passing of time - the factor applies to all time that has passed, as well as time that is passing.

So, if you set your speed factor to 3 and then wait 10 minutes, your clock will correctly read 30 minutes. But if you then change the factor to 2, your clock will immediately read 20 minutes because the multiplication is applied to time already passed. That's obviously not correct.

I don't think the stopwatch is the class you want to measure "system time" with. I think you want to measure it yoruself, and store elapsed time in your own variable.

Assuming that your target project really is a game, you will likely have your "game loop" somewhere in code. Each time through the loop, you can use a regular stopwatch object to measure how much real-time has elapsed. Multiply that value by your speed-up factor and add it to a separate game-time counter. That way, if you reduce your speed factor, you only reduce the factor applied to passing time, not to the time you've already recorded.

You can wrap all this behaviour into your own stopwatch class if needs be. If you do that, then I'd suggest that you calculate/accumulate the elapsed time both "every time it's requested" and also "every time the factor is changed." So you have a class something like this (note that I've skipped field declarations and some simple private methods for brevity - this is just a rough idea):

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;
    }
 }
Dan Puzey
@Dan: This was kinda what I suspected i.e. having to do all the calculations manually. I just thought there might have been an easier way using something like the Stopwatch class.
James
A: 

It sounds like what you might actually be looking for is an event scheduler, where you specify that certain events must happen at specific points in simulated time and you want to be able to change the relationship between real time and simulated time (perhaps dynamically). You can run into boundary cases when you start to change the speed of time in the process of running your simulation and you may also have to deal with cases where real time takes longer to return than normal (your thread didn't get a time slice as soon as you wanted, so you might not actually be able to achieve the simulated time you're targeting.)

For instance, suppose you wanted to update your simulation at least once per 50ms of simulated time. You can implement the simulation scheduler as a queue where you push events and use a scaled output from a normal Stopwatch class to drive the scheduler. The process looks something like this:

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

This can be generalized to different types of events occurring at different intervals. You still need to deal with the boundary case where the event queue is ballooning because the simulation can't keep up with real time.

Dan Bryant