Android簡(jiǎn)易打地鼠

先看看基本的效果(背景圖片及老鼠圖片來(lái)源于網(wǎng)絡(luò))

未開(kāi)始時(shí)


開(kāi)始后
停止播放背景音樂(lè)
時(shí)間到時(shí)

上面貼出的這幾張就是該APP的游戲界面,下面談?wù)勔婚_(kāi)始設(shè)計(jì)的基本思路

在布局方面,整體是一個(gè)線性布局,最下方是由兩個(gè)按鈕和一個(gè)文本組成

關(guān)于上方的游戲畫(huà)面,有兩種設(shè)計(jì)思想

1.最外層采用幀布局,設(shè)置背景為有9個(gè)空洞的那張圖片,在幀布局中使用相對(duì)布局放置9個(gè)ImageView,分別放置在洞的位置。在畫(huà)面左上角,設(shè)置一個(gè)CheckBox用于開(kāi)關(guān)背景音樂(lè)

2.最外層采用幀布局,設(shè)置背景為有9個(gè)空洞的那張圖片,在幀布局中使用相對(duì)布局放置9個(gè)按鈕,分別放置在洞的位置。在畫(huà)面左上角,設(shè)置一個(gè)CheckBox用于開(kāi)關(guān)背景音樂(lè)

關(guān)于代碼,主要的實(shí)現(xiàn)在于背景音樂(lè)的控制、老鼠的彈出、下方游戲時(shí)間的控制

背景音樂(lè)控制:采用了Service的基本用法,根據(jù)用戶在游戲界面CheckBox的選中與否,分別開(kāi)啟和關(guān)閉服務(wù),在服務(wù)中使用MediaPlayer播放背景音樂(lè)

老鼠的彈出:這個(gè)與游戲畫(huà)面的不同設(shè)計(jì)有關(guān)。? 對(duì)于第1種,是采用一個(gè)數(shù)組存放9個(gè)ImageView的對(duì)象,同時(shí)在線程中每隔1s生成一次隨機(jī)數(shù)(0~8),剛好與ImageView的對(duì)象在數(shù)組中的序號(hào)對(duì)應(yīng),然后將對(duì)應(yīng)的ImageView背景設(shè)置為那張老鼠。?? 對(duì)于第2種,是制作9張老鼠與背景的合成圖分別作為背景,即每個(gè)洞分別與老鼠進(jìn)行合成,然后將這9張圖用一個(gè)數(shù)組存放起來(lái),同時(shí)在線程中每隔1s生成一次隨機(jī)數(shù)(0~8),剛好與9張合成圖在數(shù)組中的序號(hào)對(duì)應(yīng),然后將包裹9個(gè)按鈕的相對(duì)布局的背景設(shè)置為這張圖片,由于圖片的覆蓋,所以看上去老鼠像是彈出的

下方游戲時(shí)間控制:當(dāng)用戶點(diǎn)擊開(kāi)始后,開(kāi)啟線程控制總時(shí)間的線程、彈出老鼠的線程和計(jì)時(shí)線程,總時(shí)間設(shè)定為60s,控制總時(shí)間的線程即sleep共60s,時(shí)間到后關(guān)閉點(diǎn)彈老鼠的線程和計(jì)時(shí)線程,在其sleep期間,計(jì)時(shí)線程每隔1s改變一次文本顯示的內(nèi)容(從60到0)


相比上次的Android簡(jiǎn)易老虎機(jī)? ,這次也是使用線程的相關(guān)知識(shí),不同的就是添加了服務(wù)用于后臺(tái)控制音樂(lè)的播放,使用了幀布局,而且解決了上次的一個(gè)小bug,就是在點(diǎn)擊開(kāi)始游戲后(開(kāi)啟各種線程),再次重復(fù)點(diǎn)擊開(kāi)始會(huì)造成線程重復(fù)啟動(dòng),使老虎機(jī)中的轉(zhuǎn)動(dòng)絮亂,解決方法是使用一個(gè)標(biāo)識(shí)flag,初始化為true,而且只有在flag為true時(shí)點(diǎn)擊按鈕才有效果,所以當(dāng)點(diǎn)擊開(kāi)始后,會(huì)設(shè)置flag為false,同時(shí)啟動(dòng)一個(gè)線程,讓該線程sleep一定時(shí)間,在sleep結(jié)束后設(shè)置flag為true,所以在該線程sleep期間,flag一直為flase,那么點(diǎn)擊開(kāi)始按鈕是無(wú)效的

