1. 程式人生 > >Android拼圖遊戲開發全紀錄5

Android拼圖遊戲開發全紀錄5

今天我們終於可以把這個專案給結束掉啦,有了前幾天的準備,相信最後一天還是比較輕鬆的,國際慣例:


最後要完成的就是我們的主要功能--拼圖介面。

佈局比較簡單,在前幾天就已經做好了,現在我們要做的是以下幾件事情:

1、計時記步:這個是遊戲基本都有的功能,其實也比較簡單,記錄成功移動的步數、顯示一個計時器就行了。

2、處理圖片,調整為合適的大小比例:這個方法在前幾天已經實現了

3、點選GridView後移動圖片:是否能移動的方法已經在前幾天實現了

4、判斷是否拼圖完成:唉,也已經實現了

5、點選原圖按鈕:顯示原圖:只要顯示一個ImageView就可以了

6、點選重置按鈕:將傳進來的這張圖片重新處理一遍流程

基本思路寫完了,看來很複雜的事情,是不是梳理下就覺得很簡單了,很多準備工作做好了,會讓我們的思路變的更清晰。

package com.xys.xpuzzle.activity;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

import com.xys.xpuzzle.R;
import com.xys.xpuzzle.adapter.GridItemsAdapter;
import com.xys.xpuzzle.bean.ItemBean;
import com.xys.xpuzzle.util.GameUtil;
import com.xys.xpuzzle.util.ImagesUtil;
import com.xys.xpuzzle.util.ScreenUtil;

/**
 * 拼圖邏輯主介面:面板顯示
 * 
 * @author xys
 * 
 */
public class PuzzleMain extends Activity implements OnClickListener {

    // 選擇的圖片
    private Bitmap picSelected;
    // 拼圖完成時顯示的最後一個圖片
    public static Bitmap lastBitmap;
    // PuzzlePanel
    private GridView gv_puzzle_main_detail;
    private int resId;
    private String picPath;
    private ImageView imageView;
    // Button
    private Button btnBack;
    private Button btnImage;
    private Button btnRestart;
    // 顯示步數
    private TextView tv_puzzle_main_counts;
    // 計時器
    private TextView tv_Timer;
    // 切圖後的圖片
    private List<Bitmap> bitmapItemLists = new ArrayList<Bitmap>();
    // GridView介面卡
    private GridItemsAdapter adapter;
    // 設定為N*N顯示
    public static int type = 2;
    // Flag 是否已顯示原圖
    private boolean isShowImg;
    // 步數顯示
    public static int countIndex = 0;
    // 計時顯示
    public static int timerIndex = 0;
    // 計時器類
    private Timer timer;

    /**
     * UI更新Handler
     */
    private Handler handler = new Handler() {

	@Override
	public void handleMessage(Message msg) {
	    switch (msg.what) {
	    case 1:
		// 更新計時器
		timerIndex++;
		tv_Timer.setText("" + timerIndex);
		break;
	    default:
		break;
	    }
	}
    };

