MMORPG programming in Silverlight tutorial (9) keyframe Animation

Source: Internet
Author: User

In the last chapter, I introduce a * algorithm, so the object can find the shortest path itself, I print the path array on the canvas. this chapter I will animate the object to pass through the path array from start to the end.

We still use the demo in the last chapter.

1st, add an ellipse namedPlayerInto the canvas, as the Sprite in our demo.

//the spriteprivate Ellipse player;private void InitPlayer(){    player = new Ellipse()    {        Fill = new SolidColorBrush(Colors.Blue),        Width = gridSize,        Height = gridSize    };    Carrier.Children.Add(player);    //init start point    Canvas.SetLeft(player, gridSize);    Canvas.SetTop(player, 5 * gridSize);}

2nd, add obstruction in the method initmatrix.

void InitMatrix(){    for (int y = 0; y < matrix.GetUpperBound(1); y++)    {        for (int x = 0; x < matrix.GetUpperBound(0); x++)        {            matrix[x, y] = 1;        }    }    for (int y = 3; y < 30; y++)    {        matrix[3, y] = 0;        rect = new Rectangle();        rect.Fill = new SolidColorBrush(Colors.Red);        rect.Width = gridSize;        rect.Height = gridSize;        Carrier.Children.Add(rect);        Canvas.SetLeft(rect, 3 * gridSize);        Canvas.SetTop(rect, y * gridSize);    }    for (int y = 3; y < 20; y++)    {        matrix[24, y] = 0;        rect = new Rectangle();        rect.Fill = new SolidColorBrush(Colors.Red);        rect.Width = gridSize;        rect.Height = gridSize;        Carrier.Children.Add(rect);        Canvas.SetLeft(rect, 24 * gridSize);        Canvas.SetTop(rect, y * gridSize);    }    for (int i = 0; i < 18; i++)    {        matrix[i, 12] = 0;        rect = new Rectangle();        rect.Fill = new SolidColorBrush(Colors.Red);        rect.Width = gridSize;        rect.Height = gridSize;        Carrier.Children.Add(rect);        Canvas.SetLeft(rect, i * gridSize);        Canvas.SetTop(rect, 12 * gridSize);    }    for (int i = 12; i < 17; i++)    {        matrix[17, i] = 0;        rect = new Rectangle();        rect.Fill = new SolidColorBrush(Colors.Red);        rect.Width = gridSize;        rect.Height = gridSize;        Carrier.Children.Add(rect);        Canvas.SetLeft(rect, 17 * gridSize);        Canvas.SetTop(rect, i * gridSize);    }    for (int i = 3; i < 18; i++)    {        matrix[i, 16] = 0;        rect = new Rectangle();        rect.Fill = new SolidColorBrush(Colors.Red);        rect.Width = gridSize;        rect.Height = gridSize;        Carrier.Children.Add(rect);        Canvas.SetLeft(rect, i * gridSize);        Canvas.SetTop(rect, 16 * gridSize);    }}

 

3rd, execute these 2 Methods abve in our constructor.

