Android打地鼠遊戲的修改和優化

dsxdsxdsx0發表於2017-12-19

最近在研究android原生的遊戲,主要是打地鼠這款經典小遊戲的熟悉和修改,因為直接copy的是開源的程式碼,不過因為年代久遠,再加上要修改的符合需求,所以做了一些調整,先看介面:

Android打地鼠遊戲的修改和優化
1.打地鼠的實現圖

這個介面是用自定義View來實現的,所以可擴充套件性比較強,HP是血量,總共20ms,進行倒數計時操作,Grade是分數,每打中一次地鼠,則增加100分,首先,我們先看看這兩個是如何繪製的:

Android打地鼠遊戲的修改和優化
2.HP和Grade的繪製

也就五行程式碼,利用Paint畫筆,設定字型顏色為紅色,字型大小為30sp,利用Canva的drawText()方法進行字型文字的繪製,同時GameAgrs這個類是遊戲屬性的封裝類,裡面的HP_X和HP_Y,Grade_X和Grade_Y分別對應著各自的橫座標和縱座標。

接下來,我們來仔細講解一下這九個老鼠窩的繪製,因為老鼠窩有九個,但是其中的每個屬性都是一樣的,我們先來看看其中一個鼠窩究竟有哪些元素和屬性構成的:

Android打地鼠遊戲的修改和優化
Android打地鼠遊戲的修改和優化
3.每個方塊的屬性頁方法

因為是直接拿原始碼直接來改的,所以這裡面的倒數計時有一點問題,利用的是自減而非傳統的CountDownTime等倒數計時的方式,所以會倒數計時會出現一點問題,這個未來會做相應的修改。

得到每個方塊的屬性和方法之後,我們雖然可以繪製鼠窩,但是為了給老鼠一個美麗的家,所以我們設定一下背景和老鼠彈出、撤退的圖片。

Android打地鼠遊戲的修改和優化
Android打地鼠遊戲的修改和優化
Android打地鼠遊戲的修改和優化
Android打地鼠遊戲的修改和優化
4.鼠窩背景和老鼠的三個狀態的設定

利用Map儲存老鼠的三個狀態,暴露出一個getBitmap的方法讓外界進行呼叫,獲取鼠窩的背景和老鼠的三個狀態。

到目前為止,我們完成了單個鼠窩的屬性,背景和老鼠的繪製,接下來我們需要對九個鼠窩進行繪製,由於程式碼太多,就不截圖了,直接看程式碼

public classGameViewextendsView {

public static intspeed=100;//重新整理速度

private static final intsHeight=298;

private booleanisCancel=false;

publicGameView(Context context) {

     super(context);

     initView(context);

     GameView.this.post(updatePaint);//重新整理畫面執行緒

      GameView.this.postDelayed(setMouse,1000);//增加地鼠的執行緒,1s後執行

}

publicGameView(Context context,@NullableAttributeSet attrs) {

     super(context,attrs);

     initView(context);

    GameView.this.post(updatePaint);//重新整理畫面執行緒

    GameView.this.postDelayed(setMouse,1000);//增加地鼠的執行緒,1s後執行

    Log.i("GameViewThread:",Thread.currentThread() +"");

}

publicGameView(Context context,@NullableAttributeSet attrs, intdefStyleAttr) {

     super(context,attrs,defStyleAttr);

    initView(context);

    GameView.this.post(updatePaint);//重新整理畫面執行緒

   GameView.this.postDelayed(setMouse,1000);//增加地鼠的執行緒,1s後執行

}

public static voidinitView(Context context){

     DisplayMetrics dMetrics =newDisplayMetrics();

     //獲取螢幕解析度

     dMetrics = context.getResources().getDisplayMetrics();

     GameAgrs.InitArgs(dMetrics);

    MainMapManager.Init(context);

    VolumsPlayer.init(context);

}

intstart_X= GameAgrs.start_X;//開始畫方塊的X座標

intstart_Y= GameAgrs.start_Y;//開始畫方塊的Y座標

privateRandomrandom=newRandom();//定義一個隨機函式

//初始化每塊方塊的資訊

privateListmainList=newArrayList(GameAgrs.Total_Count);

{

     for(inti =0;i < GameAgrs.Total_Count;i++) {

        mainList.add(newEpicture());

    }

}

RunnableupdatePaint=newRunnable() {

@Override

public voidrun() {

        GameView.this.invalidate();

       GameView.this.postDelayed(this,speed);//每100ms重新整理一次

}

};

Runnable setMouse=new  Runnable() {

@Override

public void run() {

       LinkedList  tempList =new  LinkedList();

      for(inti =0;i

           Epicture epicture =mainList.get(i);

           if(epicture.getCurrenty() == GameAgrs.Hole_Empty) {

          tempList.add(epicture);

}

}

inttempSize = tempList.size();

if(tempSize ==1) {

tempList.poll().toShow();

}else if(tempSize >1) {

//隨機出一個或者兩個地鼠

for(inti =0;i

tempList.remove(random.nextInt(tempList.size())).toShow();

}

GameView.this.invalidate();

}

GameView.this.postDelayed(this,800- GameAgrs.Grade/20);

}

};

private void  drawMessage(Canvas canvas) {

Paint paint =new  Paint();

paint.setColor(Color.RED);

paint.setTextSize(GameAgrs.text_size);

canvas.drawText("HP:"+ GameAgrs.HP,GameAgrs.HP_X,GameAgrs.HP_Y,paint);

canvas.drawText("\nGrade:  "+ GameAgrs.Grade,GameAgrs.Grade_X,GameAgrs.Grade_Y,paint);

}

//遊戲結束處理

private void   doGameOver() {

AlertDialog.Builder builder =new  AlertDialog.Builder(getContext());

if(GameAgrs.Grade<2500)

builder.setTitle("繼續努力O(∩_∩)O");

else if(GameAgrs.Grade<3500)

builder.setTitle("那你很棒棒呦(。^▽^)");

else

builder.setTitle("哇!你墜棒(๑•̀ㅂ•́)و✧");

builder.setMessage("得分:"+ GameAgrs.Grade+",是否重新開始遊戲?");

builder.setPositiveButton("確定", newDialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, intwhich) {

GameAgrs.Reset();//使用者資訊重置

isCancel=false;

initView(getContext());

GameView.this.post(updatePaint);//重新整理畫面執行緒

GameView.this.postDelayed(setMouse,1000);

}

});

