Android打地鼠游戏的修改和优化

最近在研究android原生的游戏,主要是打地鼠这款经典小游戏的熟悉和修改,因为直接copy的是开源的代码,不过因为年代久远,再加上要修改的符合需求,所以做了一些调整,先看界面:

1.打地鼠的实现图

这个界面是用自定义View来实现的,所以可扩展性比较强,HP是血量,总共20ms,进行倒计时操作,Grade是分数,每打中一次地鼠,则增加100分,首先,我们先看看这两个是如何绘制的:

2.HP和Grade的绘制

也就五行代码,利用Paint画笔,设置字体颜色为红色,字体大小为30sp,利用Canva的drawText()方法进行字体文本的绘制,同时GameAgrs这个类是游戏属性的封装类,里面的HP_X和HP_Y,Grade_X和Grade_Y分别对应着各自的横坐标和纵坐标。

接下来,我们来仔细讲解一下这九个老鼠窝的绘制,因为老鼠窝有九个,但是其中的每个属性都是一样的,我们先来看看其中一个鼠窝究竟有哪些元素和属性构成的:

3.每个方块的属性页方法

因为是直接拿源码直接来改的,所以这里面的倒计时有一点问题,利用的是自减而非传统的CountDownTime等倒计时的方式,所以会倒计时会出现一点问题,这个未来会做相应的修改。

得到每个方块的属性和方法之后,我们虽然可以绘制鼠窝,但是为了给老鼠一个美丽的家,所以我们设置一下背景和老鼠弹出、撤退的图片。

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(),则定义了一个弹窗,点击确定则继续开始,点击取消,则重置页面初始状态。

以上就是打地鼠的代码了,虽然不全,但是精华已经全都交代出来了,另外这个还只是最初的修改版本,未来工作中还有更多的修改,包括页面的重绘,逻辑的修改等等。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容