飞机大战(上篇绘制)

大家好,今天来共同探讨一下,飞机大战这个游戏,本篇章主要讲解飞机大战的背景绘制,用户飞机的绘制,敌机的绘制,子弹的绘制,本次游戏设计和前两次是一样的,都是采用的是SurfaceView+BitMap二级缓存实现的。见下图
这里写图片描述
首先来看看先,下面这个接口

 public interface ImageErji {
    float getX();
    float getY();
    Bitmap draw();
    //销毁BitMap
    void recycle();
}

一共四个方法,分别是获取坐标的x,y,绘制图片以及销毁BitMap的方法。该接口适用于所有的游戏中出现的图片。

   class Bg implements ImageErji {
    private Bitmap newBitMap = null;
    private int hight = 0;
    private float x;
    private float y;

    public Bg() {
        newBitMap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    }

    public void setX(float x) {
        this.x = x;
    }

    public void setY(float y) {
        this.y = y;
    }

    @Override
    public float getX() {
        return x;
    }

    @Override
    public float getY() {
        return y;
    }

    @Override
    public Bitmap draw() {
        mCanvas.setBitmap(newBitMap);
        mCanvas.drawBitmap(mBackGroungBitMap, new Rect(0, 0, mBackGroungBitMap.getWidth(), mBackGroungBitMap.getHeight())
                , new Rect(0, -getMeasuredHeight() + hight, getMeasuredWidth(), hight), mPaint);

        mCanvas.drawBitmap(mBackGroungBitMap, new Rect(0, 0, mBackGroungBitMap.getWidth(), mBackGroungBitMap.getHeight()),
                new Rect(0, hight, getMeasuredWidth(), hight + getMeasuredHeight()), mPaint);
        hight+=10;
        if (hight >= getMeasuredHeight()) {
            hight = 0;
        }
        return newBitMap;
    }

    public void reset(){
        hight = 0;
    }

    @Override
    public void recycle() {
        newBitMap.recycle();
    }
}

该类draw() 实现的功能是,背景图片的从上至下移动,线程没循环一次就要绘制一次

接下来看用户飞机的绘制

class UserPlane implements ImageErji {
    private Bitmap newBitMap;
    private int flag = 0;
    private float x;
    private float y;

    public UserPlane() {
        newBitMap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        //设置初始位置
        y = getMeasuredHeight() - mUserBitMap.getHeight();
        x = (getMeasuredWidth() - mUserBitMap.getWidth() / 4) / 2;
    }


    public void setX(float x) {
        this.x = x;
    }

    public void setY(float y) {
        this.y = y;
    }

    @Override
    public float getX() {
        return x;
    }

    @Override
    public float getY() {
        return y;
    }

    public boolean check() {
        if (startTuchPoint.x < x || startTuchPoint.x > (x + mUserBitMap.getWidth() / 4)) {
            return false;
        }

        if (startTuchPoint.y < y || startTuchPoint.y > y + mUserBitMap.getHeight()) {
            return false;
        }
        return true;
    }

    //设置userPlane的坐标
    public void resetXY(float x, float y) {
        float xx = x - mUserBitMap.getWidth() / 8;
        float yy = y - mUserBitMap.getHeight() / 2;
        //边界检查
        if (xx < 0 || xx > getMeasuredWidth() - mUserBitMap.getWidth() / 4) {
            return;
        }

        if (yy < 0 || yy > getMeasuredHeight() - mUserBitMap.getHeight()) {
            return;
        }
        //设置
        setX(xx);
        setY(yy);
    }

    @Override
    public Bitmap draw() {
        mCanvas.setBitmap(newBitMap);
        Bitmap b = mUserLisrt.get(flag / 10);
        mCanvas.drawBitmap(b, new Rect(0, 0, b.getWidth(), b.getHeight())
                , new Rect(0, 0, b.getWidth(), b.getHeight()), mPaint);
        flag++;
        if (flag == 40) {
            flag = 0;
        }
        return newBitMap;
    }

    @Override
    public void recycle() {
        newBitMap.recycle();
    }

    public void reset() {
        y = getMeasuredHeight() - mUserBitMap.getHeight();
        x = (getMeasuredWidth() - mUserBitMap.getWidth() / 4) / 2;
    }
}

该类主要是负责用户飞机的绘制,检查,和销毁,背景和用户飞机只有一个实体类,所以作为字段,在urfaceCreated()方法中初始化,还要提供一个集合来承载背景和用户飞机,在线程方法中依次绘制背景和用户飞机,还有一点,用户飞机和敌机是有动画效果的,所以要在一次线程循环中绘制不同的图片,敌机也是如此,如下代码块

//循环绘制图片,将图片贴到mPicture上
        for (ImageErji imageErji : listErji) {
            Bitmap b = imageErji.draw();
            mCanvas.setBitmap(mPicture);
            mCanvas.drawBitmap(b, imageErji.getX(), imageErji.getY(), mPaint);
        }

绘制玩背景和用户飞机后,还要能拖动一起移动,这样我们还要重写OnTuchEvent()方法,这里我控制飞机开始是在屏幕的底部中间的位置

 @Override