builder.setNegativeButton("取消", newDialogInterface.OnClickListener() {

@Override

public voidonClick(DialogInterface dialog, intwhich) {

isCancel=true;

GameAgrs.Reset();//使用者資訊重置

initView(getContext());

GameView.this.invalidate();

}

});

builder.setCancelable(false);

AlertDialog dialog = builder.create();

dialog.show();

}

@Override

protected void  onMeasure(intwidthMeasureSpec, intheightMeasureSpec) {

super.onMeasure(widthMeasureSpec,heightMeasureSpec);

setMeasuredDimension(ViewGroup.LayoutParams.MATCH_PARENT,sHeight);

}

@Override

protected void  onDraw(Canvas canvas) {

super.onDraw(canvas);

if(GameAgrs.HP<=0) {

getHandler().removeCallbacks(updatePaint);

getHandler().removeCallbacks(setMouse);

doGameOver();

return;

}

canvas.drawColor(Color.WHITE);//將背景設定為白色

drawMessage(canvas);//顯示使用者資訊

if(isCancel) {

for(inti =0;i

Epicture epicture =mainList.get(i);

intx = i % GameAgrs.Colums_Count;//獲得所在列

inty = i / GameAgrs.Colums_Count;//獲得所在行

canvas.drawBitmap(MainMapManager.getBitmap(epicture.getEmpty()),

start_X+ x * GameAgrs.EpicSize,start_Y+ y

* GameAgrs.EpicSize, null);

}

return;

}

for(inti =0;i

Epicture epicture =mainList.get(i);

intx = i % GameAgrs.Colums_Count;//獲得所在列

inty = i / GameAgrs.Colums_Count;//獲得所在行

canvas.drawBitmap(MainMapManager.getBitmap(epicture.getCurrenty()),

start_X+ x * GameAgrs.EpicSize,start_Y+ y

* GameAgrs.EpicSize, null);

epicture.toNext();//進入下一個狀態

}

}

//觸控事件

@Override

public boolean  onTouchEvent(MotionEvent event) {

if(event.getAction() != MotionEvent.ACTION_DOWN) {

return true;

}

floatx = event.getX();

floaty = event.getY();

intX = (int) ((x -start_X) / GameAgrs.EpicSize);

intY = (int) ((y -start_Y) / GameAgrs.EpicSize);

if(X <0|| Y <0|| X >=3|| Y >=4) {//如果打擊不在方塊範圍內則不響應

//點選外圍的時候,則開始遊戲

startGame();

return true;

}

intnum = Y * GameAgrs.Colums_Count+ X;

Log.i("game-----------",num +"");

if(num <9){//暫時先解決陣列出界的問題

Epicture epicture =mainList.get(num);

epicture.beHited();

}

return true;

}

private void  startGame() {

GameAgrs.Reset();//使用者資訊重置

initView(getContext());

isCancel=false;

GameView.this.post(updatePaint);//重新整理畫面執行緒

GameView.this.postDelayed(setMouse,1000);

}

}

程式碼不長,但是有幾個方法,首先定義了updatePaint和setMouse的兩個runnable,分別用來更新UI介面和老鼠動作,onDraw()方法用來繪製九個鼠窩和背景和老鼠的動作狀態,onTouchEvent主要用來處理點選事件,具體的可以看看程式碼,都有註釋,並不難理解,doGameOver(),則定義了一個彈窗,點選確定則繼續開始,點選取消,則重置頁面初始狀態。

以上就是打地鼠的程式碼了,雖然不全,但是精華已經全都交代出來了,另外這個還只是最初的修改版本,未來工作中還有更多的修改,包括頁面的重繪,邏輯的修改等等。

相關文章