Make Your Time!

It’s going on seven months since my last post, which is kind of pathetic. When finishing a large project, like the WP7 port of Guardian, my brain tends to shut down for awhile for recharging. That, on top of starting a new job back in November, lead to a much longer blogging hiatus than intended. So, how about something simple to get back into the swing of things. And since we’re talking about time…

Very often in video games there is a need to perform some action after a certain amount of time elapses. Examples include deciding when to show the next frame of an animation, deciding when to spawn the next enemy, hiding a message after it’s been displayed for awhile, and so on. For a most basic implementation of this we need two values: something to describe how long we want to wait, and something to track how long we’ve been waiting.

float timerLimit = 2.0f;
float timerElapsed = 0.0f;

We also need to pick a unit of time to work with. Seconds seem to be pretty convenient, and that’s what we’ll use here. So the value of 2.0 for timerLimit means we want to wait 2 seconds before doing something.

Once we have these values established it’s a matter of updating timerElapsed each frame and checking it against timerLimit to see if the desired amount of time has passed. Since the game programming API of choice here is XNA, the proper place to do this updating is in the game’s Update() method.

protected override void Update(GameTime gameTime)
{
  // grab the number of seconds that have elapsed since the last
  // frame, including fractional seconds, so if you're running
  // at 60fps this value will be 0.0166667 more or less, or
  // 1/60th of a second.
  float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

  // add the elapsed time to our timer
  timerElapsed += elapsedTime;

  // if the timer has exceed our limit then do something
  if (timerElapsed >= timerLimit)
  {
    // TODO : do something
  }
}

Once timerElapsed passes timerLimit then we can perform our action. There’s a problem with this code though. Once the timer exceeds our limit it will keep executing the action every frame thereafter. While this may be what we want sometimes, in many cases, if not most, it isn’t. So we need a way to turn off the timer, or restart it.

To restart it we can simply reset timerElapsed back to zero if we want to the event to fire again in the same amount of time. To stop the timer we can use timerElapsed as a flag and set to -1 to indicate that the timer is inactive. Our timer code now looks like this:

// update the timer if it's enabled
if (timerElapsed != -1)
{
  // add the elapsed time to our timer
  timerElapsed += elapsedTime;

  // if the timer has exceed our limit then do something
  if (timerElapsed >= timerLimit)
  {
    // TODO : do something

    // set the elapsed time back to 0 to schedule the event again,
    // otherwise set it to -1 to disable the timer
    timerElapsed = -1.0f;
  }
}

To start the timer initially our code needs to set timerElapsed to 0 which will being the process of tracking elapsed time until timerLimit is reached.

This code practically begs to become a class, so let’s not disappoint it.

public class SimpleTimer
{
  public float Limit;
  public float Elapsed;

  public SimpleTimer(float limit)
  {
    Limit = limit;
    Stop(); // make sure it's not running
  }

  public void Start()
  {
    Elapsed = 0.0f;
  }

  public void Stop()
  {
    Elapsed = -1.0f;
  }

  public bool Update(float elapsedTime)
  {
    bool result = false;

    if (Elapsed >= 0.0f)
    {
      Elapsed += elapsedTime;
      result = Elapsed >= Limit;
    }

    return result;
  }
}

Our previous example now looks like this:

SimpleTimer timer = new SimpleTimer(2.0f);
protected override void Update(GameTime gameTime)
{
  // grab the number of seconds that have elapsed since the last
  // frame, including fractional seconds, so if you're running
  // at 60fps this value will be 0.0166667 more or less, or
  // 1/60th of a second.
  float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

  if (timer.Update(elapsedTime))
  {
    // TODO : do something

    timer.Stop(); // or use timer.Start() to restart it
  }
}

Somewhat less crappy.

Scheduling events like this is one use for a timer. Another thing that’s often needed is the ability to perform an action over time, such as fading out text. The next post will cover that.

One thought on “Make Your Time!”

Leave a Reply

Your email address will not be published. Required fields are marked *