一. 整体实现思路
- 飞机是一个对象,这个对象的属性包括血量、x,y轴,图片
- 飞机在飞行中会发射子弹,所以飞机应该对应着一个子弹的线程
- 因为子弹飞行过程中,以及飞机飞行过程中都会碰到障碍物(子弹、敌机),所以在碰撞的一瞬间应该会有一个线程释放出碰撞效果
- 在监听屏幕触摸事件等方面运用onTouchEvent方法
二. 如何绘制滚动循环的背景图片
铺两张同样的背景图,依次向下滚动。当第一张出现的背景图的y轴坐标大于等于屏幕底部的y轴坐标时,立刻移动到第二张图片的顶部,同样的,当第二张背景图的y轴坐标大于等于屏幕底部的y轴坐标时,立刻移动到第一张图片的顶部,在视觉效果上形成循环。
public void logic() {
y1+=10;
y2+=10;
if (y1>=MySurfaceView.height){
y1=y2-bitmap.getHeight();//移动到第二张图片的顶部
}
if (y2>=MySurfaceView.height){
y2=y1-bitmap.getHeight();
}
}
三. 如何绘制飞机
在绘制飞机的时候记得把血量带上
private Bitmap bitmap;
private Bitmap bitmapHp;
private int x,y;
private int width,height;
private boolean noCollision;
private int noCollisionCount;
private int hp =3;
public Myplane(Bitmap bitmap, Bitmap bitmapHp){
this.bitmap = bitmap;
this.bitmapHp = bitmapHp;
x = MySurfaceView.width/2-bitmap.getWidth()/2;
y = MySurfaceView.height-bitmap.getHeight();
width = bitmap.getWidth();
height = bitmap.getHeight();
}
另外还要记得裁剪飞机
public void myPlane (Canvas canvas,Paint paint){
if (noCollsion){
count++;
if (count%8==0){
canvas.drawBitmap(bitmap1,x,y,paint);
}
if (count==100){
noCollsion=false;
count=0;
}
}else {
canvas.drawBitmap(bitmap1,x,y,paint);
}
for (int i =0;i<hp;i++){
canvas.drawBitmap(bitmaphp,i*bitmaphp.getWidth(),MySurfaceView.heigth-bitmaphp.getHeight(),paint);
}
}
四. 如何绘制子弹
子弹的属性有x,y轴,速度以及当子弹飞出屏幕外时移除它
我们把玩家子弹与Boss子弹写在一个类中,用0代表玩家子弹,1代表Boss子弹
①绘制玩家的子弹
case 1:
RectF rectF = new RectF(0,0,getWidth(),getHeight());
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.gamewin),null,rectF,paint);
break;
设置玩家子弹飞行速度与方向以及移除玩家子弹,因为在视觉效果中玩家子弹是向上飞的,所以y轴为-
switch (type){
//玩家子弹
case 0:
y -= speed+5;
if (y < 0) {
isDead = true;
}
break;
②绘制Boss子弹
case 2:
RectF rectF1 = new RectF(0,0,getWidth(),getHeight());
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.gamelost),null,rectF1,paint);
break;
设置Boss子弹飞行速度与方向以及移除,与玩家子弹相反,Boss子弹y轴为+
//Boss子弹
case 1:
y += speed+8;
if (y < 0) {
isDead = true;
}
break;
default:
break;
五. 如何判断碰撞(子弹与飞机碰撞,飞机与飞机)
我们设定当子弹的坐标与飞机的坐标重合时判定子弹与飞机碰撞;
玩家飞机与Boss飞机坐标重合时判定飞机与飞机碰撞
private void ff(){
switch (teyp){
case 0:
y-=speed;
if (y<-300){
isDead=true;
}
break;
case 1:
y+=(speed/2);
if (y>MySurfaceView.heigth){
isDead=true;
}
break;
}
}
六. 如何绘制爆炸效果
首先继承子弹类,因为子弹碰撞到飞机后才会产生爆炸,然后将爆炸效果一帧帧的绘制出来
public class Boom extends Bullet {
private Bitmap bitmap;
private int x,y;
private int totalFrame;
private int currentFrame;
private int frameW,frameH;
private boolean isEnd;
public Boom(Bitmap bitmap, int x, int y, int totalFrame) {
super();
this.bitmap = bitmap;
this.x = x;
this.y = y;
this.totalFrame = totalFrame;
frameW = bitmap.getWidth()/totalFrame;
frameH = bitmap.getHeight();
}
public void draw(Canvas canvas, Paint paint){
canvas.save();
canvas.clipRect(x,y,x+frameW,y+frameH);
canvas.drawBitmap(bitmap,x-currentFrame*frameW,y,paint);
canvas.restore();
logic();
}
public void logic(){
if (currentFrame<totalFrame){
currentFrame++;
}else{
isEnd = true;
}
}
public boolean isEnd() {
return isEnd;
}
}
七. 如何添加音效
首先定义一个游戏音效类GameSoundPool,定义SoundPool对象
public class GameSoundPool {
private SoundPool soundPool;
private int s1;
private int s2;
private int s3;
public GameSoundPool(Context context){
this.soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC,0);
s1 = soundPool.load(context,R.raw.shoot,1);
s2 = soundPool.load(context,R.raw.explosion2,1);
s3 = soundPool.load(context,R.raw.bgm_zhandou2,1);
}
public void playSound(int s) {
switch (s){
case 1:
soundPool.play(s1,1,1,1,1,1.0f);
break;
case 2:
soundPool.play(s2,1,1,1,1,1.0f);
break;
case 3:
soundPool.play(s3,1,1,1,1,1.0f);
break;
}
}
}
八. 那些地方用到封装、继承、多态、方法重载、接口等
①封装到处都有吧
②爆炸效果那里就用到了继承
③玩家子弹与Boss子弹用到了多态
④
⑤SurfaceHolder.Callback,与Runnable
九. 收获与感悟
一个极其简单的小飞机游戏却花掉了我一周的时间(也可以说是一个月,之前三周学的基础知识就在这里得到了应用),真的无法想象我们平时玩的例如LOL、dnf、吃鸡之类的游戏是由多少行代码构成的。在编程这一行我算是没什么天赋的平庸之辈,只能用努力去不断弥补。
路漫漫其修远兮,吾将上下而求索。