Silverlight - Basic Movement with Animations

Skill

Silverlight - Basic Movement with Animations

Posted in:

So what do you need to make a game with Silverlight? Well, at the most basic level, you need something that moves around the screen. At the most basic level, four buttons that move a sprite in four directions. How do you do that? Well, there are multiple ways to accomplish this movement, some more flexible than others. Today, we are going to using Silverlight animations to do that job.

Silverlight animations are not hard to use, but what is hard to master are dynamic animations, which require multiple classes to create and set up. You have to set up a storyboard, then create an animation, then set the target information. When it is all said and done, you will end up with something like so:



As with any Silverlight app, we need to start with some Xaml:

  <Canvas Height="300" Name="canvas1" Width="400" >
    <Canvas.Resources>
      <Storyboard x:Name="mySB"></Storyboard>
    </Canvas.Resources>
    <Ellipse x:Name="myEllipse" Width="50" Height="50" Canvas.Left="175"
     Canvas.Top="125" Fill="Black" />
 </Canvas>

I know what you are thinking, this is not enough XAML for animations. Well, it is everything we need. We are actually creating all of the animations dynamically, then adding them to the storyboard. To start with, however, we need an event - a keyboard triggered event.

What we need is a KeyUp event, that only fires when we release a key, as opposed to pushing it down. Now I am using Visual Studio 2010 (which is currently under beta, so it is a free download), so I am not adding the event to the Canvas myself, but it is one line of code you can find in just about any SOTC Silverlight Tutorial. As I stated above, you need to setup a KeyUp event. This event also has to be tied to the Canvas, so it works no matter where you click the application:

private void canvas1_KeyUp(object sender, KeyEventArgs e)
{
}

The first thing we need to add to our event is key capturing. If you have ever done this before, you will recognize the code, if not it is extremely easy to do:

private void canvas1_KeyUp(object sender, KeyEventArgs e)
{
  if (e.Key == Key.Left)
  {
  }
  else if (e.Key == Key.Right)
  {
  }
  else if (e.Key == Key.Up)
  {
  }
  else if (e.Key == Key.Down)
  {
  }
}

What is going on here is that we are taking the key pressed, in this case a property of e, which is passed with the event. This gives up information about what key was pressed so we can compare it to key codes built into C#, which is given as an easy to use enum. As you can see, it is pretty obvious how to capture the right key.

Now we can start with the crazy stuff. First we need to setup some variables - movement speed and movement distance. Speed corresponds to how long it will take to travel a length equal to movement distance. For example we will set movement distance at 100 and speed at 0.5, making the animation travel 100 pixels in half a second. All we are doing right now is setting these variables, for later use:

private void canvas1_KeyUp(object sender, KeyEventArgs e)
{
  Double mDist = 100.00;
  Double mSpeed = 0.5;

  if (e.Key == Key.Left)
  {
  }
  else if (e.Key == Key.Right)
  {
  }
  else if (e.Key == Key.Up)
  {
  }
  else if (e.Key == Key.Down)
  {
  }
}

The next step is to start setting up the animation. To do this, we utilize a lot of different classes and methods:

private void canvas1_KeyUp(object sender, KeyEventArgs e)
{
  Double mDist = 100.00;
  Double mSpeed = 0.5;

  Double x = Canvas.GetLeft(myEllipse);
  Double y = Canvas.GetTop(myEllipse);

  DoubleAnimation animation = new DoubleAnimation();
  animation.Duration = new Duration(TimeSpan.FromSeconds(mSpeed));

  if (e.Key == Key.Left)
  {
    animation.From = x;
    animation.To = x - mDist;
    Storyboard.SetTargetProperty(
      animation, new PropertyPath(Canvas.LeftProperty));
  }
  else if (e.Key == Key.Right)
  {
    animation.From = x;
    animation.To = x + mDist;
    Storyboard.SetTargetProperty(
      animation, new PropertyPath(Canvas.LeftProperty));
  }
  else if (e.Key == Key.Up)
  {
    animation.From = y;
    animation.To = y - mDist;
    Storyboard.SetTargetProperty(
      animation, new PropertyPath(Canvas.TopProperty));
  }
  else if (e.Key == Key.Down)
  {
    animation.From = y;
    animation.To = y + mDist;
    Storyboard.SetTargetProperty(
      animation, new PropertyPath(Canvas.TopProperty));
  }
 
  Storyboard.SetTarget(animation, myEllipse);
  mySB.Children.Add(animation);
  mySB.Begin();
}