public MainPage(){    InitializeComponent();    //init matrix    InitMatrix();    //init sprite    InitPlayer();   }

 

4. Add keyframe in the method carrier_mouseleftbuttondown, I have written enough comment in the code, which can help you understand more clearly.

private void Carrier_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){    Point p = e.GetPosition(Carrier);    //scale down the coordinate of start and end    int start_x = (int)Canvas.GetLeft(player) / gridSize;    int start_y = (int)Canvas.GetTop(player) / gridSize;    start = new Point(start_x, start_y);    int end_x = (int)p.X / gridSize;    int end_y = (int)p.Y / gridSize;    end = new Point(end_x, end_y);    //use A* algorithm    IPathFinder pathFinder = new PathFinderFast(matrix);    pathFinder.Formula = HeuristicFormula.Manhattan;     pathFinder.HeavyDiagonals = true;    pathFinder.HeuristicEstimate = 0;    var path = pathFinder.FindPath(start, end);    if (path == null)    {        MessageBox.Show("The path doesn't exist");        return;    }    //define keyframe array    Point[] framePosition = new Point[path.Count];    for (int i = path.Count - 1; i >= 0; i--)    {        //fill keyframe array from the start of the path array, and enlarge the coordinate        framePosition[path.Count - 1 - i] = new Point(path[i].X * gridSize, path[i].Y * gridSize);    }    //create storyboard    Storyboard storyboard = new Storyboard();    int cost = 100; //spend 100ms per grid(20*20)    //create animation frame by frame in X-coordinate    DoubleAnimationUsingKeyFrames keyFramesAnimationX = new DoubleAnimationUsingKeyFrames();    //all the spending time = path.Count * cost    keyFramesAnimationX.Duration = new Duration(TimeSpan.FromMilliseconds(path.Count * cost));    Storyboard.SetTarget(keyFramesAnimationX, player);    Storyboard.SetTargetProperty(keyFramesAnimationX, new PropertyPath("(Canvas.Left)"));    //create animation frame by frame in Y-coordinate    DoubleAnimationUsingKeyFrames keyFramesAnimationY = new DoubleAnimationUsingKeyFrames();    keyFramesAnimationY.Duration = new Duration(TimeSpan.FromMilliseconds(path.Count * cost));    Storyboard.SetTarget(keyFramesAnimationY, player);    Storyboard.SetTargetProperty(keyFramesAnimationY, new PropertyPath("(Canvas.Top)"));    for (int i = 0; i < framePosition.Count(); i++)    {        //add keyframe in X-coordinate        LinearDoubleKeyFrame keyFrame = new LinearDoubleKeyFrame();        keyFrame.Value = i == 0 ? Canvas.GetLeft(player) : framePosition[i].X;        keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i));        keyFramesAnimationX.KeyFrames.Add(keyFrame);        //add keyframe in Y-coordinate        keyFrame = new LinearDoubleKeyFrame();        keyFrame.Value = i == 0 ? Canvas.GetTop(player) : framePosition[i].Y;        keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i));        keyFramesAnimationY.KeyFrames.Add(keyFrame);    }    storyboard.Children.Add(keyFramesAnimationX);    storyboard.Children.Add(keyFramesAnimationY);    //start the storyboard    storyboard.Begin();    //trace the moving by white points    for (int i = path.Count - 1; i >= 0; i--)    {        rect = new Rectangle()        {            Fill = new SolidColorBrush(Colors.White),            Width = 5,            Height = 5        };        Carrier.Children.Add(rect);        Canvas.SetLeft(rect, path[i].X * gridSize);        Canvas.SetTop(rect, path[i].Y * gridSize);    }}

 

More or less, the principle is that, when we click on the canvas, we will start and end point at once.

We add keyframesanimationx and keyframesanimationy In the storyboard, they are timeline in the X and Y coordinate.

//create animation frame by frame in X-coordinateDoubleAnimationUsingKeyFrames keyFramesAnimationX = new DoubleAnimationUsingKeyFrames();//all the spending time = path.Count * costkeyFramesAnimationX.Duration = new Duration(TimeSpan.FromMilliseconds(path.Count * cost));Storyboard.SetTarget(keyFramesAnimationX, player);Storyboard.SetTargetProperty(keyFramesAnimationX, new PropertyPath("(Canvas.Left)"));//create animation frame by frame in Y-coordinateDoubleAnimationUsingKeyFrames keyFramesAnimationY = new DoubleAnimationUsingKeyFrames();keyFramesAnimationY.Duration = new Duration(TimeSpan.FromMilliseconds(path.Count * cost));Storyboard.SetTarget(keyFramesAnimationY, player);Storyboard.SetTargetProperty(keyFramesAnimationY, new PropertyPath("(Canvas.Top)"));

...... (Ignore some code)

storyboard.Children.Add(keyFramesAnimationX);storyboard.Children.Add(keyFramesAnimationY);

 

Then we add keyframe in the timeline:

for (int i = 0; i < framePosition.Count(); i++){    //add keyframe in X-coordinate    LinearDoubleKeyFrame keyFrame = new LinearDoubleKeyFrame();    keyFrame.Value = i == 0 ? Canvas.GetLeft(player) : framePosition[i].X;    keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i));    keyFramesAnimationX.KeyFrames.Add(keyFrame);    //add keyframe in Y-coordinate    keyFrame = new LinearDoubleKeyFrame();    keyFrame.Value = i == 0 ? Canvas.GetTop(player) : framePosition[i].Y;    keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i));    keyFramesAnimationY.KeyFrames.Add(keyFrame);}

 

Finally, we print all the path element in white color. notice that the first element in the path array is the end point of the path ., so we need to iterate the path array from end to start.

OK, press Ctrl + F5, click on the canvas. the original point of the ellipse is. when I click on the point B, the ellipse Begins moving. when the ellipse passes through the point C, we click on the other point D, the ellipse will change direction at once, it dues to the features of timeline and keyframe.

 

 

Summary: This chapter introduce how to integrate a * algorithm and keyframe, so we can control the animation freely.

Next chapter, I will implement how to add all these techniques in our game engine. Please focus on it.

Chinese friend, You can also visit this Chinese blog if you feel difficult to read English, http://www.cnblogs.com/alamiye010/archive/2009/06/17/1505346.html, part of my article is base on it.

Demo download: http://silverlightrpg.codeplex.com/releases/view/40978

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.