前面介绍了《2048》的实现,现在来说说《防御小鸟》...

【小萌伴】防御小鸟

从上图可以看出,《防御小鸟》有两种玩法,一种是利用管道将小鸟永久的挡在左边,另一种是利用管道将小鸟压死。这两种玩法与正版的《像素小鸟》有点不一样,《像素小鸟》是控制小鸟的飞行,而《防御小鸟》是控制管道的闭合;刚开始时难道比较低,但是随着小鸟不断增多,难度也是相当大的。

【小萌伴】防御小鸟

该游戏源码主要包含了一个Bird类,和一个GameView,然后还有一个SafeInt用于计算得分。里面最大的不足之处是游戏音效没有抽离出来,导致在GameView中使用了GameActivity实例调用音效播放。

Bird

Bird类包含了一些Bird属性的定义,以及Bird的移动、级别的控制;Bird还带有draw方法

/**
* 小鸟的绘制
* @param canvas
*/
public void draw(Canvas canvas){
// Paint paint=new Paint();
if (level<=upic){
canvas.drawBitmap(pic[upic], new Rect(0,0,pic[upic].getWidth(),pic[upic].getHeight()), new Rect(y-width/2,x-height/2,y+width/2,x+height/2), null);
}else{
canvas.drawBitmap(apic[upic], new Rect(0,0,apic[upic].getWidth(),apic[upic].getHeight()), new Rect(y-width/2,x-height/2,y+width/2,x+height/2), null);
}
}

GameView

GameView继承自SurfaceView类,并且实现了Callback和Runnable接口;它的主要工作是UI的绘制(包含Bird,管道,计分板,Tap,各种按钮等),事件的监听(OnTouch时间、游戏进度事件等),线程刷新(使用的SurfaceView,在子线程内调用draw方法在canvas上进行绘制);需要注意的是,绘图时使用SurfaceHolder的lockCanvas()对Canvas进行锁定。以下是游戏线程,用于刷新UI,这里控制的是1秒33帧(实际上没有33帧),能基本满足肉眼看上去无延迟:

/**
* 游戏线程
*/
public void run() {
while (flag) {
isDraw=!isDraw;
if (isDraw)myDraw();
if (isStop==false) {
long start = System.currentTimeMillis();
logic();
long end = System.currentTimeMillis();
try {
if (end - start < 30) {
Thread.sleep(30 - (end - start));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

SafeInt

SafeInt用于游戏分数的记录,包含Add和Get方法。

GameActivity

GameActivity除了用于显示GameView外,还有了几个作用,1. 分享功能;2. 得分与最高分保存与展示; 3. 游戏音效初始化及播放方法;

游戏音效这里用的是SoundPool,相比MediaPlayer而言,SoundPool适合于短音频的播放,并且多个音频能重叠,所以在游戏中更合适。

实际上Activity中只是定义了播放的方法,在GameView的逻辑中进行播放(其实应该将音效及播放抽离出来,并在相应的播放回调中调用声音播放方法,这里只是简单快速开发,没处理了。)

/**
* 初始化音效
*/
public void initMusic(){
soundp=new SoundPool(50, AudioManager.STREAM_MUSIC,100);
soundm=new HashMap();
soundm.put("slide", soundp.load(this, R.raw.slide, 1));
soundm.put("flap", soundp.load(this, R.raw.flap, 1));
soundm.put("s1", soundp.load(this, R.raw.squish1, 1));
soundm.put("s2", soundp.load(this, R.raw.squish2, 1));
soundm.put("k1", soundp.load(this, R.raw.kick1, 1));
soundm.put("k2", soundp.load(this, R.raw.kick2, 1));
}
/**
* 播放音效
*/
public void playMusic(String str){
soundp.play(soundm.get(str), 1, 1, 0, 0, 1f);
}