上篇文章中對開始打地鼠遊戲的思路做了簡單的介紹,現在來具體的說一說開始打地鼠遊戲的實現,先說說佈局,用LinearLayout或TableLyout都可以。上面一行是4個TextView下面的地洞是ImageButton。遊戲中打中或沒打中地鼠都更新會對應按鈕背景圖。打中地鼠的效果圖(圖1)和沒打中的效果圖(圖2)。
遊戲中需要開啓一個線程來控制遊戲時間,更新顯示剩餘時間時,遊戲0.5s更新一次,遊戲時間爲30s,因此更新次數是遊戲時間的二倍。當遊戲時間爲0s時遊戲停止關閉遊戲界面並開啓記錄玩家信息的窗口。該線程同時產生一個隨機數(1-12)來指定地鼠出現位置,由於子線程不能更新UI,需要通過handler發送消息來更新UI。更新界面時將每一個按鈕背景都有重置爲地洞,再更新地鼠出現位置的圖片,這樣會清除由於點擊出現的錘子和上一次地鼠出現位置設置的圖片。當用戶點擊屏幕是,如果打中地鼠,效果如圖1,沒打中效果如圖2,並且如果開啓了音效,會播放不同的打擊聲音。最後在遊戲界面不可見是關閉線程。
代碼如下:
package cn.com.cyj.mouse.services;
import java.util.HashMap;
import java.util.Random;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import cn.com.cyj.mouse.R;
import cn.com.cyj.mouse.ui.BaseActivity;
import cn.com.cyj.mouse.ui.MouseStart;
/**
* 遊戲開始的界面:遊戲中有12個ImageButton,每個ImageButton背景設置成地鼠洞,遊戲中開啓一個線程控制遊戲時間
*
* @author cyj
*
*/
public class GameRun extends BaseActivity {
/**
* 線程睡眠時間
*/
public static final int THREAD_SLEEP_TIME = 500;
/**
* 遊戲時間
*/
public static final int TIME = 30;
private ImageButton one;
private ImageButton two;
private ImageButton three;
private ImageButton four;
private ImageButton five;
private ImageButton six;
private ImageButton seven;
private ImageButton eight;
private ImageButton nine;
private ImageButton ten;
private ImageButton eleven;
private ImageButton twleve;
// 顯示時間
private TextView showTime;
// 顯示分數
private TextView score;
MyClick click;
private Random random;
// 遊戲當前時間
private int time;
// 遊戲總時間
private int totalTime;
// 老鼠下一次出現位置
private int next;
// 遊戲當前分數
private int nowScore;
// 遊戲線程
private Thread t;
// 存放按鈕和next的映射
HashMap<ImageButton, Integer> battle;
HashMap<Integer, ImageButton> nextMap;
public Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
changeUI();
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gamerun);
battle = new HashMap<ImageButton, Integer>();
nextMap = new HashMap<Integer, ImageButton>();
initImageButton();
initOnClick();
initbattleMap();
initNextMap();
next = -1;
random = new Random();
totalTime = TIME;
time = 0;
nowScore = 0;
showTime.setText(TIME + "");
}
@Override
protected void onResume() {
super.onResume();
if(t == null){
// 控制遊戲時間
t = new Thread(new Runnable() {
@Override
public void run() {
try {
while (totalTime != 0) {
Thread.sleep(THREAD_SLEEP_TIME);
next = random.nextInt(12) + 1;
time++;
handler.sendEmptyMessage(1);
}
} catch (Exception e) {
e.printStackTrace();
}
if (totalTime == 0) {
Intent intent = new Intent(GameRun.this, GameOver.class);
// 該參數跳轉頁面不會觸發onUserLeaveHint()方法
intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
intent.putExtra("score", "" + nowScore);
GameRun.this.startActivity(intent);
finish();
}
}
});
}
t.start();
}
// 初始化按鈕
private void initImageButton() {
one = (ImageButton) findViewById(R.id.first);
two = (ImageButton) findViewById(R.id.second);
three = (ImageButton) findViewById(R.id.three);
four = (ImageButton) findViewById(R.id.four);
five = (ImageButton) findViewById(R.id.five);
six = (ImageButton) findViewById(R.id.six);
seven = (ImageButton) findViewById(R.id.seven);
eight = (ImageButton) findViewById(R.id.eight);
nine = (ImageButton) findViewById(R.id.nine);
ten = (ImageButton) findViewById(R.id.ten);
eleven = (ImageButton) findViewById(R.id.eleven);
twleve = (ImageButton) findViewById(R.id.twelve);
showTime = (TextView) findViewById(R.id.showtime);
score = (TextView) findViewById(R.id.score);
}
// 給按鈕添加點擊事件
private void initOnClick() {
click = new MyClick();
one.setOnClickListener(click);
two.setOnClickListener(click);
three.setOnClickListener(click);
four.setOnClickListener(click);
five.setOnClickListener(click);
six.setOnClickListener(click);
seven.setOnClickListener(click);
eight.setOnClickListener(click);
nine.setOnClickListener(click);
ten.setOnClickListener(click);
eleven.setOnClickListener(click);
twleve.setOnClickListener(click);
}
// 按鈕id和next映射關係
private void initbattleMap() {
battle.put(one, 1);
battle.put(two, 2);
battle.put(three, 3);
battle.put(four, 4);
battle.put(five, 5);
battle.put(six, 6);
battle.put(seven, 7);
battle.put(eight, 8);
battle.put(nine, 9);
battle.put(ten, 10);
battle.put(eleven, 11);
battle.put(twleve, 12);
}
// next和按鈕id的映射關係
private void initNextMap() {
nextMap.put(1, one);
nextMap.put(2, two);
nextMap.put(3, three);
nextMap.put(4, four);
nextMap.put(5, five);
nextMap.put(6, six);
nextMap.put(7, seven);
nextMap.put(8, eight);
nextMap.put(9, nine);
nextMap.put(10, ten);
nextMap.put(11, eleven);
nextMap.put(12, twleve);
}
/**
* 更新小老鼠出現位置和顯示遊戲剩餘時間
*/
private void changeUI() {
// 更新顯示剩餘時間,遊戲0.5s更新一次,因此更新次數是遊戲時間的二倍
if (time % 2 == 0) {
showTime.setText(--totalTime + "");
}
if (next == -1)
return;
// 每次出地鼠時將按鈕背景初始化
reImageButton();
// 獲得next對應的按鈕
ImageButton bt = nextMap.get(next);
// 給按鈕設置地鼠圖片
bt.setBackgroundResource(R.drawable.end);
}
// 按鈕背景初始化
private void reImageButton() {
one.setBackgroundResource(R.drawable.start);
two.setBackgroundResource(R.drawable.start);
three.setBackgroundResource(R.drawable.start);
four.setBackgroundResource(R.drawable.start);
five.setBackgroundResource(R.drawable.start);
six.setBackgroundResource(R.drawable.start);
seven.setBackgroundResource(R.drawable.start);
eight.setBackgroundResource(R.drawable.start);
nine.setBackgroundResource(R.drawable.start);
ten.setBackgroundResource(R.drawable.start);
eleven.setBackgroundResource(R.drawable.start);
twleve.setBackgroundResource(R.drawable.start);
}
/**
* 點擊事件,判斷是否打中
*
* @author cyj
*
*/
class MyClick implements OnClickListener {
@Override
public void onClick(View v) {
// 是否的分的標記
Boolean isScore = false;
// 獲取點擊按鈕對應next
int battleId = battle.get(v);
// 如果點擊按鈕爲next得分
if (battleId == next) {
// 得分爲true
isScore = true;
}
if (isScore) {
// 設置打中的圖片
v.setBackgroundResource(R.drawable.zhong);
if (MouseStart.controller.isPlay()) {
// 打中的音效
MouseStart.controller.playSound(R.raw.hathit);
}
// 加分
score.setText((nowScore += 10) + "");
} else {
// 設置沒打中的圖片
v.setBackgroundResource(R.drawable.meizhong);
if (MouseStart.controller.isPlay()) {
// 沒打中的音效
MouseStart.controller.playSound(R.raw.dismistake);
}
}
}
}
@Override
protected void onStop() {
// 停止線程
super.onStop();
if (t != null) {
t.interrupt();
t = null;
}
}
}
小技巧:記得有位大神說過switch是小白專用(我也是一個小白),在本遊戲中免不了各種判斷:在產生地鼠位置時,要通過隨機數來確定按鈕位置,例如:如果隨機數是1,則在第一個按鈕設置地鼠圖片,需要多次判斷,應該是出現隨機數1那麼直接在第一個按鈕設置;玩家點擊按鈕時,需要判斷點擊的是那個按鈕並判斷是否是有地鼠的按鈕,再設置相應的圖片。那麼應該怎麼辦呢?
答案是用HashMap來代替switch,在HashMap來映射隨機數和按鈕,更新地鼠位置時直接用隨機數來獲得按鈕設置圖片。用另一個HashMap中映射按鈕和對應的隨機數,這樣在點擊按鈕時直接獲取映射的數,該數和現在地鼠位置的隨機數比較即可判斷是否打中地鼠;這樣就完美解決了。