views:

1668

answers:

1

I'm designing a game like this

class Anima
{
 Storyboard story;
 Random rand;
 Canvas canvas;
 Ellipse target;

 public Anima() {
  rand = new Random();
  canvas = new Canvas();
  target = new Ellipse();

  target.Fill = Brushes.Red;
  target.Width = 50;
  target.Height = 50;
  Canvas.SetLeft(target, rand.NextDouble() * 300);
  Canvas.SetTop(target, rand.NextDouble() * 300);
  canvas.Children.Add(target);

  story = new Storyboard();
  story.BeginTime = TimeSpan.FromMilliseconds(rand.Next(500, 5000));

  DoubleAnimation a = new DoubleAnimation();
  a.To = rand.NextDouble() * 300;
  a.Duration = new Duration(TimeSpan.FromMilliseconds(50));

  Storyboard.SetTarget(a, target);
  Storyboard.SetTargetProperty(a, new PropertyPath(Canvas.LeftProperty));
  story.Children.Add(a);

  DoubleAnimation b = new DoubleAnimation();
  b.To = rand.NextDouble() * 300;
  b.Duration = new Duration(TimeSpan.FromMilliseconds(50));

  Storyboard.SetTarget(b, target);
  Storyboard.SetTargetProperty(b, new PropertyPath(Canvas.TopProperty));
  story.Children.Add(b);

  story.Completed += new EventHandler(story_Completed);

  Window win = new Window();

  win.Loaded += delegate(object sender, RoutedEventArgs e) {
   story.Begin();
  };

  win.Content = canvas;
  win.Show();
 }

 void story_Completed(object sender, EventArgs e) {
  int next = rand.Next(500, 5000);
  double left = rand.NextDouble() * 300;
  double top = rand.NextDouble() * 300;

  Console.WriteLine("position: ({0:G6}, {1:G6})", Canvas.GetLeft(target), Canvas.GetTop(target));
  Console.WriteLine("state   : wait for " + next + " ms");
  Console.WriteLine("next    : ({0:G6}, {1:G6})", left, top);
  Console.WriteLine();

  (story.Children[0] as DoubleAnimation).To = left;
  (story.Children[1] as DoubleAnimation).To = top;

  story.BeginTime = TimeSpan.FromMilliseconds(next);
  story.Begin();
 }
}

Everything is great, but I found that the ellipse didn't get the right position and make an error about 2% to 50%. It seems like the Storyboard.Completed event triggered before the end of animation.

What's wrong with it?

A: 

I would suggest that you use CompositionTarget.Rendering event or DispatcherTimer for controlling complex animations, especially if you are developing a game. The built-in animations are not precise enough and cannot be controlled easily.

Here are some links that will get you started on CompositionTarget

How to: Render on a Per Frame Interval Using CompositionTarget

Using the CompositionTarget

Fun with Animation Part 1

Milan Nankov