The best part of playing with other APIs and platforms is finding all the little gems you can bring back to your preferred platform. In this post, I’m bringing some of the NSTimer functionality found in the iPhone (and regular OS X) Cocoa Framework to the XNA Framework.
The NSTimer class is basically like any other timer, but it integrates so nicely given the run-loop mechanism used in Cocoa. Basically you could call a single static method and it would create a timer and add it to some mysterious list where it would be managed and updated without you having to care. In other words, fire and forget timers.
This is something I really wanted for myself when I came back to the XNA Framework so I hammered out my own replacement today and, like usual, I feel like sharing. Before I get into the implementation, let me just show you a quick example of what my Timer API looks like to use.
Let’s say I have a variable defined as “Color clearColor” in my main game class. This variable is used when clearing the screen. Now, let’s say I want it to change to red after the game runs for five seconds. Well, with the Timer API we just do this in our Initialize method:
Timer.CreateTimer(5f, () => clearColor = Color.Red);
And that’s it. Now there is one small caveat which is that you have a Timer.Update(GameTime) static method that you need to call in your game’s update method which will drive every timer. However you never need to explicitly add any of these timers to the list nor manage updating each one individually. Heck, even though the CreateTimer method returns a Timer, you don’t even need to hold onto it if you don’t want.
So let me just show you the implementation. It’s pretty long, so I just uploaded the .cs file for you to look at: Timer.cs. It’s pretty well commented so it shouldn’t be hard to figure out. I provide a lot of overloads of CreateTimer to take in different Action types as well as shortcutting for timers that don’t repeat since that is a common scenario.
If you do have a timer that repeats, you can simply hold on to the Timer reference from CreateTimer and call Invalidate on it whenever you want it to stop updating. Then just null out your reference and you’re all set.
Another nice thing the Timer class does is recycle timers. Given that most timers will be used in a fire and forget manner, it makes sense to just hold onto ever Timer object created and reuse them as they become expired. This lets you create timers as much as you want and never have an issue with the garbage collector.
To top it off, you can actually make some pretty fun and complex timer scenarios without doing much work. Take for instance a scenario I came up with (which actually inspired me to make this class) which is a logo screen at the start of a game. I wanted the game to start, wait one second, display a logo for two seconds, wait another second, and then move on to the next screen. If I were doing this by hand, I’d have all sorts of state variables and other things to track to make sure each timer was handled in order. But with the Timer API I can simply nest a bunch of CreateTimer methods like this:
Timer.CreateTimer(
1f,
() =>
{
titleVisible = true;
Timer.CreateTimer(
2f,
() =>
{
titleVisible = false;
Timer.CreateTimer(1f, () => ScreenManager.RemoveScreen(this));
});
});
And that’s that. No states to manage, no individual objects to update, and no worrying about garbage collections here.
Hopefully others will enjoy the Timer API. It makes life so much easier when you have events you want fired at specific times or intervals, but don’t want to be hassled into tracking and updating a whole bunch of individual timer objects.