안 드 로 이 드 미녀 퍼 즐 게임 상세 설명 실현

18493 단어 android퍼 즐게임.
먼저 효과 보기:

그림 은 여러 부분 으로 나 누 어 교환 을 클릭 하여 완전한 것 으로 만 듭 니 다.이렇게 하면 관문 도 쉽게 설계 할 수 있다.4 4;5 5;6 6;쭉 내려가다
전환 애니메이션 을 추가 하면 효과 가 좋 습 니 다.사실은 게임 은 컨트롤 을 사용자 정의 한 것 입 니 다.다음은 사용자 정의 여행 을 시작 하 겠 습 니 다.
게임 디자인
우선 우 리 는 이 게임 을 어떻게 디자인 하 는 지 분석 해 보 자.
1.우 리 는 용기 가 필요 합 니 다.이 그림 들 의 블록 을 넣 을 수 있 습 니 다.편 의 를 위해 우 리 는RelativeLayout협조addRule를 사용 하여 실현 하려 고 합 니 다.
2.각 그림 의 블록 을 사용 하려 고 합 니 다ImageView3.교환 을 클릭 하면 우 리 는 전통 적 인TranslationAnimation을 사용 하여 실현 하려 고 합 니 다.
초보 적 인 디자인 이 생 겼 어 요.이 게임 so easy~
게임 레이아웃 의 실현
우선,우 리 는 한 장의 그림 을 n*n 부 로 자 르 고 지 정 된 위치 에 놓 을 수 있 도록 준비 합 니 다.우 리 는 n 이라는 숫자 만 설정 한 다음 에 구조의 너비 나 높이 에 따라 그 중의 작은 값 을 n 으로 나 누 면 약간의 거 리 를 줄 이면 우리ImageView의 너비 와 높이 를 얻 을 수 있 습 니 다~~

    
/** 
  *   Item   n*n;   3 
  */ 
 private int mColumn = 3; 
 /** 
  *       
  */ 
 private int mWidth; 
 /** 
  *    padding 
  */ 
 private int mPadding; 
 /** 
  *      Item 
  */ 
 private ImageView[] mGamePintuItems; 
 /** 
  * Item    
  */ 
 private int mItemWidth; 
 
 /** 
  * Item         
  */ 
 private int mMargin = 3; 
  
 /** 
  *       
  */ 
 private Bitmap mBitmap; 
 /** 
  *          bean 
  */ 
 private List<ImagePiece> mItemBitmaps; 
  
 private boolean once; 
  
 public GamePintuLayout(Context context) { 
  this(context, null); 
 } 
 
 public GamePintuLayout(Context context, AttributeSet attrs) { 
  this(context, attrs, 0); 
 } 
 
 /**
  *     ,     
  * @param context the context
  * @param attrs the attrs
  * @param defStyle the def style
  * @author qiu   :www.qiuchengjia.cn   :2016-09-12
  */
 public GamePintuLayout(Context context, AttributeSet attrs, int defStyle) { 
  super(context, attrs, defStyle); 
 
 //    margin    dp
  mMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 
    mMargin, getResources().getDisplayMetrics()); 
  //   Layout    ,    ,             
  mPadding = min(getPaddingLeft(), getPaddingTop(), getPaddingRight(), 
    getPaddingBottom()); 
 }
구조 방법 에서 우 리 는 설 치 된margin값 을 dp 로 바 꾸 었 다.레이아웃 의padding값 획득 하기;전체적으로 정사각형 이기 때문에 우 리 는padding네 방향 중 가장 작은 값 을 취한 다.margin에 대해 서 는Item사이 의 가로 와 세로 간격 으로 마음 에 드 시 면 사용자 정의 속성 으로 추출 할 수 있 습 니 다~~

onMeasure
/**
  *           View   ,
  * @param widthMeasureSpec the width measure spec
  * @param heightMeasureSpec the height measure spec
  * @author qiu   :www.qiuchengjia.cn   :2016-09-12
  */
@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
  super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
  
  //           
  mWidth = Math.min(getMeasuredHeight(), getMeasuredWidth()); 
 
  if (!once) { 
   initBitmap(); 
   initItem(); 
  } 
  once = true; 
  setMeasuredDimension(mWidth, mWidth); 
 }
onMeasure안 에는 주로 구조의 폭 을 얻 은 다음 에 그림 의 준 비 를 하고 우리 의Item을 초기 화하 여Item너비 와 높이 를 설정 합 니 다.
initBitmap 은 자 연 스 럽 게 그림 을 준비 하 는 것 입 니 다.

