飞机大战(上篇绘制)

    xiaoxiao2021-03-26  38

    大家好,今天来共同探讨一下,飞机大战这个游戏,本篇章主要讲解飞机大战的背景绘制,用户飞机的绘制,敌机的绘制,子弹的绘制,本次游戏设计和前两次是一样的,都是采用的是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

    转载请注明原文地址: https://ju.6miu.com/read-350305.html

    最新回复(0)