In chapter 5, we study how to use image's clip and rendertransform to create animation for Sprite.
Now, I will introduce a new method base on writeablebitmap to cut the image. You can use it as follows:
BitmapimageBitmap =NewBitmapimage(NewUri(@ "/Images/role/sprite.png",Urikind. Relative ));
ImageImage =NewImage();
Image. Source = bitmap;
WriteablebitmapWB =NewWriteablebitmap(150,150 );
WB. Render (image,NewTranslatetransform() {X =-150 * j });
WB. invalidate ();
Sprite. Source = WB;
The code snippet above show the simplest syntax how to use writeablebitmap to get part of the large picture. but in our project, we always find this snippet will throw an exception because the large picture still not be loaded when we invoke writeablebitmap's render method. the solution is that we register bitmap_imageopened method to image's imageopened event, and invoke WB. render () in this method. we refract the Code as follows:
Public partial class Mainpage : Usercontrol {Private int Count = 1; Private Image Sprite; Imagesource [] Frames = New Imagesource [10]; Public Mainpage () {initializecomponent (); sprite = New Image (); Bitmapimage Bitmap = New Bitmapimage ( New Uri ( @ "/Images/role/sprite.png" , Urikind . Relative); bitmap. imageopened + = New Eventhandler < Routedeventargs > (Bitmap_imageopened); carrier. Children. Add (sprite); Sprite. Visibility = Visibility . Collapsed; Sprite. Source = bitmap ;} Void Dispatchertimer_tick ( Object Sender, Eventargs E) {Sprite. Source = frames [count]; Count = COUNT = 7? 0: Count + 1 ;} Void Bitmap_imageopened ( Object Sender, Routedeventargs E) {Sprite. Source = sender As Bitmapimage ; For ( Int J = 0; j <10; j ++ ){ Writeablebitmap WB = New Writeablebitmap (150,150); WB. Render (sprite,New Translatetransform () {X =-150 * j}); WB. invalidate (); frames [J] = ( Imagesource ) WB ;} Dispatchertimer Dispatchertimer = New Dispatchertimer (); Dispatchertimer. Tick + = New Eventhandler (Dispatchertimer_tick); dispatchertimer. interval = Timespan . Fromilliseconds (150 ); Dispatchertimer. Start (); Sprite. Source = frames [count]; Sprite. Visibility = Visibility . Visible ;}}
You can also find I set up an array to store all the small pictures.
Imagesource[] Frames =NewImagesource[10];
It is convenient for you to reuse them in the animation again and again.
Maybe you want to know when image's imageopened event was fired. I have tried, and find it occurs when you set image's source property:
Sprite. Source = bitmap;
If you don't believe it, please mark this sentence, and check if the method bitmap_imageopened will be executed.
The other code above is the same as last chapter, so I won't spend time on it. please refer to (5) Implement the sprite's 2D animation (part II) for details.
OK, press Ctrl + F5, you will find the Sprite can run now, the effect is the same as the previous chapter.
Now, let us compare these 2 techniques, clip and writeablebitmap. the former I introduced in the last chapter, is easy to use, but I am not sure if you have found, each time the sprite change to next frame, we must do the same clip action on the large picture. the performance is low.
The latter, writeablebitmap, Because I store all the small image into the memory, so we don't need to do the same action on the large picture again. although it is not convenient in coding, it is more flexible.
Summary: This chapter introduce the 3rd method to control object's own animation. writeablebitmap is so powerful that, it is widely used in animation, I will introduce this technique in the following chapters.
Next chapter, I will implement sprite's animation, both moving in distance and its own animation. 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