/**
 *    bitmap
 * @author qiu   :www.qiuchengjia.cn   :2016-09-12
 */
private void initBitmap() { 
  if (mBitmap == null) 
   mBitmap = BitmapFactory.decodeResource(getResources(), 
     R.drawable.aa); 
 
  mItemBitmaps = ImageSplitter.split(mBitmap, mColumn); 
 
 //       
  Collections.sort(mItemBitmaps, new Comparator<ImagePiece>(){ 
   @Override 
   public int compare(ImagePiece lhs, ImagePiece rhs){ 
   //    random      
    return Math.random() > 0.5 ? 1 : -1; 
   } 
  }); 
 }
설정 되 어 있 지 않 으 면 예비 그림 을 준비 하고mBitmap그림 을 n*n 으로 자 르 고ImageSplitter.split되 돌려 줍 니 다.자 른 후에 우 리 는 순 서 를 흐 트 러 뜨 려 야 하기 때문에 우 리 는List<ImagePiece>방법 을 호출 했다.비교 기 에 대해 우 리 는sort무 작위 로 크기 를 비교 했다.그러면 우 리 는 우리 의 난 서 작업 을 완성 했다.찬 불 찬~

/**
 * Description:      
 * Data:2016/9/11-19:53
 * Blog:www.qiuchengjia.cn
 * Author: qiu
 */