So starting from the top, the first thing we do is get the current position of our Ellipse. We can't really do very much without our object's current position. It is important to do this at a specific point, because the animation is of course going to change that position. Once we have the position, we begin to create the animation. Yes, there is a DoubleAnimation object we can use, but that is not the only important object.

The first thing we do with our animation is set up its duration, which is done using the Duration object and Timespan class. Using Timespan's methods, we can set the duration to seconds, minutes, hours, or even days.

Now, it gets a little crazy when we get to the different movement directions. For each direction, we have to set the animation's To and From properties. Then we use some a static method in the Storyboard class called SetTargetProperty(), which allows us to tell the animation what property to animate on the target. For horizontal movement, that would be the LeftProperty, vertical the TopProperty. The tricky thing is that you have to use the Canvas class to get these properties. To make things even crazier, you have to pass it as an object called PropertyPath so you have to create that object as well. Then whole thing ends up being a web of objects and static methods.

Before we can finally add the animation to the storyboard, we have to set its target. In this case we are going to target our ellipse. We do this with the static method SetTarget in the Storyboard class. Once the target has been set, we add it to the storyboard, then start the animation.

If you ran the code we have now, you will notice one thing, it only works once. If you try to add the animation more than once, Silverlight doesn't really like it, so it fails. What we have to do is remove the current animation from the storyboard, or better yet, clear it entirely. This was the really tricky part.

In order to clear the storyboard, any animations attached have to be stopped. This is fine, but in order for things to work, we have to take the position of the ellipse before we clear the animations. So, we pause, take the position, then finally stop and clear the animations. But, one final step is setting the position of the ellipse. This has to do with animating only one axis at a time. While the animation is going, only one axis is truly updated, so we need to set the position to make sure we have the right coordinates for the animation. The final version will look something like so:

private void canvas1_KeyUp(object sender, KeyEventArgs e)
{
  Double mDist = 100.00;
  Double mSpeed = 0.5;

  mySB.Pause();

  Double x = Canvas.GetLeft(myEllipse);
  Double y = Canvas.GetTop(myEllipse);

  mySB.Stop();
  mySB.Children.Clear();

  Canvas.SetLeft(myEllipse, x);
  Canvas.SetTop(myEllipse, y);

  DoubleAnimation animation = new DoubleAnimation();
  animation.Duration = new Duration(TimeSpan.FromSeconds(mSpeed));

  if (e.Key == Key.Left)
  {
    animation.From = x;
    animation.To = x - mDist;
    Storyboard.SetTargetProperty(
      animation, new PropertyPath(Canvas.LeftProperty));
  }
  else if (e.Key == Key.Right)
  {
    animation.From = x;
    animation.To = x + mDist;
    Storyboard.SetTargetProperty(
      animation, new PropertyPath(Canvas.LeftProperty));
  }
  else if (e.Key == Key.Up)
  {
    animation.From = y;
    animation.To = y - mDist;
    Storyboard.SetTargetProperty(
      animation, new PropertyPath(Canvas.TopProperty));
  }
  else if (e.Key == Key.Down)
  {
    animation.From = y;
    animation.To = y + mDist;
    Storyboard.SetTargetProperty(
      animation, new PropertyPath(Canvas.TopProperty));
  }

  Storyboard.SetTarget(animation, myEllipse);
  mySB.Children.Add(animation);
  mySB.Begin();
}

This gives us the animated movement we are looking for. Not a lot of code, but there is a lot going on. After using 3 separate key classes, and even more objects, we can dynamically create and use animations to move our ellipse around the screen.

Well, this wraps up this tutorial. I hope you learned something, and just remember that if you need coding help, all you have to do is Switch On The Code.

Anonymous
09/15/2009 - 17:18

I am trying to get started on Silverlight - and I really appreciate your taking the time to post these. They are more helpful than most examples I've run across.

reply

Anonymous
03/28/2010 - 13:27

Question, my version of C# doesn't have Silverlight options, how would I add them in?

reply

The Reddest
03/29/2010 - 08:42

You need to go to the Silverlight website and grab the SDK or the Visual Studio development tools.

reply

bluewater
11/22/2011 - 05:16

This helped me a lot. Thank you!

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.