    /**
     * 計時器執行緒
     */
    private TimerTask timerTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.xpuzzle_puzzle_detail_main);
	// 獲取選擇的圖片
	Bitmap picSelectedTemp;
	// 選擇預設圖片還是自定義圖片
	resId = getIntent().getExtras().getInt("picSelectedID");
	picPath = getIntent().getExtras().getString("picPath");
	if (resId != 0) {
	    picSelectedTemp = BitmapFactory.decodeResource(getResources(), resId);
	} else {
	    picSelectedTemp = BitmapFactory.decodeFile(picPath);
	}
	type = getIntent().getExtras().getInt("type", 2);
	// 對圖片處理
	handlerImage(picSelectedTemp);
	// 初始化Views
	initViews();
	// 生成遊戲資料
	generateGame();
	// GridView點選事件
	gv_puzzle_main_detail.setOnItemClickListener(new OnItemClickListener() {

	    @Override
	    public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {
		// 判斷是否可移動
		if (GameUtil.isMoveable(position)) {
		    // 交換點選Item與空格的位置
		    GameUtil.swapItems(GameUtil.itemBeans.get(position), GameUtil.blankItemBean);
		    // 重新獲取圖片
		    recreateData();
		    // 通知GridView更改UI
		    adapter.notifyDataSetChanged();
		    // 更新步數
		    countIndex++;
		    tv_puzzle_main_counts.setText("" + countIndex);
		    // 判斷是否成功
		    if (GameUtil.isSuccess()) {
			// 將最後一張圖顯示完整
			recreateData();
			bitmapItemLists.remove(type * type - 1);
			bitmapItemLists.add(lastBitmap);
			// 通知GridView更改UI
			adapter.notifyDataSetChanged();
			Toast.makeText(PuzzleMain.this, "拼圖成功!", Toast.LENGTH_LONG).show();
			gv_puzzle_main_detail.setEnabled(false);
			timer.cancel();
			timerTask.cancel();
		    }
		}
	    }
	});
	// 返回按鈕點選事件
	btnBack.setOnClickListener(this);
	// 顯示原圖按鈕點選事件
	btnImage.setOnClickListener(this);
	// 重置按鈕點選事件
	btnRestart.setOnClickListener(this);
    }

    /**
     * Button點選事件
     */
    @Override
    public void onClick(View v) {
	switch (v.getId()) {
	// 返回按鈕點選事件
	case R.id.btn_puzzle_main_back:
	    PuzzleMain.this.finish();
	    break;
	// 顯示原圖按鈕點選事件
	case R.id.btn_puzzle_main_img:
	    Animation animShow = AnimationUtils.loadAnimation(PuzzleMain.this, R.anim.image_show_anim);
	    Animation animHide = AnimationUtils.loadAnimation(PuzzleMain.this, R.anim.image_hide_anim);
	    if (isShowImg) {
		imageView.startAnimation(animHide);
		imageView.setVisibility(View.GONE);
		isShowImg = false;
	    } else {
		imageView.startAnimation(animShow);
		imageView.setVisibility(View.VISIBLE);
		isShowImg = true;
	    }
	    break;
	// 重置按鈕點選事件
	case R.id.btn_puzzle_main_restart:
	    cleanConfig();
	    generateGame();
	    recreateData();
	    // 通知GridView更改UI
	    tv_puzzle_main_counts.setText("" + countIndex);
	    adapter.notifyDataSetChanged();
	    gv_puzzle_main_detail.setEnabled(true);
	    break;
	default:
	    break;
	}
    }

    /**
     * 生成遊戲資料
     */
    private void generateGame() {
	// 切圖 獲取初始拼圖資料 正常順序
	new ImagesUtil().createInitBitmaps(type, picSelected, PuzzleMain.this);
	// 生成隨機資料
	GameUtil.getPuzzleGenerator();
	// 獲取Bitmap集合
	for (ItemBean temp : GameUtil.itemBeans) {
	    bitmapItemLists.add(temp.getBitmap());
	}

	// 資料介面卡
	adapter = new GridItemsAdapter(this, bitmapItemLists);
	gv_puzzle_main_detail.setAdapter(adapter);

	// 啟用計時器
	timer = new Timer(true);
	// 計時器執行緒
	timerTask = new TimerTask() {

	    @Override
	    public void run() {
		Message msg = new Message();
		msg.what = 1;
		handler.sendMessage(msg);
	    }
	};
	// 每1000ms執行 延遲0s
	timer.schedule(timerTask, 0, 1000);
    }

    /**
     * 新增顯示原圖的View
     */
    private void addImgView() {
	RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.rl_puzzle_main_main_layout);
	imageView = new ImageView(PuzzleMain.this);
	imageView.setImageBitmap(picSelected);
	int x = (int) (picSelected.getWidth() * 0.9F);
	int y = (int) (picSelected.getHeight() * 0.9F);
	LayoutParams params = new LayoutParams(x, y);
	params.addRule(RelativeLayout.CENTER_IN_PARENT);
	imageView.setLayoutParams(params);
	relativeLayout.addView(imageView);
	imageView.setVisibility(View.GONE);
    }

    /**
     * 返回時呼叫
     */
    @Override
    protected void onStop() {
	super.onStop();
	// 清空相關引數設定
	cleanConfig();
	this.finish();
    }

    /**
     * 清空相關引數設定
     */
    private void cleanConfig() {
	// 清空相關引數設定
	GameUtil.itemBeans.clear();
	// 停止計時器
	timer.cancel();
	timerTask.cancel();
	countIndex = 0;
	timerIndex = 0;
	// 清除拍攝的照片
	if (picPath != null) {
	    // 刪除照片
	    File file = new File(MainActivity.TEMP_IMAGE_PATH);
	    if (file.exists()) {
		file.delete();
	    }
	}
    }

    /**
     * 重新獲取圖片
     */
    private void recreateData() {
	bitmapItemLists.clear();
	for (ItemBean temp : GameUtil.itemBeans) {
	    bitmapItemLists.add(temp.getBitmap());
	}
    }

    /**
     * 對圖片處理 自適應大小
     * 
     * @param bitmap
     */
    private void handlerImage(Bitmap bitmap) {
	// 將圖片放大到固定尺寸
	int screenWidth = ScreenUtil.getScreenSize(this).widthPixels;
	int screenHeigt = ScreenUtil.getScreenSize(this).heightPixels;
	picSelected = new ImagesUtil().resizeBitmap(screenWidth * 0.8f, screenHeigt * 0.6f, bitmap);
    }

    /**
     * 初始化Views
     */
    private void initViews() {
	// Button
	btnBack = (Button) findViewById(R.id.btn_puzzle_main_back);
	btnImage = (Button) findViewById(R.id.btn_puzzle_main_img);
	btnRestart = (Button) findViewById(R.id.btn_puzzle_main_restart);
	// Flag 是否已顯示原圖
	isShowImg = false;

	// GV
	gv_puzzle_main_detail = (GridView) findViewById(R.id.gv_puzzle_main_detail);
	// 設定為N*N顯示
	gv_puzzle_main_detail.setNumColumns(type);
	LayoutParams gridParams = new RelativeLayout.LayoutParams(picSelected.getWidth(), picSelected.getHeight());
	// 水平居中
	gridParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
	// 其他格式屬性
	gridParams.addRule(RelativeLayout.BELOW, R.id.ll_puzzle_main_spinner);
	// Grid顯示
	gv_puzzle_main_detail.setLayoutParams(gridParams);
	gv_puzzle_main_detail.setHorizontalSpacing(0);
	gv_puzzle_main_detail.setVerticalSpacing(0);

	// TV步數
	tv_puzzle_main_counts = (TextView) findViewById(R.id.tv_puzzle_main_counts);
	tv_puzzle_main_counts.setText("" + countIndex);
	// TV計時器
	tv_Timer = (TextView) findViewById(R.id.tv_puzzle_main_time);
	tv_Timer.setText("0秒");

	// 新增顯示原圖的View
	addImgView();
    }
}

自認為註釋、程式碼風格還是不錯的,希望大家喜歡。

PS:需要原始碼的朋友請留言,其實根據這個思路自己去實現下,對自己是有很大提高的,如果能優化我的程式碼,那就更好了,可以一起學習交流下。