public boolean onTouchEvent(MotionEvent event) {
    isUserUseful = true;
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startTuchPoint.set(event.getX(), event.getY());
            if (mUserPlane.check()) {
                isUserUseful = true;
            } else {
                isUserUseful = false;
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (isUserUseful) {
                //选中User的飞机,让飞机在点击位置的中间位置
                mUserPlane.resetXY(event.getX(), event.getY());
            }

            break;
        case MotionEvent.ACTION_UP:
            break;

    }
    return true;
}

接下来,我们来绘制敌人的飞机

class Enemy implements ImageErji {
    private Bitmap newBitMap;
    private int flag = 0;
    private float x;
    private float y;

    public Enemy() {
        newBitMap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    }

    public void setX(float x) {
        this.x = x;
    }

    public void setY(float y) {
        this.y = y;
    }

    @Override
    public float getX() {
        return x;
    }

    @Override
    public float getY() {
        return y;
    }

    @Override
    public Bitmap draw() {
        mCanvas.setBitmap(newBitMap);
        Bitmap b = mEnemyBitMapList.get(flag / 10);
        mCanvas.drawBitmap(b, new Rect(0, 0, b.getWidth(), b.getHeight())
                , new Rect(0, 0, b.getWidth(), b.getHeight()), mPaint);
        flag++;
        if (flag == 40) {
            flag = 0;
        }

        return newBitMap;
    }

    public void reset(){
        flag = 0;
    }
    @Override
    public void recycle() {
        newBitMap.recycle();
    }
}

值得注意的是,为了不让随机的飞机重叠在一起,我先划分了n快区域,再在每块区域中取随机数,自认为这种方法是最简单的

private void creatEnemyPoint() {
    boolean isNeed = false;
    //找最近的
    if (mEnemyList.size() == 0) {
        isNeed = true;
    } else {
        Enemy e = mEnemyList.get(mEnemyList.size() - 1);
        if (e.getY() > mEnemyBitMap.getHeight()) {
            isNeed = true;
        }
    }

    if (isNeed) {
        //最大飞机的数量
        int num = mRandom.nextInt(getMeasuredWidth() / mEnemyBitMap.getWidth());
        int countW;
        //把横向高度分成num份,产生的随机数加上前面的num份距离
        if (num == 0) {
            countW = getMeasuredWidth() - mEnemyBitMap.getWidth();
        } else {
            countW = getMeasuredWidth() / num;
        }
        for (int i = 0; i < num; i++) {
            //减去一个飞机的宽度
            int x = mRandom.nextInt(countW - mEnemyBitMap.getWidth()) + i * countW;
            Enemy ee = new Enemy();
            ee.setX(x);
            ee.setY(-mEnemyBitMap.getHeight());
            mEnemyList.add(ee);
        }

    }
}

接下来,要绘制子弹了
//子弹

  class ZiDan implements ImageErji {
    private Bitmap newBitMap;
    private float x;
    private float y;
    private boolean isDelete = false;

    public boolean isDelete() {
        return isDelete;
    }

    public void setDelete(boolean delete) {
        isDelete = delete;
    }

    public ZiDan() {
        newBitMap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    }

    @Override
    public float getX() {
        return x;
    }

    @Override
    public float getY() {
        return y;
    }

    public void setX(float x) {
        this.x = x;
    }

    public void setY(float y) {
        this.y = y;
    }

    @Override
    public Bitmap draw() {
        mCanvas.setBitmap(newBitMap);
        mCanvas.drawBitmap(mZiDuanBitMap, 0, 0, mPaint);
        return newBitMap;
    }

    @Override
    public void recycle() {
        newBitMap.recycle();
    }

    private boolean CheckPengZhuang(List<ZiDan> list){
        for (int i = 0; i <mEnemyList.size() ; i++) {
            Enemy e = mEnemyList.get(i);
            if (x+mZiDuanBitMap.getWidth()<e.getX()||x>e.getX()+mEnemyBitMap.getWidth()/4){
                continue;
            }
            if (y-e.getY()+mEnemyBitMap.getHeight()<=0){
                mEnemyList.remove(i);
                e.recycle();
                list.remove(this);
                recycle();
                return true;
            }
        }
        return false;
    }
}

这里子弹的绘制就不在过多的阐述了 ,方法基本一样,然后我们还要生产子弹,当最后的子弹移动了一个子弹的高度了,就要生产一个子弹

private void creatZiDan() {
    boolean isNeed = true;
    if (mZiDanList.size()>0) {
        ZiDan zz = mZiDanList.get(mZiDanList.size() - 1);
        if (zz.getY()<mUserPlane.getY()-mZiDuanBitMap.getHeight()){
            isNeed = true;
        }else {
            isNeed = false;
        }
    }
    if (isNeed) {
        //生产子弹
        float xx = mUserPlane.getX();
        float yy = mUserPlane.getY();
        float positionX =xx+(mUserBitMap.getWidth()/4-mZiDuanBitMap.getWidth())/2;
        ZiDan z = new ZiDan();
        z.setX(positionX);
        z.setY(yy - mZiDuanBitMap.getHeight());
        mZiDanList.add(z);
    }
}

现在背景,用户飞机,敌机,子弹都有了,我们就要考虑碰撞问题,好啦,下一篇我们继续讲,github地址:https://github.com/yzzAndroid/PlaneWar

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值