public class ImageSplitter { 
 /** 
  *       , piece *piece 
  * @param bitmap 
  * @param piece 
  * @return 
  */ 
 public static List<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 (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:   bean
 * Data:2016/9/11-19:54
 * Blog:www.qiuchengjia.cn
 * Author: qiu
 */
public class ImagePiece 
{ 
 public int index = 0; 
 public Bitmap bitmap = null; 
}
전체적으로 말 하면 너비 높이 와 n 에 따라 그림 을 자 르 고 저장 하 는 과정 입 니 다~~random저 장 된 그림 과 색인,그런데 이 두 가 지 는 제 가 본의 아니 게 인터넷 에서 발 견 했 습 니 다~
그림 은 여기 서 준 비 했 습 니 다.현재 Item 의 생 성 을 보면 너비 가 설정 되 어 있 습 니 다.즉,ImagePiece

/**
 *       item
 * @author qiu   :www.qiuchengjia.cn   :2016-09-12
 */
private void initItem() { 
  //   Item    
  int childWidth = (mWidth - mPadding * 2 - mMargin * 
  (mColumn - 1)) / mColumn; 
  mItemWidth = childWidth; 
 
  mGamePintuItems = new ImageView[mColumn * mColumn]; 
  //   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); 
   //       ,       
   if ((i + 1) % mColumn != 0) { 
    lp.rightMargin = mMargin; 
   } 
   //         
   if (i % mColumn != 0) { 
    lp.addRule(RelativeLayout.RIGHT_OF,// 
      mGamePintuItems[i - 1].getId()); 
   } 
   //        ,//      ,      
   if ((i + 1) > mColumn) { 
    lp.topMargin = mMargin; 
    lp.addRule(RelativeLayout.BELOW,// 
      mGamePintuItems[i - mColumn].getId()); 
   } 
   addView(item, lp); 
  } 
 }
우리 의 아 이 템 너비 계산 을 볼 수 있 습 니 다.initItems용기 의 너비,자신의 내 변 거 리 를 제거 하고 아 이 템 간 의 거 리 를 제거 한 다음childWidth = (mWidth - mPadding 2 - mMargin (mColumn - 1) ) / mColumn;한 줄 의 개 수 를 나 누 면Item의 폭 을 얻 을 수 있 습 니 다.
다음은 생 성Item을 옮 겨 다 니 며 위치 설정Item에 따라 주석 을 자세히 보 세 요~~
두 가지 주의:
1.우 리 는Rule을 위해Item설 치 했 습 니 다.이것 은 물론 입 니 다.왜냐하면 우리 의 게임 은 바로 아 이 템 을 시 키 는 것 이기 때 문 입 니까?
2.그리고 저희 가setOnClickListener에 설 치 했 습 니 다Itemtag 에 저 장 된Tag:item.setTag(i + "_" + mItemBitmaps.get(i).index);,즉 정확 한 위치 입 니 다.그리고 i,i 는 우리 가index에서 현재mItemBitmaps의 그림 을 찾 는 데 도움 을 줄 수 있다.Item이제 우리 게임 의 레이아웃 코드 가 끝 났 습 니 다~~
그리고 레이아웃 파일 에 다음 과 같이 설명 합 니 다.

<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>
(mItemBitmaps.get(i).bitmap)안에 이 레이아웃 을 설치 해 주세요~~
현재 효 과 는:

게임 전환 효과
초기 전환
우리 모두ActivityItem감청 을 추가 한 것 을 기억 하 십 니까~
지금 우 리 는 실현 이 필요 합 니 다.두 개onClick를 클릭 하면 그들의 그림 이 교환 할 수 있 습 니 다~
그러면 우 리 는 이 두 개Item를 저장 한 다음 에 교환 하 는 두 멤버 변수 가 필요 하 다.

/**
 *         ImageView
 */
private ImageView mFirst; 
/**
 *         ImageView
 */
private ImageView mSecond; 
/**
 *     
 * @param view the view
 * @author qiu   :www.qiuchengjia.cn   :2016-09-12
 */ 
@Override 
public void onClick(View v) { 
 /** 
  *            
  */ 
 if (mFirst == v) { 
  mFirst.setColorFilter(null); 
  mFirst = null; 
  return; 
 } 
 //     Item 
 if (mFirst == null) { 
  mFirst = (ImageView) v; 
  mFirst.setColorFilter(Color.parseColor("#55FF0000")); 
 } else//     Item 
 { 
  mSecond = (ImageView) v; 
  exchangeView(); 
 } 
 
}
첫 번 째 를 클릭 하고Item설정 을 통 해 선택 효 과 를 설정 하고 다른 것 을 다시 클릭 하면 우 리 는setColorFilter을 호출 하여 그림 을 교환 할 준 비 를 합 니 다.물론 이 방법 은 아직 쓰 지 않 았 습 니 다.먼저 놓 으 세 요~
같은 것 을 두 번 클릭 하면 선택 효 과 를 제거 하고 아무 일 도 없 었 던 것 으로 생각 합 니 다.
다음은 우리 가 실현 할 것 이다exchangeView.

/**
 *     Item   
 * @author qiu   :www.qiuchengjia.cn   :2016-09-12
 */
 private void exchangeView() { 
    
  mFirst.setColorFilter(null); 
  String firstTag = (String) mFirst.getTag(); 
  String secondTag = (String) mSecond.getTag(); 
   
  //   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; 
 
 }
우리 전exchangeView기억 하 시 겠 죠?까 먹 었 어 요.돌아 가 봐 요.주의 하 라 고 했 어 요~setTag을 통 해 List 에서 색인 을 받 은 다음getTag교환 설정 을 받 고 마지막 으로 tag 를 교환 합 니 다.
이제 우리 의 교환 효과 가 끝 났 습 니 다.우리 의 게임 은 끝 났 습 니 다~~
효 과 는 다음 과 같다.

우 리 는 이미 놀 수 있 는 것 을 볼 수 있 습 니 다.왜 상쾌 한 풍경 도 를 사용 하지 않 는 지 에 대해 서 는 그것 이 저것 인지,아니면 여동생 이 직관 적 인지 알 수 없 기 때 문 입 니 다.
여러분 은 분명히 토 할 것 입 니 다.제 가 닦 을 게 요.애니메이션 이 바 뀌 었 어 요.분명히 두 명 이 날 아가 서 위 치 를 바 꾸 지 않 았 어 요?니 마 이게 뭐야?
하 긴,프로그램 에 대한 추구 가 있어 야 합 니 다.애니메이션 전환 효 과 를 추가 하 겠 습 니 다~~
틈새 없 는 애니메이션 전환
우 리 는 먼저 어떻게 추가 하 는 지 에 대해 이야기 합 니 다.나 는bitmap을 사용 하려 고 합 니 다.그리고 두 개TranslationAnimation의 top,left 도 용기 로 얻 을 수 있 습 니 다.
그러나 우리 가 실제로ItemItem에 만 변화 가 생 겼 을 뿐 Item 의 위 치 는 변 하지 않 았 다 는 것 을 알 아야 한다.
우 리 는 지금 애니메이션 이동 효과 가 필요 하 다.예 를 들 어 A 가 B 로 이동 하 는 것 은 문제 가 없다.이동 이 완 료 된 후에setImage돌아 가 야 한다.그러나 그림 은 변화 가 없 기 때문에 우 리 는 수 동Item이 필요 하 다.
이렇게 해서 하나의 현상 을 초래 했다.애니메이션 전환 효과 가 있 지만 마지막 에 반 짝 이 는 것 은 우리 가 그림 을 전환 해서 생 긴 것 이다.
상기 현상 을 피하 기 위해 전환 효 과 를 완벽 하 게 할 수 있 습 니 다.여기 서 우 리 는 애니메이션 그래 픽 을 도입 하여 애니메이션 효 과 를 전문 적 으로 만 들 고 ps 와 유사 한 그래 픽 을 만 듭 니 다.다음은 우리 가 어떻게 하 는 지 보 겠 습 니 다.

/** 
 *          
 */ 
private boolean isAniming; 
/** 
 *     
 */ 
private RelativeLayout mAnimLayout; 
  
/**
 *     Item  
 * @author qiu   :www.qiuchengjia.cn   :2016-09-12
 */
private void exchangeView(){ 
  mFirst.setColorFilter(null); 
  setUpAnimLayout(); 
  //   FirstView 
  ImageView 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 = mFirst.getTop() - mPadding; 
  first.setLayoutParams(lp); 
  mAnimLayout.addView(first); 
  //   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); 
 
  //      
  TranslateAnimation anim = new TranslateAnimation(0, mSecond.getLeft() 
    - mFirst.getLeft(), 0, mSecond.getTop() - 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); 
  //        
  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 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; 
   } 
  }); 
 
 } 
 
 /** 
  *       
  */ 
 private void setUpAnimLayout(){ 
  if (mAnimLayout == null){ 
   mAnimLayout = new RelativeLayout(getContext()); 
   addView(mAnimLayout); 
  } 
 
 } 
  
 private int getImageIndexByTag(String tag){ 
  String[] split = tag.split("_"); 
  return Integer.parseInt(split[0]); 
 
 }
