2 votes

WPF - Événement de fin d'animation Storyboard

Je conçois un jeu comme ça

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();
    }
}

Tout est génial, mais j'ai remarqué que l'ellipse n'obtient pas la bonne position et commet une erreur d'environ 2% à 50%. Il semble que l'événement Storyboard.Completed soit déclenché avant la fin de l'animation.

Qu'est-ce qui cloche ?

2voto

Milan Nankov Points 678

Je suggère que vous utilisiez l'événement CompositionTarget.Rendering ou DispatcherTimer pour contrôler des animations complexes, surtout si vous développez un jeu. Les animations intégrées ne sont pas assez précises et ne peuvent pas être contrôlées facilement.

Voici quelques liens qui vous aideront à démarrer avec CompositionTarget

Comment : Rendre à un intervalle par image en utilisant CompositionTarget

Utilisation de CompositionTarget

Plaisir avec Animation Partie 1

0voto

Kevin Points 11

Utilisez Dispatcher.BeginInvoke(...), vous pouvez obtenir la bonne valeur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X