package com.bigfat.game_pintu.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.bigfat.game_pintu.R;
import com.bigfat.game_pintu.util.ImagePiece;
import com.bigfat.game_pintu.util.ImageSplitterUtil;
import com.bigfat.game_pintu.util.OnGamePintuListener;
import com.bigfat.game_pintu.util.Utils;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @author <a href="mailto:fbzhh007@gmail.com">bigfat</a>
* @since 2015/2/17
*/
public class GamePintuLayout extends RelativeLayout implements View.OnClickListener {
private static final int TIME_CHANGED = 0x110;
private static final int NEXT_LEVEL = 0x111;
/**
* 容器的宽度
*/
private int mWidth;
/**
* 默认是3x3的拼图
*/
private int mColumn = 3;
/**
* 容器的内边距
*/
private int mPadding;
/**
* 每张小图的间距(dp)
*/
private int mMargin = 3;
/**
* 图片对象
*/
private ImageView[] mPintuImgs;
/**
* 每张拼图宽度
*/
private int mItemWidth;
/**
* 游戏的大图
*/
private Bitmap mBitmap;
/**
* 游戏的拼图
*/
private List<ImagePiece> mItems;
/**
* 用于控制测量操作只进行一次
*/
private boolean mOnce;
/**
* 拼图游戏回调
*/
private OnGamePintuListener mOnGamePintuListener;
/**
* 游戏时间
*/
private int mTime;
/**
* 是否启用游戏倒计时
*/
private boolean isTimeEnabled;
/**
* 当前游戏等级
*/
private int mLevel = 1;
/**
* 游戏是否过关
*/
private boolean isGameSuccess;
/**
* 游戏是否结束
*/
private boolean isGameOver;
/**
* 游戏是否暂停
*/
private boolean isPause;
/**
* 设置拼图游戏回调接口
*/
public void setOnGamePintuListener(OnGamePintuListener onGamePintuListener) {
this.mOnGamePintuListener = onGamePintuListener;
}
/**
* 设置是否开启游戏计时
*/
public void setTimeEnabled(boolean isTimeEnabled) {
this.isTimeEnabled = isTimeEnabled;
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case TIME_CHANGED:
if (isGameSuccess || isGameOver || isPause) {
return;
}
if (mOnGamePintuListener != null) {
mOnGamePintuListener.timeChanged((int) mTime);
if (mTime == 0) {
isGameOver = true;
mOnGamePintuListener.gameOver();
return;
}
}
mTime--;
//一秒后继续更新游戏计时
mHandler.sendEmptyMessageDelayed(TIME_CHANGED, 1000);
break;
case NEXT_LEVEL:
mLevel++;
if (mOnGamePintuListener != null) {
mOnGamePintuListener.nextLevel(mLevel);
} else {
nextLevel();
}
break;
}
}
};
public GamePintuLayout(Context context) {
this(context, null);
}
public GamePintuLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GamePintuLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMargin, getResources().getDisplayMetrics());
mPadding = Utils.min(getPaddingLeft(), getPaddingRight(), getPaddingTop(), getPaddingBottom());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = Utils.min(getMeasuredWidth(), getMeasuredHeight());
if (!mOnce) {
gameStart();
mOnce = true;
}
setMeasuredDimension(mWidth, mWidth);
}
/**
* 游戏开始
*/
public void gameStart() {
isGameSuccess = false;
isGameOver = false;
removeAllViews();
mAnimLayout = null;
initBitmap();
initItem();
checkTimeEnable();
}
/**
* 游戏暂停
*/
public void pause() {
isPause = true;
}
/**
* 从暂停中恢复
*/
public void resume() {
if (isPause) {
isPause = false;
mHandler.sendEmptyMessage(TIME_CHANGED);
}
}
/**
* 检查计时设置
*/
private void checkTimeEnable() {
if (isTimeEnabled) {
countTimeBaseLevel();
mHandler.sendEmptyMessage(TIME_CHANGED);
}
}
/**
* 基于关卡等级设置游戏时间
*/
private void countTimeBaseLevel() {
mTime = (int) (Math.pow(2, mLevel - 1) * 60);
}
/**
* 切图及排序
*/
private void initBitmap() {
if (mBitmap == null) {
mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.test);
}
mItems = ImageSplitterUtil.splitImage(mBitmap, mColumn);
//图片乱序
Collections.sort(mItems, new Comparator<ImagePiece>() {
@Override
public int compare(ImagePiece lhs, ImagePiece rhs) {
return Math.random() > 0.5 ? 1 : -1;
}
});
}
/**
* 设置ImageView的宽高等属性
*/
private void initItem() {
mItemWidth = (mWidth - mPadding * 2 - mMargin * (mColumn - 1)) / mColumn;
mPintuImgs = new ImageView[mColumn * mColumn];
//设置拼图ImageView属性
for (int i = 0; i < mPintuImgs.length; i++) {
ImageView imageView = new ImageView(getContext());
imageView.setOnClickListener(this);
imageView.setImageBitmap(mItems.get(i).getBitmap());
mPintuImgs[i] = imageView;
//设置id
imageView.setId(i + 1);
//设置index,即乱序后图片真实的索引
imageView.setTag(i + "_" + mItems.get(i).getIndex());
//设置宽高及依赖关系
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(mItemWidth, mItemWidth);
//不是第一列
if (i % mColumn != 0) {
lp.leftMargin = mMargin;
lp.addRule(RelativeLayout.RIGHT_OF, mPintuImgs[i - 1].getId());
}
//不是第一行
if (i + 1 > mColumn) {
lp.topMargin = mMargin;
lp.addRule(RelativeLayout.BELOW, mPintuImgs[i - mColumn].getId());
}
//设置点击事件监听器
imageView.setOnClickListener(this);
//将ImageView添加到容器中
addView(imageView, lp);
}
}
private ImageView mFirst;
private ImageView mSecond;
@Override
public void onClick(View v) {
if (isAniming) {
return;
}
//第一张图片被点击两次
if (mFirst == v) {
mFirst.setColorFilter(null);
mFirst = null;
return;
}
if (mFirst == null) {
mFirst = (ImageView) v;
mFirst.setColorFilter(0x550000cc);
} else {
mSecond = (ImageView) v;
exchangeView();
}
}
/**
* 动画层
*/
private RelativeLayout mAnimLayout;
private boolean isAniming;
/**
* 交换选中的两张图片
*/
private void exchangeView() {
mFirst.setColorFilter(null);
//构造动画层
setUpAnimLayout();
final String firstTag = (String) mFirst.getTag();
final String secondTag = (String) mSecond.getTag();
final Bitmap firstBitmap = mItems.get(Utils.getImageIdByTag(firstTag)).getBitmap();
final Bitmap secondBitmap = mItems.get(Utils.getImageIdByTag(secondTag)).getBitmap();
//创建动画层上的ImageView
ImageView first = new ImageView(getContext());
first.setImageBitmap(mItems.get(Utils.getImageIdByTag((String) mFirst.getTag())).getBitmap());
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(mItemWidth, mItemWidth);
lp.leftMargin = mFirst.getLeft() - mPadding;
lp.topMargin = mFirst.getTop() - mPadding;
first.setLayoutParams(lp);
mAnimLayout.addView(first);
ImageView second = new ImageView(getContext());
second.setImageBitmap(mItems.get(Utils.getImageIdByTag((String) mSecond.getTag())).getBitmap());
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(mItemWidth, mItemWidth);
lp2.leftMargin = mSecond.getLeft() - mPadding;
lp2.topMargin = mSecond.getTop() - mPadding;
second.setLayoutParams(lp2);
mAnimLayout.addView(second);
//创建动画
TranslateAnimation firstAnim = new TranslateAnimation(0, mSecond.getLeft() - mFirst.getLeft(), 0, mSecond.getTop() - mFirst.getTop());
firstAnim.setDuration(300);
firstAnim.setFillAfter(true);
first.startAnimation(firstAnim);
TranslateAnimation secondAnim = new TranslateAnimation(0, mFirst.getLeft() - mSecond.getLeft(), 0, mFirst.getTop() - mSecond.getTop());
secondAnim.setDuration(300);
secondAnim.setFillAfter(true);
second.startAnimation(secondAnim);
firstAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
mFirst.setVisibility(INVISIBLE);
mSecond.setVisibility(INVISIBLE);
isAniming = true;
}
@Override
public void onAnimationEnd(Animation animation) {
mFirst.setImageBitmap(secondBitmap);
mSecond.setImageBitmap(firstBitmap);
mFirst.setTag(secondTag);
mSecond.setTag(firstTag);
mFirst.setVisibility(VISIBLE);
mSecond.setVisibility(VISIBLE);
mFirst = mSecond = null;
//移除动画层图片
mAnimLayout.removeAllViews();
//检查是否过关
checkSuccess();
isAniming = false;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
/**
* 构造动画层
*/
private void setUpAnimLayout() {
mAnimLayout = new RelativeLayout(getContext());
addView(mAnimLayout);
}
/**
* 检查是否过关
*/
private void checkSuccess() {
boolean isSuccess = true;
for (int i = 0; i < mPintuImgs.length; i++) {
String tag = (String) mPintuImgs[i].getTag();
if (i != Utils.getIndexByTag(tag)) {
isSuccess = false;
break;
}
}
if (isSuccess) {
isGameSuccess = true;
// Toast.makeText(getContext(), "isSuccess:" + isSuccess, Toast.LENGTH_SHORT).show();
mHandler.sendEmptyMessage(NEXT_LEVEL);
}
}
/**
* 下一关
*/
public void nextLevel() {
mColumn++;
gameStart();
}
}