Game timing in Silverlight 5

Game timing in Silverlight 5

  • Comments 3

One thing missing from the new 3D functionality in Silverlight 5 is an equivalent of the XNA Game class.  I previously wrote about how to provide XNA style Update and Draw methods in a WinForms environment.  What is the Silverlight equivalent of that?

After installing the Silverlight Toolkit, create a new project using the Silverlight 3D Application template.  Open up MainPage.xaml, and note how this declares a DrawingSurface object and hooks its Draw event.  Now open MainPage.xaml.cs, and observe the implementation of the myDrawingSurface_Draw event handler method. After calling scene.Draw(), this calls e.InvalidateSurface(), which tells Silverlight this object needs to be redrawn.  Normally Silverlight would draw the object once at startup, then only redraw it when something changed about the scene (perhaps because the object was resized, or some other shape moved over the top of it).  But when the draw handler invalidates the surface, that causes it to be drawn again, which invalidates it again, which causes it to be drawn again, which { rinse, lather, repeat }.  This effectively creates an infinite loop, with the surface constantly being redrawn, just like we want for a game loop.

Note also the UserControl_Loaded method in MainPage.xaml.cs, which is hooked up to the UserControl.Loaded event via MainPage.xaml.  This is the Silverlight equivalent of the XNA Initialize and LoadContent methods.

Well and good, but how do we build an actual game on top of this system?  Check out the Silverlight port of the XNA Platformer starter kit (in c:/Program Files (x86)/Microsoft SDKs/Silverlight/v5.0/Toolkit/Sep11/Source/Sample source code.zip/Xna).  Again look at the myDrawingSurface_Draw method in MainPage.xaml.cs.  This is very simple:

    private void myDrawingSurface_Draw(object sender, DrawEventArgs e)
    {
        platformerGame.Update(e);
        platformerGame.Draw(e);

        e.InvalidateSurface();
    }

What we have here is a variable timestep game loop.  Thanks to the InvalidateSurface call, it will loop forever, calling Update and then Draw as fast as possible.

If you prefer to use a fixed timestep system, you can make one like so:

    readonly TimeSpan TargetElapsedTime = TimeSpan.FromTicks(TimeSpan.TicksPerSecond / 60);
    readonly TimeSpan MaxElapsedTime = TimeSpan.FromTicks(TimeSpan.TicksPerSecond / 10);

    TimeSpan accumulatedTime;


    private void myDrawingSurface_Draw(object sender, DrawEventArgs e)
    {
        TimeSpan elapsedTime = e.DeltaTime;

        if (elapsedTime > MaxElapsedTime)
        {
            elapsedTime = MaxElapsedTime;
        }

        accumulatedTime += elapsedTime;

        while (accumulatedTime >= TargetElapsedTime)
        {
            Update();
            accumulatedTime -= TargetElapsedTime;
        }

        Draw();
        e.InvalidateSurface();
    }
  • So my experience with silverlight is that it's timer is limited to 1/16 second precision.  Will that mess up the above code?

    Any chance you could knock some sense into someone to get a higher precision timer in?

  • Perhaps DrawEventArgs.DeltaTime has better precision? It's a new feature in Silverlight 5 (it seems), so I hope they did take this opportunity to provide better precision.

    In earlier versions of Silverlight the best you could do was 1-millisecond precision. I found that the best way to handle this was to just accept running at a constant 62.5 FPS (16ms/frame) as "close enough".

  • The timing information in DrawEventArgs is more than sufficiently accurate for game simulation/animation.

Page 1 of 1 (3 items)
Leave a Comment
  • Please add 8 and 2 and type the answer here:
  • Post