飞机大战是集成这一个月实训以来的成果,其中包括了所学的封装,继承,多态,方法的重载等多个知识点构成的一款简单的小游戏。经过一个礼拜的时间将此项目完成,由多个模块组成。
这个代码我们一共需要创建7个类
这个游戏首先的第一个问题就是呈现出飞机正在向前飞行的效果,也就是如何将图片一张接着一张无缝的滚动播放
在MySurfacView的画布上将背景图片上传
我们先创建Blackground类,并创建logic方法
package com.example.administrator.myapplication9;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
public class BackGround {
private int y1;
private int y2;
private Bitmap bitmap;
public BackGround(Bitmap bitmap){
this.bitmap = bitmap;
y1=0;
y2=y1-bitmap.getHeight();
}
public void draw(Canvas canvas,Paint paint){
logic();
canvas.drawBitmap(bitmap,0,y1,paint);
canvas.drawBitmap(bitmap,0,y2,paint);
}
public void logic() {
y1+=10;
y2+=10;
if (y1>=MySurfaceView.height){
y1=y2-bitmap.getHeight();//移动到第二张图片的顶部
}
if (y2>=MySurfaceView.height){
y2=y1-bitmap.getHeight();
}
}
}
我们需要创建一只画笔,锁定画布
并在MySurfaceView中创建run方法
public void run() {
gameSoundPool.playSound(3);
Paint paint = new Paint();
BackGround backGround = new BackGround(BitmapFactory.decodeResource(getResources(), R.mipmap.img_bg_level_3));
plane = new Myplane(BitmapFactory.decodeResource(getResources(), R.mipmap.myplane),BitmapFactory.decodeResource(getResources(), R.mipmap.myhp));
BossPlane bossPlane = new BossPlane(BitmapFactory.decodeResource(getResources(), R.mipmap.bossplane));
这样就将敌机和我方机器绘制在了画布上
绘制子弹和绘制飞机的方法类似,创建一个子弹(bullet)类,在MySurfaceView中需要实例化子弹对象,然后将子弹的图片上传,我们还需要创建我方子弹,敌方子弹的数组eg: private VectorbulletVector = new Vector <>();像这样的一个数组用来存放子弹,调用bullet类,在bullet类中创造logic方法,用if语句进行判断,分别进行判断,并给玩家子弹和敌方子弹进行设置
这里写package com.example.administrator.myapplication9;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
public class Bullet {
private Bitmap bitmap;
private int x, y;
private int speed = 10;
private boolean isDead;
private int type;
public Bullet(Bitmap bitmap, int x, int y,int type) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
this.type = type;
}
public Bullet() {
}
public void draw(Canvas canvas, Paint paint) {
canvas.drawBitmap(bitmap, x, y, paint);
logic();
}
public void logic() {
switch (type){
//玩家子弹
case 0:
y -= speed+5;
if (y < 0) {
isDead = true;
}
break;
//Boss子弹
case 1:
y += speed+8;
if (y < 0) {
isDead = true;
}
break;
default:
break;
}
}
public boolean isDead() {
return isDead;
}
public Bitmap getBitmap(){
return bitmap;
}
public int getX(){
return x;
}
public int getY() {
return y;
}
public void setDead(boolean dead) {
isDead = dead;
}
}
代码片
这一段代码是在开始创建子弹的数组
private VectorbulletVector = new Vector <>();
private VectorbossBulletVector = new Vector <>();
private VectorboomVector = new Vector <>();
public void run() {
gameSoundPool.playSound(3);
Paint paint = new Paint();
BackGround backGround = new BackGround(BitmapFactory.decodeResource(getResources(), R.mipmap.img_bg_level_3));
plane = new Myplane(BitmapFactory.decodeResource(getResources(), R.mipmap.myplane),BitmapFactory.decodeResource(getResources(), R.mipmap.myhp));
BossPlane bossPlane = new BossPlane(BitmapFactory.decodeResource(getResources(), R.mipmap.bossplane));
while (isDrawing) {
count++;
try {
canvas = surfaceHolder.lockCanvas();//锁定(选定)画布
canvas.drawColor(Color.WHITE);
switch (GAME_STATE){
case 0:
backGround.draw(canvas, paint);
plane.draw(canvas, paint);
bossPlane.draw(canvas,paint);
if(count%20==0){
gameSoundPool.playSound(1);
Bullet bullet = new Bullet(BitmapFactory.decodeResource(getResources(), R.mipmap.mybullet),plane.getX(),plane.getY(),0);
Bullet bullet1 = new Bullet(BitmapFactory.decodeResource(getResources(), R.mipmap.mybullet),plane.getX()+plane.getWidth(),plane.getY(),0);
bulletVector.add(bullet);
bulletVector.add(bullet1);
}
for (int i = 0;i
if (bulletVector.elementAt(i).isDead()) {
bulletVector.remove(i);
}
}
for (int i = 0;i
bulletVector.elementAt(i).draw(canvas,paint);
if (bossPlane.isCollision(bulletVector.elementAt(i))){
gameSoundPool.playSound(2);
Boom boom = new Boom(BitmapFactory.decodeResource(getResources(),R.mipmap.boom),bossPlane.getX()+bossPlane.getFrameW()/4,bossPlane.getY(),7);
boomVector.add(boom);
}
}
for (int i=0;i
if (boomVector.elementAt(i).isDead()){
boomVector.remove(i);
}else{
boomVector.elementAt(i).draw(canvas,paint);
}
}
if(count%40==0){
Bullet bullet = new Bullet(BitmapFactory.decodeResource(getResources(), R.mipmap.bossbullet),bossPlane.getX()+bossPlane.getFrameW ()/2,bossPlane.getY()+bossPlane.getFrameH(),1);
//Bullet bullet1 = new Bullet(BitmapFactory.decodeResource(getResources(), R.mipmap.bossbullet),bossPlane.getX()+bossPlane.getFrameW(),bossPlane.getY()+bossPlane.getFrameH(),1);
bossBulletVector.add(bullet);
// bossBulletVector.add(bullet1);
}
for (int i = 0;i < bossBulletVector.size(); i++) {
if (bossBulletVector.elementAt(i).isDead()) {
bossBulletVector.remove(i);
}
}
for (int i = 0;i < bossBulletVector.size(); i++){
bossBulletVector.elementAt(i).draw(canvas,paint);
plane.isCollision(bossBulletVector.elementAt(i));
}
plane.isCollision(bossPlane);
break;
case 1:
RectF rectF1 = new RectF(0,0,getWidth(),getHeight());
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.gamewin),null,rectF1,paint);
break;
case 2:
RectF rectF = new RectF(0,0,getWidth(),getHeight());
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.gamelost),null,rectF,paint);
break;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);//解锁画布,显示到屏幕上
}
}
以上这一段是完整的一段run方法,里面有子弹的绘制,还有如何运行程序,下面这一小段代码就是如何在MySurfaceView里如何绘制子弹
Bullet bullet = new Bullet(BitmapFactory.decodeResource(getResources(), R.mipmap.bossbullet),bossPlane.getX()+bossPlane.getFrameW()/2,bossPlane.getY()+bossPlane.getFrameH(),1);
//Bullet bullet1 = new Bullet(BitmapFactory.decodeResource(getResources(), R.mipmap.bossbullet),bossPlane.getX()+bossPlane.getFrameW(),bossPlane.getY()+bossPlane.getFrameH(),1);
bossBulletVector.add(bullet);
// bossBulletVector.add(bullet1);
实例化,然后将子弹绘制出来
在飞机大战中碰撞分为两种,飞机与飞机的碰撞,能够子弹与飞机的碰撞,而这一段也是非常重要的,我们需要知道飞机的位置,get到飞机的位置,当我方飞机碰撞到敌方飞机的顶部,或子弹打到时,敌方飞机有爆炸效果(爆炸效果如何实现,下文会写),左右时,我方飞机进行闪烁,同样,当敌方子弹闯入我方飞机的范围内,我方飞机闪烁,并且减少血量
在Myplane中建立两个方法 noCollision(Boss),isCollision(myplane)
并用if语句进行条件判断如果碰到血量就–
public void draw(Canvas canvas,Paint paint){
if (hp<=0){
MySurfaceView.GAME_STATE= 2;
}
if (noCollision){
noCollisionCount++;
if (noCollisionCount%10==0){
canvas.drawBitmap(bitmap,x,y,paint);//飞机闪烁
}
if (noCollisionCount>100){//无敌时间
noCollision = false;
noCollisionCount = 0;
}
}else {
//非无敌状态
canvas.drawBitmap(bitmap,x,y,paint);
}
for (int i = 0; ipublic void touchEvent(MotionEvent event){
if (event.getAction()==MotionEvent.ACTION_MOVE){
float ex = (int) event.getX();
float ey = (int) event.getY();
if (ex>x&&exy&&eyint) ex-width/2;
y = (int) ey-height/2;
if(y<0){
y=0;
}
if(y+height>MySurfaceView.height){
y=MySurfaceView.height-height;
}
}
}
`
``` public boolean isCollision(Bullet bullet){
if (noCollision){
return false;
}else{
if (bullet.getX()>x&&bullet.getX()y&&bullet.getY()true;
if (hp>0){
hp--;
}
return true;
}
}
return false;
}
上面的这两段代码实现的判断碰撞,然后不同的飞机的不同反应
"se-preview-section-delimiter">
####如何绘制爆炸效果
当飞机子弹打到敌方飞机时会有爆炸效果,我们需要新建一个Bomm类
"se-preview-section-delimiter">
package com.example.administrator.myapplication9;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
public class Boom extends Bullet {
private Bitmap bitmap;
private int x,y;
private int totalFrame;
private int currentFrame;
private int frameW,frameH;
private boolean isEnd;
public Boom(Bitmap bitmap, int x, int y, int totalFrame) {
super();
this.bitmap = bitmap;
this.x = x;
this.y = y;
this.totalFrame = totalFrame;
frameW = bitmap.getWidth()/totalFrame;
frameH = bitmap.getHeight();
}
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
}
同样我们需要get到位置,爆炸的效果是一帧一帧显示的,并且在MySurfaceView中调用,运用for循环
<div class="se-preview-section-delimiter">div>
for (int i = 0;i
package com.example.administrator.myapplication9;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
public class GameSoundPool {
private SoundPool soundPool;
private int s1;
private int s2;
private int 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.bg_logobg,2);
}
public void playSound(int s) {
switch (s){
case 1:
soundPool.play(s1,1,1,1,1,1.0f);
break;
case 2:
soundPool.play(s2,1,1,1,1,1.0f);
break;
case 3:
soundPool.play(s3,1,1,1,1,1.0f);
break;
}
}
}
用switch,case语句进行判断,然后将在MySurfaceView中,将这些音乐写入合适的位置,比如在boss发射子弹时运行哪一个音乐,音乐代码中的参数分别是左右声道,音乐的播放速率。