更為詳細(xì)的解釋都放在代碼的注釋中,這里貼出實(shí)現(xiàn)該游戲的主要代碼,完整代碼已上傳到GitHub?

public class GameActivity extends Activity{

private Button playGame,overGame;

private TextView times;

private Button btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9;

private LinearLayout ll_bg_show;

private CheckBox cb_sound;

private intbgAtrr[] =new int[9];//保存九張帶有老鼠的背景圖

private intbtnAtrr[] =new int[9];//保存九個(gè)洞對(duì)應(yīng)的按鈕

private MyHandler myHandler=newMyHandler();

private SumTime sumTime;

private GameTime gameTime;

private GoTime goTime;

private ClickTime clickTime;

private intt=59;

private intsumMouse=0;//彈出老鼠總個(gè)數(shù)

private intclickMouse=0;//用戶點(diǎn)中的老鼠個(gè)數(shù)

private intmouseCheckedId=0;//當(dāng)前彈出圖片在數(shù)組中的序號(hào)

private booleanflag=true;//用于限制開(kāi)始按鈕的有效點(diǎn)擊次數(shù)

@Override

protected void onCreate(BundlesavedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.game_layout);

initView();//初始化控件

initAtrr();//添加圖片id到數(shù)組bgAtrr中

initListener();//初始化監(jiān)聽(tīng)器,將監(jiān)聽(tīng)器與開(kāi)始和結(jié)束按鈕進(jìn)行綁定

judgeMusic();//播放背景音樂(lè)

}

private void judgeMusic() {

Intent intent Service=newIntent(GameActivity.this,MyMusicService.class);

if(cb_sound.isChecked()) {

stopService(intentService);

}else{

startService(intentService);

}

}

/**

* 計(jì)時(shí)器,游戲開(kāi)始,該線程sleep一分鐘,時(shí)間到后,終止彈老鼠進(jìn)程和計(jì)時(shí)進(jìn)程并彈出提示框,傳入MyHander的參數(shù)為0

*/

class SumTime extendsThread{

@Override

public voidrun() {

super.run();

try{

sleep(60000);

}catch(InterruptedExceptione) {

e.printStackTrace();

}

gameTime.isStop();//調(diào)用gameTime的isStop方法,使其停止彈出老鼠

goTime.isStop();//調(diào)用goTime的isStop方法,結(jié)束該線程

Message message=Message.obtain();

message.what=0;

myHandler.sendMessage(message);

}

}

/**

* 隨機(jī)彈出老鼠圖片,傳入到MyHander的參數(shù)為1

*/

class GameTime extends Thread{

private boolean isStoped=false;

private void isStop() {

isStoped=true;

gameTime.interrupt();

}

@Override

public voidrun() {

super.run();

while(!isStoped) {

try{

sleep(1000);

}catch(InterruptedExceptione) {

e.printStackTrace();

}

Message message=Message.obtain();//獲取Message對(duì)象

message.what=1;

myHandler.sendMessage(message);

}

}

}

/**

* 時(shí)間計(jì)數(shù),傳入到MyHander的參數(shù)為2

*/

class GoTime extends Thread{

private boolean isStoped=false;

private void isStop() {

isStoped=true;

goTime.interrupt();

}

@Override

public void run() {

super.run();

while(!isStoped) {

try{

sleep(1000);

}catch(InterruptedExceptione) {

e.printStackTrace();

}

Message message=Message.obtain();

message.what=2;

myHandler.sendMessage(message);

}

}

}

