I hope this article will help my friends who are devoted to Silverlight games.
CodeDownload: silverlighttestwbresource.zip
The directory settings are as follows:
Scenario 1: Set all PNG files to resource and do not copy.
Source code of the specified image:
Spirit. Source =NewBitmapimage(NewUri(@ "Player /"+ Count +". PNG",Urikind. Relative ));
Note that the relative path is used here, which is the position of the current mainpage. XAML relative to the image, rather than the server path.
If the source of the image is specified in spirit, that is, the relative path is changed, the code should be written as follows:
Body. Source =NewBitmapimage(NewUri(@ "../Player/2.png",Urikind. Relative ));
In this case, all images are embedded into the DLL as resources. Observing the organizational structure in the xap confirms our conclusion:
Scenario 2: Set all PNG files to content and copy If newer.
Source code of the specified image:
Spirit. Source =NewBitmapimage(NewUri(@ "/Player /"+ Count +". PNG",Urikind. Relative ));
Note that the server path is used, but the relative path is not used.
One advantage of using the server path is that no matter where the XAML is located, it can be ignored. For example, the above spirit control:
Body. Source =NewBitmapimage(NewUri(@ "/Player/2.png",Urikind. Relative ));
In this case, all the images are packaged into the xap player directory. Observing the organization structure in the xap confirms our conclusion:
The player folder contains the 8 PNG images ranging from 0 to 7.
The Technology analyzed below is to take a big picture and only part of it.
There are two methods:
Method 1: Use clip technology.
Public partial class Mainpage : Usercontrol {Private int Count = 1; Private Image Spirit; Public Mainpage () {initializecomponent (); spirit = New Image () {Width = 1500, Height = 150, source = New Bitmapimage ( New Uri ( @ "Player/playermagic.png" , Urikind . Relative)}; carrier. Children. Add (spirit ); Dispatchertimer Dispatchertimer = New Dispatchertimer (); Dispatchertimer. Tick + = dispatchertimer_tick; dispatchertimer. interval = Timespan . Frommilliseconds (150); dispatchertimer. Start ();} Void Dispatchertimer_tick ( Object Sender, Eventargs E) {spirit. Clip = New Rectanglegeometry () {Rect =New Rect (Count * 150, 0,150,150)}; spirit. rendertransform = New Translatetransform () {X =-count * 150}; Count = COUNT = 7? 0: Count + 1 ;}}
You can use the relative path or server path. Of course, you must set the image to resource or content.
Method 2: Use writeablebitmap Technology
This writeablebitmap is very mysterious and should be noted in many aspects during use. I almost got killed by the dark blue right hand yesterday and got to the QQ Group for discussion. Only then did I know that many people are equally troubled and confused.
1) programming model using server paths:
Public partial class Mainpage : Usercontrol { Private int Count = 1; Private Image Spirit; Public Mainpage () {initializecomponent (); spirit = New Image () {Width = 150, Height = 150}; carrier. Children. Add (spirit ); Dispatchertimer Dispatchertimer = New Dispatchertimer (); Dispatchertimer. Tick + = dispatchertimer_tick; dispatchertimer. interval = Timespan . Frommilliseconds (150); dispatchertimer. Start ();}Void Dispatchertimer_tick ( Object Sender, Eventargs E ){ // Spirit. Source = new bitmapimage (New uri (@ "/images/" + Count + ". PNG", urikind. Relative )); Spirit. Source = composeequip ( @ "/Images/body0.png" , 150,150, New Point (-Count * 150, 0); Count = COUNT = 33? 0: Count + 1 ;} Public static Writeablebitmap Composeequip ( String Bodyaddress,Int Width, Int Height, Point Bodyoffset ){ Writeablebitmap Writeablebitmap = New Writeablebitmap (Width, height); writeablebitmap. Render ( New Image () {Source = getimage (bodyaddress )}, New Translatetransform () {X = bodyoffset. X, Y = bodyoffset. y}); writeablebitmap. invalidate (); Return Writeablebitmap ;}Public static Bitmapsource Getimage ( String Address ){ Return new Bitmapimage ( New Uri ( String . Format ( @ "{0 }" , Address ), Urikind . Relative ));}}
If we want to merge two images, the composeequip method may be as follows:
Public static Writeablebitmap Composeequip ( String Bodyaddress, String Weaponaddress, Int Width, Int Height, Point Bodyoffset, Point Weaponoffset ){ Writeablebitmap Writeablebitmap = New Writeablebitmap (Width, height); writeablebitmap. Render ( New Image () {Source = Super . Getimage (bodyaddress )}, New Translatetransform () {X = bodyoffset. X, Y = bodyoffset. y}); writeablebitmap. Render ( New Image () {Source = Super . Getimage (weaponaddress )}, New Translatetransform () {X = weaponoffset. X, Y = weaponoffset. y}); writeablebitmap. invalidate (); Return Writeablebitmap ;}
2) programming model using relative paths:
How to replace the above path with a relative path and change the image to a resource is not a problem.
I guess the problem lies in writeablebitmap. Render (....); And writeablebitmap. invalidate. Because render takes time,
How can this problem be solved?
Someone had an idea to open a thread between the two statements and then sleepfor 1 second, but he didn't take into account that our composeequip is a method to execute every 150mm.
The correct solution is as follows:
We have attached a method to the imageopened event of the large image to be loaded. In this method, we cut the large image into several small images, and put it in the frames array-in this case, large images can be used, so there is no need to worry about the blank space when cutting.
Note that when Will bitmap_imageopened be triggered? We can see the last statement of the mainpage constructor:
Spirit. Source = bitmap;
Yes, it is triggered when this statement is executed -- do not believe? Comment out this sentence to see if the bitmap_imageopened method can be executed. I did not see the breakpoint will stop here.
Public partial class Mainpage : Usercontrol { Private int Count = 1; Private Image Spirit; Imagesource [] Frames = New Imagesource [10]; Public Mainpage () {initializecomponent (); spirit = New Image (); Bitmapimage Bitmap = New Bitmapimage ( New Uri ( @ "Src/playermagic.png" ,Urikind . Relative); bitmap. imageopened + = New Eventhandler < Routedeventargs > (Bitmap_imageopened); carrier. Children. Add (spirit); spirit. Visibility = Visibility . Collapsed; spirit. Source = bitmap ;} Void Dispatchertimer_tick ( Object Sender, Eventargs E) {spirit. Source = frames [count]; Count = COUNT = 7? 0: Count + 1 ;} Void Bitmap_imageopened (Object Sender, Routedeventargs E) {spirit. Source = sender As Bitmapimage ; For ( Int J = 0; j <10; j ++ ){ Writeablebitmap WB = New Writeablebitmap (150,150); WB. Render (spirit, 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 ); // Repetition Interval Dispatchertimer. Start (); spirit. Source = frames [count]; spirit. Visibility = Visibility . Visible ;}}
In other words, when I was learning the dark blue right hand game tutorial, I converted his WPF version into the Silverlight version. During this period, I found this problem. The dark blue right hand handed me a task last night, that is, to understand this study and then give an ultimate answer. So this articleArticle.
Review the key points of this article,
1. Differences between images, resources, and content
2. Applicable scenarios of clip and writeablebitmap