Geeks With Blogs
Freestyle Coding Programming in the Real World

It was unofficially announced yesterday that XNA has officially hit the end of its life. Fortunately, as mentioned in the last post, I'm working on porting everything out of XNA. However, there is stall a lot in XNA to love. As such, I have been making it a point to borrow some of the better features of XNA. Think of this post as the beginning of a series of posts called "Recreating XNA in Windows Store Apps."

The first thing I needed to recreate was a GameComponent. For those of you not familiar with XNA, a GameComponent is an object that updates itself during every cycle of the game loop. This helps to avoid a monolithic function that updates the entire game.

It is worth mentioning that I did, at one point, try to recreate a game loop in my Windows Store App. I stopped that experiment for two reasons. First, I wanted to try to treat the WinRT platform like the WinRT platform as much as possible. Second, you still have to call the UI thread for screen manipulation, so you're never going to get a true Draw phase. We'll go more on that second point in my next post, where I'll create a DrawableGameComponent. I think it is still possible, so I may return to the idea at a later time.

The first thing I had to attack was the concept of the object being called during every cycle of my virtual game loop. Traditionally, you would perform such an action by creating a thread, performing your update, and sleeping until it was time to do it again. However, this is a big no-no in a Windows Store App. You're really supposed to handle everything through the ThreadPool. I like monitoring threads manually as much as the next guy, so I opted to use his brother, the ThreadPoolTimer.

Using the ThreadPoolTimer, I can tell the thread pool to call my update function on a specific interval. The ThreadPoolTimer does include support for periodic timers, but I eventually moved to manual timers for reasons I shall soon disclose (I wasn't kidding when I said I like to manually monitor threads.) My constructor asks the App for the current target framerate and sets a timer. When my timer goes off and my update completes, I set a new timer.

The reason I don't use the periodic timer is twofold. First, I want to be able to be able to track some statistics about the system performance. XNA featured a class called GameTime that would report information about the clock to every call to Update. I wanted to use a few of those features. I created a custom set of EventArgs called UpdateEventArgs. These help me report the amount of time the thread slept. This allows me to do proper timing based events.

public class UpdateEventArgs : EventArgs {
public long SleepTicks {
get;
private set;
}
 
public UpdateEventArgs( long Ticks ) : base() #123;
SleepTicks = Ticks;
}
}

The other think I wanted to port from the old GameTime was a flag to notify that the game is running slowly. I put the IsRunningSlowly flag in the actual class and set if on each call to the timer. This guy gets set to true if the call to update takes longer to run than the current frame. This lets the component ignore a few things if the game gets a little hectic.

The last thing that was vital was a mechanism to turn off the component. This was easily accomplished with a simple property on the object called Enabled. If you set it to true, then the timer is created. If you set it to false, then the timer is canceled.

Once all this was in place, I created an event for the superclass. This is the event that will be triggered so the component can execute it's code.

public abstract class Updatable {
private ThreadPoolTimer UpdateTimer;
 
protected long TicksPerFrame {
get;
private set;
}
 
protected bool IsRunningSlowly {
get;
private set;
}
 
public delegate void UpdateEventHandler( object sender, UpdateEventArgs e );
public event UpdateEventHandler Update;
 
private bool m_Enabled = true;
public bool Enabled {
get {
return m_Enabled;
}
set {
m_Enabled = value;
 
if( m_Enabled )
UpdateTimer = ThreadPoolTimer.CreateTimer( RaiseUpdate, TimeSpan.FromTicks( TicksPerFrame ) );
else
if( UpdateTimer != null )
UpdateTimer.Cancel();
}
}
 
protected Updatable() {
IsRunningSlowly = false;
TicksPerFrame = TimeSpan.FromMilliseconds( App.FRAMERATE ).Ticks;
UpdateTimer = ThreadPoolTimer.CreateTimer( RaiseUpdate, TimeSpan.FromTicks( TicksPerFrame ) );
}
 
protected void RaiseUpdate( ThreadPoolTimer _Timer ) {
DateTime EntryTime = DateTime.Now;
 
if( Update != null )
Update( this, new UpdateEventArgs( _Timer.Delay.Ticks ) );
 
IsRunningSlowly = false;
while( TicksPerFrame < ( DateTime.Now - EntryTime ).Ticks ) {
IsRunningSlowly = true;
EntryTime += TimeSpan.FromTicks( TicksPerFrame );
}
 
UpdateTimer = ThreadPoolTimer.CreateTimer( RaiseUpdate, TimeSpan.FromTicks( TicksPerFrame - ( DateTime.Now - EntryTime ).Ticks ) );
}
 
~Updatable() {
if( UpdateTimer != null )
UpdateTimer.Cancel();
}
}

I have a few quick notes about the preceding code sample. The call to App.FRAMERATE is a constant I declared so I could globally change the framerate if I need. Also, I convert everything to ticks for two reasons. First, integer math is much quicker than floating point math. Second, integer math does not have round-off errors.

So, there it is. Next up, we will base off this class to create a DrawableGameComponent. However, this will take some serious time, so you can digest all this. Plus, there is one little sticking point I'm trying to clean.

Let me know what you think. Comment away.

Posted on Thursday, January 31, 2013 12:27 PM .NET , C# , Interfaces , XNA , Win8 , WinRT | Back to top


Comments on this post: Creating an XNA GameComponent in Windows Store Apps

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Chris Gardner | Powered by: GeeksWithBlogs.net