class ClickTime implements Runnable{

@Override

public voidrun() {

try{

Thread.sleep(60000);

}catch(InterruptedExceptione) {

e.printStackTrace();

}

flag=true;

}

}

/**

* 根據(jù)傳入的參數(shù)進(jìn)行處理,傳入為0則表示游戲結(jié)束,傳入為1表示開(kāi)始游戲,傳入2是倒時(shí)器開(kāi)始

*/

class MyHandler extends Handler{

@Override

public void handleMessage(Messagemsg) {

super.handleMessage(msg);

switch(msg.what) {

case0:

sumTime.interrupt();

AlertDialog.Builderdialog=newAlertDialog.Builder(GameActivity.this);

dialog.setTitle("游戲結(jié)束");

dialog.setMessage("本輪地鼠總數(shù)為: "+sumMouse+" 只\n"+

"您逮住的地鼠共:"+clickMouse+" 只\n"+

"捕獲率:"+clickMouse*100/sumMouse+"%"

);

dialog.setCancelable(false);

dialog.setPositiveButton("再試一次",newDialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterfacedialog,intwhich) {

times.setText(60+"");

t=60;

sumMouse=0;

clickMouse=0;

onRestart();

}

});

dialog.show();

break;

case1:

Random random=newRandom();

int index=random.nextInt(9);

ll_bg_show.setBackgroundResource(bgAtrr[index]);

sumMouse++;

if(btnAtrr[index] ==mouseCheckedId) {

clickMouse++;//判斷當(dāng)前老鼠所在的RadioButton的id與用戶點(diǎn)擊的是否一致,若一致則為打中地鼠

}

break;

case2:

times.setText(t+"");

t--;

break;

}

}

}

class ButtonListener implementsView.OnClickListener{

@Override

public voidonClick(Viewv) {

mouseCheckedId=v.getId();

switch(v.getId()) {

caseR.id.bt_play:

if(flag) {

sumTime=newSumTime();

sumTime.start();

gameTime=newGameTime();

gameTime.start();

goTime=newGoTime();

goTime.start();

}

flag=false;

clickTime=newClickTime();

newThread(clickTime).start();

break;

caseR.id.bt_over:

finish();

Intent intent=newIntent(GameActivity.this,MyMusicService.class);

stopService(intent);

break;

caseR.id.cb_sound:

judgeMusic();

break;

}

}

}


下面列出這次開(kāi)發(fā)中的一些小知識(shí)點(diǎn):

設(shè)置手機(jī)強(qiáng)制橫屏

在配置文件中

在LInearLayout中設(shè)置 orientation屬性為vertical時(shí),layout_gravity只能夠使用橫向的如:left, right, center_horizontal?? 設(shè)置 orientation屬性為horizontal時(shí),layout_gravity只能夠使用縱向的,如:top, bottom, center_vertical

在src中放置的是原圖,是不會(huì)被拉伸的,如果在水平或者垂直方向需要拉伸,分別使用scaleX和scaleY,參數(shù)為縮放比例

在Activity中調(diào)用onRestart方法可以使當(dāng)前Activity回到原始狀態(tài)

使用Service,需要寫(xiě)一個(gè)類繼承自Service,在需要使用服務(wù)的Activity中使用 Intent intent = new Intent(this, 定義的類.class); 使用startService(intent)開(kāi)啟服務(wù) ?,記得使用stopService來(lái)關(guān)閉服務(wù),整體操作類似Activity的跳轉(zhuǎn)

音頻文件放在raw文件夾中(可能需要自己創(chuàng)建),然后使用 MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.music) 創(chuàng)建播放器對(duì)象并指定音頻位置,然后使用mediaPlayer.setLooping(true)設(shè)置循環(huán)播放,最后使用mediaPlayer.start()開(kāi)始播放,在退出時(shí)使用mediaPlayer.release()釋放資源




最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容