This blog is no longer updated. Feel free to copy any useful information to other blogs or wikis. Thanks.


Borrowing From The iPhone SDK

May 5th, 2009 | 8 comments

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.

  1. Khalos
    May 6th, 2009 at 14:27
    Quote | #1

    Thanks for sharing this! I always love ‘borrowing’ features from one API to the next, but I have never dabbled in the iPhone framework.

    It seems like this technique could be useful in other areas aside from Timers, which I will enjoy trying out.

  2. JeBuS
    May 7th, 2009 at 09:37
    Quote | #2

    I did something similar, but once again, you’ve made yours better.

  3. May 7th, 2009 at 15:10
    Quote | #3

    Ohh, I am so into JS “SetInterval” right now, your code is pure beauty :)

    Should you want to beautify it even further: Maybe make the “CreateTimer” a real factory method (returning an ITimer interface) so that you eliminate all that “switch” stuff in your Timer.Update method. Timer.Update could then concentrate on expired-list management and delegate everything else to “t.Update(gameTime, out expired)”. Would also allow the timers to decide what time (Game/Wall) they want to use.

    However, thanks for the share! I’ll see how I can use it once I’m back from the dark side of languages.

  4. Bjoern
    May 9th, 2009 at 02:54
    Quote | #4

    The one minor thing I would change is to clear expired timer properties when it is added to the expired list, not when it is reused, to remove any references held on tickData.

    And while I sort of agree with sirlantis that an interface and Timer.Update would be nicer OOP it would make caching a bit more complex. Something that could mitigate this OOP purity issue would be to drop the different types and just use the tickWithTimerAndData action for all timers.

  5. May 9th, 2009 at 09:34
    Quote | #5

    I think Bjoern’s idea is the best. Probably would be easiest to just require the one type of delegate which would remove the switch logic entirely without needing a complex OO scenario.

    And yes, clearing those properties when they are moved to the expired list is the better route. Not sure why I did it the other way… :)

  6. May 11th, 2009 at 07:14
    Quote | #6

    little idea, why don’t you make the timer component and service? The service exposes CreateTimer, the component side of it handles the updating.

    would fit into the “XNA” way of doing things better. Though calling GetService(typeof(ITimerService)) would be a little annoying, but would make sense. Thanks for the share. Think I’ll go implement my own version me thinks.

  7. May 11th, 2009 at 17:13
    Quote | #7

    I didn’t use components for a few reasons:

    1) I wanted to make the whole system use one class and I didn’t want users thinking they had to add each timer as a game component because I wanted just a single updat method so I could have fire and forget timers. In addition if the Timer was derived from GameComponent it would have bloated it with properties and methods it didn’t use.
    2) I prefer to just use static methods over services if it’s something that is going to be universally accessible. To me it makes no sense to pass around the game’s services collection everywhere when I can just make a static method to do what I need.

  8. Danthekilla
    June 12th, 2009 at 18:48
    Quote | #8

    Hey i seem to get this error 6 times

    Timer.cs(33,17): error CS0305: Using the generic type ‘System.Action’ requires ’1′ type arguments

    Im using xna 3.1 i can’t figure it out…
    I used to have this working in an older project but now i get this

Comments are closed.