안 드 로 이 드 미녀 퍼 즐 게임 상세 설명 실현
그림 은 여러 부분 으로 나 누 어 교환 을 클릭 하여 완전한 것 으로 만 듭 니 다.이렇게 하면 관문 도 쉽게 설계 할 수 있다.4 4;5 5;6 6;쭉 내려가다
전환 애니메이션 을 추가 하면 효과 가 좋 습 니 다.사실은 게임 은 컨트롤 을 사용자 정의 한 것 입 니 다.다음은 사용자 정의 여행 을 시작 하 겠 습 니 다.
게임 디자인
우선 우 리 는 이 게임 을 어떻게 디자인 하 는 지 분석 해 보 자.
1.우 리 는 용기 가 필요 합 니 다.이 그림 들 의 블록 을 넣 을 수 있 습 니 다.편 의 를 위해 우 리 는
RelativeLayout
협조addRule
를 사용 하여 실현 하려 고 합 니 다.2.각 그림 의 블록 을 사용 하려 고 합 니 다
ImageView
3.교환 을 클릭 하면 우 리 는 전통 적 인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
에 설 치 했 습 니 다Item
tag 에 저 장 된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)
안에 이 레이아웃 을 설치 해 주세요~~현재 효 과 는:
게임 전환 효과
초기 전환
우리 모두
Activity
에Item
감청 을 추가 한 것 을 기억 하 십 니까~지금 우 리 는 실현 이 필요 합 니 다.두 개
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 도 용기 로 얻 을 수 있 습 니 다.그러나 우리 가 실제로
Item
Item
에 만 변화 가 생 겼 을 뿐 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();
}
총결산자,여기 서 우리 가 소개 한 내용 은 기본적으로 끝 났 습 니 다.관심 이 있 는 친구 들 은 스스로 조작 할 수 있 습 니 다.그러면 여러분 들 이 학습 을 이해 하 는 데 도움 이 될 것 입 니 다.궁금 한 점 이 있 으 면 댓 글 을 달 아 교류 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.