飞机大战(上篇绘制)

来源:互联网 发布:安卓鼓机软件loopz 编辑:程序博客网 时间:2024/05/01 02:21

大家好,今天来共同探讨一下,飞机大战这个游戏,本篇章主要讲解飞机大战的背景绘制,用户飞机的绘制,敌机的绘制,子弹的绘制,本次游戏设计和前两次是一样的,都是采用的是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()方法,这里我控制飞机开始是在屏幕的底部中间的位置

 @Overridepublic 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 2
原创粉丝点击