Here is the gameloop class:
/// <summary>
/// Animation on a storyboard used as a timer tick for a game loop
/// from: http://silverlightrocks.com/community/blogs/silverlight_games_101/archive/2007/05/21/a-better-game-loop.aspx
/// </summary>
public class Gameloop
{
/// <summary>
/// canvas for update
/// </summary>
Canvas targetCanvas = null;
/// <summary>
/// story board for animation
/// </summary>
Storyboard storyboard;
/// <summary>
/// datetime of last update
/// </summary>
DateTime lastUpdateTime = DateTime.MinValue;
/// <summary>
/// Delegate used to pass tick event
/// </summary>
/// <param name="ElapsedTime">time since last tick</param>
public delegate void UpdateDelegate(TimeSpan ElapsedTime);
/// <summary>
/// Tick event
/// </summary>
public event UpdateDelegate Update;
/// <summary>
/// Create a storyboard gameloop for the canvas
/// </summary>
/// <param name="canvas">The canvas to update on tick</param>
public void Attach(Canvas canvas)
{
targetCanvas = canvas;
storyboard = new Storyboard();
storyboard.SetValue<string>(Storyboard.NameProperty, "gameloop");
canvas.Resources.Add(storyboard);
lastUpdateTime = DateTime.Now;
storyboard.Completed += new EventHandler(storyboard_Completed);
storyboard.Begin();
}
/// <summary>
/// stop the rimer and remove the canvas
/// </summary>
/// <param name="canvas">the canvas to remove</param>
public void Detach(Canvas canvas)
{
storyboard.Stop();
canvas.Resources.Remove(storyboard);
}
/// <summary>
/// Tick event for animation on timer
/// </summary>
/// <param name="sender">not used</param>
/// <param name="e">not used</param>
void storyboard_Completed(object sender, EventArgs e)
{
TimeSpan elapsedTime = DateTime.Now - lastUpdateTime;
lastUpdateTime = DateTime.Now;
if (Update != null) Update(elapsedTime);
storyboard.Begin();
}
}
In your main canvas, create the gameloop and give it a function to call on update:
//create timer
Gameloop mGameloop = new Gameloop();
mGameloop.Attach(this);//attach the canvas that you want a timer for
//assign a callback function to be called on tick
mGameloop.Update += new Gameloop.UpdateDelegate(gameloop_Update);
Here is my update function:
/// <summary>
/// each tick this methos is called
/// </summary>
/// <param name="ElapsedTime">time since last tick</param>
void gameloop_Update(TimeSpan elapsedTime)
{
//do something like move a sprite on the screen
mSprite.Animate(elapsedTime);
//force garbage, not necessary, but may help with the beta(1.1)
GC.Collect();
}
I have found that this approach does not work well if you have other Storyboards in your application. In this case, you would need to manage which Storyboard is running and only let one run at a time. If you do not manage your Storyboards, you will get odd effects.
No comments:
Post a Comment