Android to realize the beauty puzzle game detailed _android

Source: Internet
Author: User
Tags prepare

First look at the effect:

The picture splits many, clicks the exchange to spell into a complete; such checkpoints are also easy to design, 3 3;4 4;5 5;6 6; Keep going.

Added a toggle animation, the effect is good, in fact, the game is a custom control, below we began to customize the trip.

The design of the game

First we analyze how to design this game:

1, we need a container, you can put the pieces of these pictures, in order to facilitate, we are ready to use RelativeLayout with the addRule implementation of

2, each piece of picture block, we are ready to useImageView

3, click Exchange, we are ready to use the traditional TranslationAnimation to achieve

With the initial design, feel the game so easy~

The implementation of the game layout

First of all, we are ready to implement the ability to put a picture, cut into n*n, put in a specified position; we just 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 margins can get our ImageView width and height ~ ~

Construction Method/** * Set the number of item n*n the default is 3 */private int mcolumn = 3; 
 /** * The width of the layout * * * private int mwidth; 
 /** * Layout of the padding * * private int mpadding; 
 /** * Store all the item * * Private imageview[] mgamepintuitems; 
 
 /** * The width of the item * * * private int mitemwidth; 
  
 /** * Item horizontal and longitudinal margin * * private int mmargin = 3; 
 /** * Pictures of the puzzle * * Private Bitmap Mbitmap; 
  
 /** * Storage After cutting the picture bean/private list<imagepiece> mitembitmaps; 
  
 Private Boolean once; 
 Public Gamepintulayout {This (context, NULL); 
 Public Gamepintulayout (context, AttributeSet attrs) {This (context, attrs, 0); /** * constructor to initialize * @param context * @param attrs the attrs * @param defstyle the def style * @ Author Qiu blog: www.qiuchengjia.cn time: 2016-09-12 * * Public gamepintulayout (context, AttributeSet attrs, int defst 
 
 YLE) {Super (context, attrs, Defstyle); Converts the set margin value to DP mmargin = (int) TypedValue.applydimension (Typedvalue.complex_unit_dip, Mmargin, Getresources (). Getdisplaymetrics ()); Set the inner margin of the layout, the four sides consistent, set to the minimum value in the quad margin mpadding = min (Getpaddingleft (), Getpaddingtop (), Getpaddingright (), GETPADDINGB 
 Ottom ()); }

In the construction method, we get the value of the set margin to the DP; Get the value of the layout padding ; the whole is a square, so we take the smallest of the padding four directions; as margin Item between the horizontal and vertical spacing between, as you like, you can extract the custom attributes ~ ~

Onmeasure
/**
  * Used to set the width of a custom view,
  * @param widthmeasurespec the width measure spec
  * @param Heightmeasurespec the height measure spec
  * @author Qiu Blog: www.qiuchengjia.cn time: 2016-09-12
  *
Override 
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) { 
  super.onmeasure ( Widthmeasurespec, Heightmeasurespec); 
  
  Get the game layout of edges 
  mwidth = math.min (Getmeasuredheight (), Getmeasuredwidth ()); 
 
  if (!once) { 
   initbitmap (); 
   Inititem (); 
  } 
  once = true; 
  Setmeasureddimension (Mwidth, mwidth); 
 }

onMeasureThe main thing is to get the width of the layout, and then prepare the picture, and initialize our Item , for Item setting width and height

Initbitmap Natural is to prepare the picture:

/**
 * Initialize bitmap
 * @author Qiu Blog: www.qiuchengjia.cn time: 2016-09-12 *
 *
private void Initbitmap () { 
  if (Mbitmap = = null) 
   Mbitmap = Bitmapfactory.decoderesource (Getresources (), 
     r.drawable.aa); 
 
  Mitembitmaps = Imagesplitter.split (Mbitmap, mcolumn); 
 
 Sort the picture
  Collections.sort (mitembitmaps, New comparator<imagepiece> () { 
   @Override public 
   int Compare (Imagepiece LHS, imagepiece RHS) { 
   //We use random random comparison size return
    math.random () > 0.5? 1:-1; 
   } 
  }); 
 }

If we don't have a setup here mBitmap , we'll prepare an alternate picture, and then call ImageSplitter.split to cut the picture to n * N to return one List<ImagePiece> . After the cut, we need to disrupt the order, so we called the sort method, as for the comparator, we use random random comparison size, so that we have completed our disorderly operation, praise not praise ~ ~

/** * Description: Picture Slice class * data:2016/9/11-19:53 * Blog:www.qiuchengjia.cn * Author:qiu/public class Imagesplitte R {/** * cut the picture, piece *piece * @param bitmap * @param piece * @return/public static LIST&LT;IMAGEP Iece> Split (Bitmap Bitmap, int piece) {list<imagepiece> pieces = new arraylist<imagepiece> (piece * pie 
 
  CE); 
  int width = bitmap.getwidth (); 
 
  int height = bitmap.getheight (); 
  LOG.E ("TAG", "bitmap width =" + width + ", height =" + height); 
 
  int piecewidth = math.min (width, height)/piece;  
    for (int i = 0; i < piece. i++) {for (int j = 0; J < piece; J +) {imagepiece imagepiece = new Imagepiece (); 
    Imagepiece.index = j + i * piece; 
    int xvalue = J * Piecewidth; 
     
    int yvalue = i * piecewidth; 
    Imagepiece.bitmap = Bitmap.createbitmap (Bitmap, Xvalue, Yvalue, Piecewidth, piecewidth); 
   Pieces.add (imagepiece); 
 } return pieces; } 
}
/**
 * Description: Picture Bean
 * data:2016/9/11-19:54
 * Blog:www.qiuchengjia.cn
 * Author:qiu
* public class Imagepiece 
{public 
 int index = 0; 
 Public Bitmap Bitmap = null; 
}

Always said is a based on the width of the height, and N, to cut the diagram to save the process ~ ~

ImagePieceSave the picture and index, say these two classes or I accidentally found on the Internet ~ ~

The picture is ready, now look at the production of the item has been set wide high, that isinitItems

/** * Initialize each item * @author Qiu Blog: www.qiuchengjia.cn time: 2016-09-12 * * private void Inititem () {//Get item width int 
  Childwidth = (mwidth-mpadding * 2-mmargin * (mColumn-1))/mcolumn; 
 
  Mitemwidth = Childwidth; 
  Mgamepintuitems = new Imageview[mcolumn * Mcolumn]; 
 
   Place item for (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); 
   Sets the horizontal margin, not the last column if ((i + 1)% mcolumn!= 0) {lp.rightmargin = Mmargin; //If not the first column if (i% mcolumn!= 0) {lp.addrule (relativelayout.right_of,//Mgamepintuitems[i-1].geti 
   D ()); //If it is not the first line,//Set the portrait margin, not the last line if ((i + 1) > Mcolumn) {lp.topmargin= Mmargin; 
   Lp.addrule (relativelayout.below,//Mgamepintuitems[i-mcolumn].getid ()); 
  } AddView (item, LP); } 
 }

You can see the calculation of our item width: The width of the childWidth = (mWidth - mPadding 2 - mMargin (mColumn - 1) ) / mColumn; container, excluding its inner margin, removing the spacing between the items, and then dividing by the Item number of rows to get Item the width ~ ~

Next, is the traversal generation Item , according to their location settings Rule , carefully look at the comments ~ ~

Note two points:

1, we Item set up setOnClickListener , this of course, because our game is the point item ~

2, and we have to Item set up aTag:item.setTag(i + "_" + mItemBitmaps.get(i).index);

tag is stored in the index right place, and i,i can help us mItemBitmaps find the current Item Picture:(mItemBitmaps.get(i).bitmap)

To this end, the layout of our game code is over ~ ~ ~

Then we declare 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 ">

 <game.qiu.com.beautygame.gamepintulayout
  android:id= "@+id/id_gameview"
  android:layout_width= " Fill_parent "
  android:layout_height=" fill_parent "
  android:layout_centerinparent=" true "
  Android: padding= "5DP" >
 </game.qiu.com.beautygame.GamePintuLayout>

</RelativeLayout>

ActivityInside remember to set this layout ~ ~

Now the effect is:

The switching effect of the game

Initial switch

Remember all Item The listening we've added onClick ?

Now we need to implement, click Two Item , their pictures can be exchanged ~

So, we need two member variables to store the two Item , then swap

/**
 * Records the first click of the
 imageview
/Private ImageView Mfirst; 
/**
 * Record the second click of the
 imageview
/Private ImageView Msecond; 
/**
 * Click event
 * @param view the View
 * @author Qiu Blog: www.qiuchengjia.cn time: 2016-09-12
 * 
Override public 
void OnClick (View v) { 
 /** 
  * If two clicks is the same * 
 /if (Mfirst = = v) { 
  Mfirst.setcolorfilter (null); 
  Mfirst = null; 
  return; 
 } 
 Click the first item 
 if (Mfirst = null) { 
  Mfirst = (imageview) v; 
  Mfirst.setcolorfilter (Color.parsecolor ("#55FF0000")); 
 } else//Click on the second item 
 { 
  Msecond = (imageview) v; 
  Exchangeview (); 
 } 
 

Click on the first one, by setColorFilter setting the selected effect, click Another, then we are ready to call exchangeView to Exchange pictures, of course, this method we have not written, put the first ~

If you click the same one for two times, remove the selected effect, and we'll take it as nothing happens.

Next, we will implement exchangeView :

/**
 * Exchange two item pictures 
 * @author Qiu Blog: www.qiuchengjia.cn time: 2016-09-12 *
 *
 private void Exchangeview () { 
    
  mfirst.setcolorfilter (null); 
  String Firsttag = (string) mfirst.gettag (); 
  String Secondtag = (string) msecond.gettag (); 
   
  Get indexed position in List 
  string[] Firstimageindex = Firsttag.split ("_"); 
  string[] Secondimageindex = Secondtag.split ("_"); 
   
  Mfirst.setimagebitmap (Mitembitmaps.get ( 
    parseint (secondimageindex[0))). Bitmap); 
  Msecond.setimagebitmap (Mitembitmaps.get ( 
    parseint (firstimageindex[0))). Bitmap); 
 
  Mfirst.settag (Secondtag); 
  Msecond.settag (Firsttag); 
   
  Mfirst = Msecond = null; 
 
 }

Should remember us before the setTag bar, forget, go back to see, we also said to pay attention to ~

Through getTag , get in the list is the index, and then get bitmap to Exchange settings, and finally exchange tag;

Our exchange effect has been finished, our game can be finished ~ ~

The effect is this:

We can see that we can play, as for why not refreshing the scenery, is because, it is really not see that piece on that piece, or sister intuitive ~

Everyone will spit, I rub, animation switch it, obviously not two flew over to Exchange position Mody, ni what is this?

Yes, and the program we have to pursue, the following we add animation switching effect ~ ~

Seamless animation switching

Let's talk about how to add, I am ready to use TranslationAnimation , and then two Item top,left also very container access;

But, to understand, we actually, Item just changed setImage , the item's position has not changed;

We now need to move the animation effect, such as a move to B, no problem, after the move is done, we Item have to go back, but the picture has not changed, we still need to manuallysetImage

This creates a phenomenon, animation switching effect has, but finally there will be a flash, is that we switch pictures caused;

In order to avoid the above phenomenon, to achieve the perfect switching effect, here we introduce an animated layer, specifically to do animation effect, a bit like PS layer, below see how we do;

/** * Animation Run logo bit * * Private Boolean isaniming; 
  
/** * Animation Layer * * Private relativelayout manimlayout; /** * Exchange Two item pictures * @author Qiu Blog: www.qiuchengjia.cn time: 2016-09-12 * * private void Exchangeview () {Mfirst.setcolorfi 
  Lter (NULL); 
  Setupanimlayout (); 
  Add Firstview ImageView The 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 = Mfirst.gettop ()-mpadding; 
  FIRST.SETLAYOUTPARAMS (LP); 
  Manimlayout.addview (a); 
  Add Secondview ImageView 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.getto 
  P ()-mfirst.gettop ()); 
  Anim.setduration (300); 
  Anim.setfillafter (TRUE); 
 
  First.startanimation (ANIM); 
      Translateanimation Animsecond = new Translateanimation (0, Mfirst.getleft ()-Msecond.getleft (), 0, MFirst.getTop () 
  -Msecond.gettop ()); 
  Animsecond.setduration (300); 
  Animsecond.setfillafter (TRUE); 
  Second.startanimation (Animsecond);  Add Animation listener Anim.setanimationlistener (new Animationlistener () {@Override public void Onanimationstart (Animation 
    Animation) {isaniming = true; 
    Mfirst.setvisibility (invisible); 
   Msecond.setvisibility (invisible); @Override public void Onanimationrepeat (Animation Animation) {} @Override public void Onanimat 
    Ionend (Animation Animation) {String firsttag = (string) mfirst.gettag (); String Secondtag = (String) msecond.gettag (); 
    string[] Firstparams = Firsttag.split ("_"); 
 
    string[] Secondparams = Secondtag.split ("_"); 
    Mfirst.setimagebitmap (Mitembitmaps.get (parseint (secondparams[0))). Bitmap); 
 
    Msecond.setimagebitmap (Mitembitmaps.get (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 Relativela 
   Yout (GetContext ()); 
  AddView (manimlayout); 
  } private int Getimageindexbytag (String tag) {string[] split = Tag.split ("_"); 
 
 Return Integer.parseint (split[0]); }

When we start swapping, we create an animation layer, then add two identical on this layer Item , hide the original, and Item then make the animation switch setFillAfter for true~

Animation finished, 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 The picture is set to B, the B copy removed, a display, so that the perfect fit, the user feels that the B moved past

4, B ditto

Now we have the effect:

Now satisfied with the effect of the ~ ~ in order to prevent users crazy point, onClick add a sentence inside:

@Override public 
 void OnClick (View v) 
 { 
  //If animation is being performed, mask 
  if (isaniming) return 
   ;

To this switch of our animation, has been a perfect end ~ ~

Switch, we should not judge whether the success ~ ~

The judgment of the game victory

We are in the switch to complete, proceed checkSuccess() ; The good news is we put the right order of the pictures inside the tag ~ ~

/**
 * Used to determine the success of the game
 * @author Qiu Blog: www.qiuchengjia.cn time: 2016-09-12 * *
private void checksuccess () { 
  Boolean issuccess = true; 
  for (int i = 0; i < mgamepintuitems.length i++) {imageview-I 
   = 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 Integer.parseint (split[1]); 
 

Very simple, traversing all Item , according to the tag to get the real index and of course the order comparison, complete agreement is victory ~ ~ After the victory to enter the next level

As for the next pass code:

public void Nextlevel () { 
  this.removeallviews (); 
  Manimlayout = null; 
  mcolumn++; 
  Initbitmap (); 
  Inititem (); 
 }

Summarize

OK, here we introduce the content of the basic end, interested friends can do their own hands-on, this will help you understand learning more helpful, if you have questions you can message exchange.

Related Article

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.