Reprint please indicate the source: http://blog.csdn.net/lmj623565791/article/details/40595385, this article from: "Zhang Hongyang Blog" 1, overview
After 2048, today to bring you a jigsaw puzzle, of course, is not very traditional that missing piece of the puzzle, that game I will not play ~ ~ All of us to play the puzzle, how to play, the picture and into many parts, click Exchange to make a complete; So the level is easy to design, 3*3;4*4;5*5;6 *6, ..... Keep going ....
The reason for the blog is that nothing in the online browsing to see a picture of the auxiliary class, the class is very simple, above said a sentence, if you do jigsaw puzzles can be used, and then we use the ~ ~
As for the effect is this:
Added a toggle animation, the effect is good ~ ~ In fact, the game is to customize a control, the following we began to customize the trip ~ ~
2, the design of the game
First we analyze how to design this game:
1, we need a container, can put the blocks of these pictures, for convenience, we are ready to use relativelayout with addrule to achieve
2, each picture block, we are ready to use ImageView
3, click Exchange, we are ready to use the traditional translationanimation to achieve
With a preliminary design, feel this game so easy~
3, the implementation of the game layout
First, we are ready to achieve the ability to put a picture, cut into n*n parts, placed in the specified position;
We only need to set n this number, and then according to the layout of the width or height of the small value, divided by N, minus some of the margin can get our imageview width and height ~ ~
1. Construction Method:
/** * Sets the number of item n*n; default is 3 */private int mcolumn = 3;/** * Layout width */private int mwidth;/** * layout padding */private int mpadding /** * Store all item */private imageview[] mgamepintuitems;/** * Item width */private int mitemwidth;/** * Item Landscape with portrait margin */private int mmargin = 3;/** * Picture of the jigsaw */private Bitmap mbitmap;/** * Store the picture bean after cutting */private list<imagepiece> MITEMBITMAPS;PR Ivate Boolean Once;public gamepintulayout (context context) {This (context, null);} Public Gamepintulayout (context context, AttributeSet Attrs) {This (context, attrs, 0);} Public Gamepintulayout (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, defstyle); mmargin = (int ) typedvalue.applydimension (Typedvalue.complex_unit_dip,mmargin, Getresources (). Getdisplaymetrics ());// Set the inner margin of the layout, four sides consistent, set to the minimum value in the Quad padding mpadding = min (Getpaddingleft (), Getpaddingtop (), Getpaddingright (), Getpaddingbottom ());}
In the construction method, we get the margin value of the set to be converted to DP, get the padding value of the layout, the whole is a square, so we take the minimum value in the padding four direction;
As for margin, as item between the horizontal and vertical spacing, you can extract a custom attribute if you like ~ ~
2, Onmeasure
@Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC);//Get the game layout side length Mwidth = Math.min (Getmeasuredheight (), Getmeasuredwidth ()), if (!once) {initbitmap (); Inititem ();} once = True;setmeasureddimension (Mwidth, mwidth);}
The main thing in Onmeasure is to get the width of the layout, then prepare the picture, and initialize our item to set the width and height for item.
Initbitmap Nature is to prepare the picture:
private void Initbitmap () {if (Mbitmap = = null) Mbitmap = Bitmapfactory.decoderesource (Getresources (), R.DRAWABLE.AA); Mitembitmaps = Imagesplitter.split (Mbitmap, Mcolumn); Collections.sort (Mitembitmaps, New comparator<imagepiece> () {@Overridepublic int compare (Imagepiece LHS, Imagepiece RHS) {return math.random () > 0.5? 1:-1;}});}
If we don't set up mbitmap, we'll prepare an alternate image, and then call Imagesplitter.split to cut the picture into n * N to return a list<imagepiece>
After the cut, we need to shuffle the order, so we call the sort method, as for the comparator, we use random to randomly compare the size ~ ~ so that we have completed our disorderly operation, like not praise ~ ~
public class imagesplitter{/** * Cut the picture, piece *piece * * @param bitmap * @param piece * @return */public static list& Lt;imagepiece> Split (Bitmap Bitmap, int piece) {list<imagepiece> pieces = new Arraylist<imagepiece> ( piece * piece); int width = bitmap.getwidth (); int height = bitmap.getheight (); LOG.E ("TAG", "bitmap width =" + width + ", height =" + height "), int piecewidth = math.min (width, height)/piece;for (in t i = 0; I < piece; i++) {for (int j = 0; J < piece; J + +) {imagepiece imagepiece = new Imagepiece (); imagepiece.index = j + I * piece;int xval UE = J * Piecewidth;int yvalue = i * piecewidth;imagepiece.bitmap = Bitmap.createbitmap (Bitmap, XValue, Yvalue,piecewidth, Piecewidth);p Ieces.add (imagepiece);}} return pieces;}}
public class Imagepiece{public int index = 0;public Bitmap Bitmap = null;}
No, no, no, it's a process based on width height, and n, to save the diagram ~ ~
Imagepiece saved pictures and indexes ~ ~ Say these two classes or I accidentally found on the Internet ~ ~
The picture is ready, now look at the item's build has been set wide, that is Inititems
private void Inititem () {//Gets the item's width int childwidth = (mwidth-mpadding * 2-mmargin * (mColumn-1))/Mcolumn;mitemwidth = Childwidth;mgamepintuitems = new Imageview[mcolumn * mcolumn];//place itemfor (int i = 0; i < mgamepintuitems.length; I + +) {ImageView item = new ImageView (GetContext ()); Item.setonclicklistener (this); Item.setimagebitmap ( Mitembitmaps.get (i). bitmap); Mgamepintuitems[i] = Item;item.setid (i + 1); Item.settag (i + "_" + mitembitmaps.get (i). index); Relativelayout.layoutparams LP = new Layoutparams (mitemwidth,mitemwidth);//Set the horizontal margin, not the last column if ((i + 1)% Mcolumn! = 0) {Lp.ri Ghtmargin = Mmargin;} If not the first column if (i% mcolumn! = 0) {lp.addrule (Relativelayout.right_of,//mgamepintuitems[i-1].getid ());} If not the first line,//Set the longitudinal margin, not the last line if ((i + 1) > Mcolumn) {lp.topmargin = Mmargin;lp.addrule (relativelayout.below,// Mgamepintuitems[i-mcolumn].getid ());} AddView (item, LP);}}
Can see the calculation of our item width: childwidth = (mwidth-mpadding * 2-mmargin * (mColumn-1))/mcolumn;
The width of the container, removing its own padding, removing the spacing between items, and dividing by the number of items to get the item's width ~ ~
The next step is to iterate over the generated item, set rule according to their location, and take a closer look at the comment ~ ~
Note two points:
We set the Setonclicklistener for item, of course, because our game is a point item ~
And we set the TAG:ITEM.SETTAG for item (i + "_" + mitembitmaps.get (i). index);
The tag contains index, which is the correct position, and i,i can help us to find the picture of the current item in Mitembitmaps: (Mitembitmaps.get (i). Bitmap)
This is where the code for the layout of our game ends.
Then we declare the following in the layout file:
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http// Schemas.android.com/tools " android:layout_width=" fill_parent " android:layout_height=" Fill_parent "> <com.zhy.gamepintu.view.gamepintulayout android:id= "@+id/id_gameview" android:layout_width= " Fill_parent " android:layout_height=" fill_parent " android:layout_centerinparent=" true " Android: padding= "5DP" > </com.zhy.gamePintu.view.GamePintuLayout></RelativeLayout>
The activity inside remember to set this layout ~ ~
Now the effect is:
Change a landscape, feel good refreshing ah ~ ~ Our transduction, layout has been completed, is not very simple, and feel that our game has been completed more than half AH ~ ~ ~ The rest is the item's click Processing.
4, the game switching effect
1, the initial switch
Remember when we all added the onclick listener to the item ~ ~
Now we need to implement, click on two item, their picture can happen exchange ~
Well, we need two member variables to store the two item and then swap
Private ImageView mfirst;private ImageView msecond; @Overridepublic void OnClick (View v) {/** * If two clicks are the same */if (Mfirst = = V {mfirst.setcolorfilter (null); mfirst = Null;return;} Click the first itemif (Mfirst = = null) {Mfirst = (ImageView) v;mfirst.setcolorfilter (Color.parsecolor ("#55FF0000"));} else// Click on the second Item{msecond = (ImageView) V;exchangeview ();}}
Click the first, through the Setcolorfilter settings to select the effect, click another again, then we are ready to call Exchangeview to Exchange pictures, of course, this method we have not written, first put ~
If you click the same two times, and remove the check, we'll take nothing.
Next, let's implement Exchangeview:
/** * Swap picture of two item */private void Exchangeview () { mfirst.setcolorfilter (null); String Firsttag = (string) mfirst.gettag (); String Secondtag = (string) msecond.gettag (),//Gets the index position in the list string[] Firstimageindex = Firsttag.split ("_"); string[] Secondimageindex = Secondtag.split ("_"); Mfirst.setimagebitmap (Mitembitmaps.get (Integer.parseInt ( Secondimageindex[0]). Bitmap); Msecond.setimagebitmap (Mitembitmaps.get (Integer.parseint (firstimageindex[0))). bitmap); Mfirst.settag (Secondtag); Msecond.settag (firsttag); mfirst = Msecond = null;}
Should remember our previous settag, forget, go back to see, we also said attention to ~
Through Gettag, get in the list is the index, then get bitmap to Exchange settings, the last swap tag;
By this we have finished the exchange effect, our game can be finished ~ ~ effect is this:
You can see that we can play now ~ ~ Why not refreshing scenery, is because, it is not to see that piece of that piece, or sister intuitive ~
Everyone will spit groove, I rub, animation switch it, obviously not two fly over to swap location, what is this count?
Also, to the program we have to pursue, let's add the animation transition effect ~ ~
2. Seamless animation switching
Let's talk about how to add, I'm ready to use translationanimation, and then the top,left of two item is also very container-acquired;
However, to understand that we actually, item only SetImage has changed, the position of item has not changed;
We now need animation to move the effect, such as a moved to B, no problem, after the move is finished, item has to go back, but the picture has not changed, we still need to manually setimage
This caused a phenomenon, animation switch effect has, but finally there will be a flash, is that we switch pictures caused;
In order to avoid the above phenomenon, can perfect switch effect, here we introduce an animation layer, specifically to do animation effect, a bit like PS layer, below see how we do;
/** * Animation run flag bit */private boolean isaniming;/** * animation layer */private relativelayout manimlayout;/** * Swap two item picture */private Void Exchangeview () {mfirst.setcolorfilter (null); Setupanimlayout ();//Add Firstviewimageview first = new ImageView ( GetContext ()); First.setimagebitmap (Mitembitmaps.get (Getimageindexbytag (String) Mfirst.gettag ()). Bitmap); Layoutparams LP = new Layoutparams (mitemwidth, mitemwidth); lp.leftmargin = Mfirst.getleft ()-Mpadding;lp.topmargin = MFi Rst.gettop ()-MPADDING;FIRST.SETLAYOUTPARAMS (LP); Manimlayout.addview (first);//Add secondviewimageview second = new ImageView (GetContext ()); Second.setimagebitmap (Mitembitmaps.get (Getimageindexbytag (String) Msecond.gettag ()). Bitmap); Layoutparams LP2 = new Layoutparams (mitemwidth, mitemwidth); lp2.leftmargin = Msecond.getleft ()-Mpadding;lp2.topmargin = Msecond.gettop ()-Mpadding;second.setlayoutparams (LP2); Manimlayout.addview (second);//Set Animation translateanimation Anim = new Translateanimation (0, Msecond.getleft ()-Mfirst.getleft (), 0, MsecoNd.gettop ()-mfirst.gettop ()); anim.setduration; Anim.setfillafter (true); First.startanimation (ANIM); Translateanimation Animsecond = new Translateanimation (0,mfirst.getleft ()-Msecond.getleft (), 0, MFirst.getTop ()- Msecond.gettop ()); animsecond.setduration (+); Animsecond.setfillafter (true); Second.startanimation (AnimSecond) ;//Add Animation listener Anim.setanimationlistener (new Animationlistener () {@Overridepublic void Onanimationstart (Animation Animation) {isaniming = True;mfirst.setvisibility (INVISIBLE); msecond.setvisibility (INVISIBLE);} @Overridepublic void Onanimationrepeat (Animation Animation) {} @Overridepublic void Onanimationend (Animation Animation ) {String firsttag = (string) mfirst.gettag (); String Secondtag = (string) msecond.gettag (); string[] Firstparams = Firsttag.split ("_"); string[] Secondparams = Secondtag.split ("_"); Mfirst.setimagebitmap (Mitembitmaps.get (Integer.parseint (secondParams [0]). bitmap); Msecond.setimagebitmap (Mitembitmaps.get (Integer.parseint (firstparams[0)). Bitmap); Mfirst.settag (Secondtag); Msecond.settag (Firsttag); mfirst.setvisibility (visible); msecond.setvisibility (visible); Mfirst = Msecond = Null;manimlayout.removeallviews (); Checksuccess (); isaniming = false;}}); /** * Create animation layer */private void Setupanimlayout () {if (manimlayout = = null) {manimlayout = new Relativelayout (GetContext ()); ADDV Iew (Manimlayout);}} private int Getimageindexbytag (String tag) {string[] split = Tag.split ("_"); return Integer.parseint (Split[0]);}
To start the exchange, we create an animation layer, and then add two identical item on this layer, hide the original item, and then animate it, Setfillafter for true~
After the animation, we have quietly put the picture of the item exchanged, directly displayed. This is the perfect switch:
Approximate process:
1, A, b hidden
2, a copy of the animation moved to the location of B; B copy moved to the location of a
3, a picture set to B, the B copy removed, a display, so that the perfect fit, the user feels that B moved past.
4, B ibid.
Now we have the effect:
Now the effect is satisfied with the ~ ~ in order to prevent the user mad point, in the onclick add a sentence:
@Overridepublic void OnClick (View v) {//If the animation is being performed, the IF (isaniming) return is masked;
To this our animation of the switch, has been the perfect end ~ ~
When switching, we should not judge whether the success of ~ ~
5, the game victory judgment
We are switching to complete, checksuccess (); Fortunately we have the correct order of the picture in the tag inside ~ ~
/** * Determine if the game is successful */private void Checksuccess () {Boolean issuccess = true;for (int i = 0; i < mgamepintuitems.length; i++) { ImageView first = Mgamepintuitems[i]; LOG.E ("TAG", Getindexbytag (String) First.gettag ()) + ""); if (Getindexbytag (String) First.gettag ())! = i) {issuccess = false;}} if (issuccess) {Toast.maketext (GetContext (), "Success, Level Up!", Toast.length_long). Show ();//Nextlevel ();}} /** * Get the real index of the picture * @param tag * @return */private int getindexbytag (String tag) {string[] split = Tag.split ("_"); return Inte Ger.parseint (split[1]);}
Very simple, traverse all the item, according to tag to get the real index and of course order comparison, exactly the same victory ~ ~ After victory into the next level.
The code for the next pass:
public void Nextlevel () {this.removeallviews (); manimlayout = Null;mcolumn++;initbitmap (); Inititem ();}
OK, here's the end of our game, I'm going to take you to a close:
Deliberately left a step, let me level up ~ ~ I hope that everyone, regardless of the game or technology can be level up!!!
Because of space reasons, time constraints and display, do not take everyone to do, we feel that it is necessary to add their own ~ ~
SOURCE Click to download
Amount, the source forgot to upload, work on,,,,,
----------------------------------------------------------------------------------------------------------
Bo Master part of the video has been online, if you do not like boring text, please poke (first record, look forward to your support):
1, High imitation 5.2.1 main interface and message alert
2, high imitation QQ5.0 slide
Android Combat Beauty jigsaw puzzle game you can stick to the first few off