飞机大战

1.整体思路的实现

飞机大战的类继承了SurfaceView,用了SurfaceHolder.Callback和Runnble接口,Runnable必须要有run方法,SurfaceHolder.Callback中定义了三个接口方法:
   1:public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}//Surface的大小发生改变时调用。
   2: public void surfaceCreated(SurfaceHolder holder){}//Surface创建时激发,一般在这里调用画面的线程。

   3: public void surfaceDestroyed(SurfaceHolder holder){}//销毁时激发,一般在这里将画面的线程停止、释放。

要想在屏幕上有东西,就必须要有canvas画布和paint画笔,要想能够屏幕上飞机有反应,就必须要有touchEvent方法,并且要return true,永远监听屏幕事件。

在绘制子弹的时候要用Vector数组,他和ArrayList的区别在于Vector是线程安全的。

首先我们要添加连续滚动的背景图片,其次添加我的飞机和敌人的飞机,然后再添加我的飞机的子弹和敌机的子弹,添加子弹音效与飞机爆炸的音效时,我们用了SoundPool。

2.如何绘制循环滚动的图片

第一步要把图片放到mipmap文件夹中,再转换格式。

用drawbitmap绘制两张一样的背景图片,第一张接着第二张滚动,当第二张的图片的y大于屏幕的高度时,第一张图片立马移到第二张图片的后面,循环播放即可。

public class BackGround {
    private int y1;
    private int y2;
    private  Bitmap bitmap;
    public BackGround (Bitmap bitmap){
        this.bitmap = bitmap;
        y1 = 0;
        y2 = bitmap.getHeight();
    }


    public void  draw(Canvas canvas,Paint paint){
        logic();

        canvas.drawBitmap(bitmap,0,y1,paint);
        canvas.drawBitmap(bitmap,0,y2,paint);

    }

    private void logic(){
        y1+=5;
        y2+=5;
        if (y1>=MySurfaceView.height){
            y1 = y2 - bitmap.getHeight();
        }
        if(y2>MySurfaceView.height){
            y2 = y1-bitmap.getHeight();
        }
    }


}

4.如何绘制飞机

首先定义自己的飞机类,定义飞机的坐标和宽和高,还有飞机的血量,要想能够让飞机移动,旧的有touchEvent方法,并且不能让他移除屏幕

public void touchEvent(MotionEvent event){
        if (event.getAction()==MotionEvent.ACTION_MOVE){

           float ex = event.getX();
           float ey = event.getY();
           if (ex>x && ex<x+width&&ey>y&&ey<y+height){
               x = (int) (ex - width/2);
               y = (int) (ey - height/2);
               if(y<0){
                   y=0;
               }
               if (y+height>MySurfaceView.height){
                   y=MySurfaceView.height-height;
               }
           }
        }
    }
飞机也要有无敌闪烁状态和无敌时间
 public void draw(Canvas canvas,Paint paint){
     
        if (noCollision){
            noCollisionCount++;
            if (noCollisionCount%10==0){
             canvas.drawBitmap(bitmap,x,y,paint);   //飞机闪烁
            }
            if (noCollisionCount>50){//无敌时间
                noCollision = false;
                noCollisionCount = 0;
            }
        }
        else{
            //非无敌状态
            canvas.drawBitmap(bitmap,x,y,paint);
        }

        for (int i = 0;i<hp;i++){
            canvas.drawBitmap(bitmapHp,i*bitmapHp.getWidth(),MySurfaceView.height-bitmapHp.getHeight(),paint);
        }
    }