교환 을 시작 할 때 우 리 는 애니메이션 층 을 만 든 다음 에 이 층 에 똑 같은 두 개setImage를 추가 하여 원래 의Item를 숨 긴 다음 에 애니메이션 전환 을 마음껏 합 니 다.Item는 true 입 니 다~
애니메이션 이 끝 났 습 니 다.우 리 는 아 이 템 의 그림 을 몰래 바 꾸 어 직접 보 여 주 었 습 니 다.이렇게 하면 완벽 하 게 전환 된다.
대략적인 과정:
    1、A,B 숨 기기
    2.A 던 전 애니메이션 이 B 의 위치 로 이동;B 던 전이 A 의 위치 로 이동
    3.A 는 그림 을 B 로 설정 하고 B 던 전 을 제거 합 니 다.A 는 완벽 하 게 일치 합 니 다.사용 자 는 B 가 이동 한 것 같 습 니 다.
    4.B 동상
현재 우리 의 효과:

이제 효과 가 만 족 스 럽 습 니 다~~사용자 의 광 점 을 방지 하기 위해setFillAfter에 한 마디 를 추가 합 니 다:

@Override 
 public void onClick(View v) 
 { 
  //         ,    
  if (isAniming) 
   return;
이제 우리 애니메이션 의 전환 은 완벽 하 게 끝 났 습 니 다~~
전환 할 때,우 리 는 성공 여 부 를 판단 해 야 합 니까?
게임 승리 의 판단
우 리 는 전환 이 완료 되 었 습 니 다.진행onClick;의 판단;자,저희 가 그림 의 정확 한 순 서 를 tag 에 저장 해 드 리 도록 하 겠 습 니 다.

/**
 *           
 * @author qiu   :www.qiuchengjia.cn   :2016-09-12
 */
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(); 
  } 
 } 
 
 /** 
  *           
  * @param tag 
  * @return 
  */ 
 private int getIndexByTag(String tag){ 
  String[] split = tag.split("_"); 
  return Integer.parseInt(split[1]); 
 }
간단 합 니 다.모든 것 을 옮 겨 다 니 며checkSuccess()태그 에 따라 진정한 색인 을 얻 을 수 있 습 니 다.물론 순서 와 비교 하면 완전히 일치 하면 승리 합 니 다~승리 후 다음 관문 에 들 어 갑 니 다.
다음 관문 의 코드:

public void nextLevel(){ 
  this.removeAllViews(); 
  mAnimLayout = null; 
  mColumn++; 
  initBitmap(); 
  initItem(); 
 }
총결산
자,여기 서 우리 가 소개 한 내용 은 기본적으로 끝 났 습 니 다.관심 이 있 는 친구 들 은 스스로 조작 할 수 있 습 니 다.그러면 여러분 들 이 학습 을 이해 하 는 데 도움 이 될 것 입 니 다.궁금 한 점 이 있 으 면 댓 글 을 달 아 교류 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기