MMORPG programming in Silverlight tutorial (13) Perfect moving mechanic

Source: Internet
Author: User

Now it is time to resolve the issue left in chapter 8, when there are no obstructions between the distinction and original place, the sprite still use a * algorithm to find path, rather than moving between these 2 point directly, as follows:

So we need to modify moving mechanic. when we click on the map, the sprite 'Action is default to move in straight path. and we create a new thread to detect if the sprite meet obstruction during his moving all the time. this time we use compositiontarget. rendering, because we have used dispatchertimer In the sprite's own animation, we want to distinguish these 2 different threads.

If the sprite find an obstruction during his moving, he will use a * algorithm until he walk around it. Then he will move straightly again. This process will last until the sprite arrive the distinction.

All the analysis above can be divided into 3 steps in our demo:

1st, pick the color of the sprite's distinction, if it is not an obstruction, move in a straight way; otherwise, no actions.

// Record the sprite's distinationPointTarget;Private voidCarrier_mouseleftbuttondown (ObjectSender,MousebuttoneventargsE ){PointP = E. getposition (carrier );// If the click point is not an obstructionIf(Pickcolor (copymap ,(Int) P. x ,(Int) P. Y, carrier. actualwidth )! =Colors. Black) {target = P;// Move in a straight pathStraightmove (p );}}

 

2nd, detect obstruction in a new thread all the time:

PublicMainpage () {initializecomponent ();
 
......
 
Compositiontarget. Rendering + =NewEventhandler(Compositiontarget_rendering );}

 
 
 Void Compositiontarget_rendering ( Object Sender, Eventargs E ){ Int X = Convert . Toint32 ( Canvas . Getleft (sprite) + spritecenterx );Int Y = Convert . Toint32 ( Canvas . Gettop (sprite) + spritecentery ); VaR Color = pickcolor (copymap, X, Y, carrier. actualwidth ); // If meet obstruction, use a * Algorithm  If (Color = Colors . Black) {astarmove (target );} // Trace the path in white, if not necessary, we need to mark them in our release version  VaR Rect = New  Rectangle (); Rect. Fill = New  Solidcolorbrush ( Colors . White); rect. width = 5; rect. Height = 5; carrier. Children. Add (rect ); Canvas . Setleft (rect, X ); Canvas . Settop (rect, Y );}

 
 

The functions straightmove and astarmove are implemented as follows, please be careful the sprite's coordinate when set canvas's left and top properties.

 Private void Straightmove ( Point P ){// Create storyboard Storyboard = New  Storyboard (); // Create Animation frame by frame in X-Coordinate  Doubleanimation Doubleanimation = New  Doubleanimation () {From = Canvas . Getleft (sprite), to = p. x-spritecenterx, duration = New  Duration ( Timespan . Frommilliseconds (1000 )),};Storyboard . Settarget (doubleanimation, Sprite ); Storyboard . Settargetproperty (doubleanimation, New  Propertypath ( "(Canvas. Left )" ); Storyboard. Children. Add (doubleanimation ); // Create Animation frame by frame in Y-Coordinate Doubleanimation = New  Doubleanimation () {From = Canvas . Gettop (sprite), to = P. Y-spritecentery, duration = New Duration ( Timespan . Frommilliseconds (1000 )),}; Storyboard . Settarget (doubleanimation, Sprite ); Storyboard . Settargetproperty (doubleanimation, New  Propertypath ( "(Canvas. Top )" ); Storyboard. Children. Add (doubleanimation ); // Start the storyboard Storyboard. Begin ();} Private void Astarmove ( Point P ){// Scale down the coordinate of start and end  Int Start_x = ( Int )( Canvas . Getleft (sprite) + spritecenterx)/gridsize; Int Start_y = ( Int )( Canvas . Gettop (sprite) + spritecentery)/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; List < Pathfindernode > Path = Pathfinder. findpath (START, end ); // 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 100 ms per grid (20*20) // Create Animation frame by frame in X-Coordinate  Doubleanimationusingkeyframes Keyframesanimationx = New  Doubleanimationusingkeyframes (); Keyframesanimationx. Duration = New  Duration ( Timespan . Frommilliseconds (path. Count * cost ));// All the spending time = path. Count * cost  Storyboard . Settarget (keyframesanimationx, Sprite ); 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, Sprite ); 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 (sprite): (frameposition [I]. X-spritecenterx); 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 (sprite): (frameposition [I]. Y-spritecentery); keyframe. keytime = Keytime . Fromtimespan ( Timespan . Frommilliseconds (Cost * I); keyframesanimationy. keyframes. Add (keyframe);} storyboard. Children. Add (contents); storyboard. Children. Add (keyframesanimationy ); // Start the storyboard Storyboard. Begin ();}

 

OK, press Ctrl + F5, we can see the effect as we expected before:

Notice, to trace the sprite's moving, we add invalid white point in the canvas, which will reduce the performance of the game engine. so in the actual programming, please mark it if not necessary, you can find it in the method compositiontarget_rendering.

 

Summary: This chapter introduce a perfect moving animation. Our game engine is more and more robust.

Next chapter, I will introduce how to object-oriented programming in Silverlight. I will separate the sprite from the main logic. 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.