public boolean isCollision(MyBullet myBullet){
        if (noCollision){
            return false;
        }else {
            if (myBullet.getX()>x&&myBullet.getX()<x+width&&myBullet.getY()>y&&myBullet.getY()<y+height){
                noCollision = true;
                if (hp > 0){
                    hp--;
                }
                return true;
            }
        }
        return  false;
    }

    public boolean isCollision(BossPlane bossPlane){
        if (noCollision){
            return false;
        }else {
            if(y > bossPlane.getY()+bossPlane.getFrameH()||y+height < bossPlane.getY()||x >bossPlane.getX()+bossPlane.getFrameW()||x+width < bossPlane.getX()){

            }else {
                noCollision = true;
                if (hp > 0){
                    hp--;
                }
                return true;
            }
        }
bossplane和我的飞机同理,但是bossplane有个疯狂模式,一定事件后会俯冲,这时X不变,之变个Y,俯冲时有个阻尼效果,速度会慢慢下降,让后回到原点。
 public void logic() {
        count++;
        if (isCrazy) {
            //疯狂模式
            y = y + crazySpeed;
            crazySpeed--;
            if (y == 0) {
                isCrazy = false;
                crazySpeed = 50;//阻尼效果
            }
            if (y > MySurfaceView.height - frameH) {
                crazySpeed = -crazySpeed;
            }
        } else {
            if (count % time == 0) {
                isCrazy = true;
            }
            x = x + speed;
            if (x > MySurfaceView.width - frameW) {
                speed = -speed;
            }
            if (x < 0) {
                speed = -speed;
            }
        }

    }

4.如何绘制子弹

首先创建一个Vector数组,存放对象bullet。用Count来计算存放了多少bullet,当bullet到达屏幕尽头时,就让bullet消失,这样可以不过多占用内存

public  void  logic(){
    switch(type){
        case 0:
            y-=speed;
            if (y<0){
                isDead = true;
            }
            break;
        case 1:
            y+=bSpeed+2;
            if (y>MySurfaceView.height){
                isDead = true;
            }
            break;
        default:
            break;

    }
}

无论是我的飞机还是敌机都要赋予一个子弹的初始速度,并且不能让敌机的自当速度与屏幕滚动的速度一样。

private int speed = 18;
private int bSpeed = 14;

子弹的图片也要用到Bitmap。

写敌机的子弹时不需要再创建一个类,可以用switch语句来写。

当写我的子弹时,要绘制子弹,移除子弹,判断子弹是否击中敌机

if (count % 20 == 0) {
                            MyBullet myBullet = new MyBullet(BitmapFactory.decodeResource(getResources(), R.mipmap.feidan), myPlane.getX(), myPlane.getY(), 0);
                            MyBullet myBullet2 = new MyBullet(BitmapFactory.decodeResource(getResources(), R.mipmap.feidan), myPlane.getX() + myPlane.getWidth(), myPlane.getY(), 0);
                            bulletVector.add(myBullet);
                            bulletVector.add(myBullet2);
                            gameSoundPool.playSound(1);
                        }
                        //移除消失的玩家子弹
                        for (int i = 0; i < bulletVector.size(); i++) {
                            if (bulletVector.elementAt(i).isDead()) {
                                bulletVector.remove(i);
                            }
                        }
                        //绘制玩家子弹
                        for (int i = 0; i < bulletVector.size(); i++) {
                            bulletVector.elementAt(i).draw(canvas, paint);
                            if (bossPlane.isCollision(bulletVector.elementAt(i))) {   //判断我的子弹是否击中boss飞机,击中就画一张boom图
                                Boom boom = new Boom(BitmapFactory.decodeResource(getResources(), R.mipmap.boom), bossPlane.getX(), bossPlane.getY(), 7);
                                boomVector.add(boom);
                                gameSoundPool.playSound(2);
                            }
                        }
boss的子弹也是同理
 if (count % 50 == 0) {
                            MyBullet myBullet3 = new MyBullet(BitmapFactory.decodeResource(getResources(), R.mipmap.bossbullet), bossPlane.getX(), bossPlane.getY() + bossPlane.getFrameH(), 1);
                            MyBullet myBullet4 = new MyBullet(BitmapFactory.decodeResource(getResources(), R.mipmap.bossbullet), bossPlane.getX() + bossPlane.getFrameW(), bossPlane.getY() + bossPlane.getFrameH(), 1);
                            bossBulletVector.add(myBullet3);
                            bossBulletVector.add(myBullet4);
                        }

                        //移除消失的Boss子弹
                        for (int i = 0; i < bossBulletVector.size(); i++) {
                            if (bossBulletVector.elementAt(i).isDead()) {
                                bossBulletVector.remove(i);
                            }
                        }
                        //绘制boss子弹
                        for (int i = 0; i < bossBulletVector.size(); i++) {
                            bossBulletVector.elementAt(i).draw(canvas, paint);
                            myPlane.isCollision(bossBulletVector.elementAt(i));  //判断boss子弹是否击中我的飞机
                        }

                        myPlane.isCollision(bossPlane);//判断我的飞机是否和boss飞机碰撞

5如何判断碰撞

还要判断我的飞机是否与敌机碰撞。

if (x+bitmap1.getWidth()<bossPlane.getX()||x>bossPlane.getX()+bossPlane.getFrameW()||
                    y>bossPlane.getY()+bossPlane.getFrameH()||y+bitmap1.getHeight()<bossPlane.getY()){
     return false;
}else {
      hp--;
     noCollsion = true;

     return true;
}

6.如何绘制爆炸效果

爆炸效果也要用Vector数组,爆炸的图片有好几帧,如何让他们衔接起来是难点,首先要将他们进行剪裁,剪成七个,也就是七帧,也要创建一个count对象来计数

 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;
        }
    }

7.如何添加音效

添加音效时要先建造一个GameSoundPool类,定义一个SoundPool,定义一个对象,给他初始值,音乐文件,soundpool.play播放


public class GameSoundPool {
    private SoundPool soundPool;
    private int s1,s2,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,0,1.0f);
            break;
            case 2:
                soundPool.play(s2,1,1,1,0,1.0f);
                break;
        soundPool.play(s3,1,1,1,0,1.0f);
        }

    }
}

soundpool.play里有左右声道和音量大小。

8.那些地方用到封装,继承,多态,方法重载,接口。

所有类中都用到了封装

public class MySurfaceView extends SurfaceView用到了继承

没有多态

没有方法重载

SurfaceHolder.Callback,与Runnable用到了接口

9.我的心得

这两个礼拜学习了飞机大战,主要目的并不是你要会做,而是要理解前两个礼拜学的java基础知识,这个项目是对java知识的一种汇总,通过这两个礼拜的学习,我java的知识得到了一定的提高。这个飞机项目非常锻炼我的逻辑思维能力,做项目前一定要理清思路,我们的java老师非常的负责人,我们同学有任何问题他都会帮助我们,是一个十分经责和蔼的老师。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值