飞机大战(上篇绘制)
来源:互联网 发布:安卓鼓机软件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
- 飞机大战(上篇绘制)
- 飞机大战(JavaScript)
- 飞机大战(二)
- 飞机大战(准备)
- 飞机大战(三)
- 飞机大战(四)
- 飞机大战(五)
- MFC飞机大战开发之绘制图像
- android:如何用一天时间,写出“飞机大战”这样的游戏!(无框架-SurfaceView绘制)
- C#飞机大战(仿微信)
- 飞机大战(JavaScript代码)
- 飞机大战(下篇:逻辑)
- 飞机大战
- 飞机大战
- 飞机大战
- 飞机大战
- 飞机大战
- 飞机大战
- Linux查看进程和终止进程的技巧
- Android学习笔记--AIDL
- javaweb学习总结——Servlet开发(一)
- 添加水印logo和文字 iOS
- spring boot集成mybatis
- 飞机大战(上篇绘制)
- sleep和yield,join
- Spring Boot 之web Filter --不支持排序的使用
- CSS3 transform笔记
- SQL优化大全
- 线程安全集合
- C++标准库(STL)中的容器
- Crackme 5
- The First Day at School