简易版--Java飞机大战

目录

 

射击游戏需求:

所参与的角色: 英雄机、子弹、小敌机、大敌机、小蜜蜂、天空

角色间的关系:

设计规则:

设计类与游戏对象:

需求设计:

代码实现:


射击游戏需求:

所参与的角色: 英雄机、子弹、小敌机、大敌机、小蜜蜂、天空

角色间的关系:

1) 英雄机发射子弹,分单倍火力和双倍火力

2) 子弹射击敌人(小敌机、大敌机、小蜜蜂),若射击到了:

2.1) 子弹直接消失、敌人先爆破再消失

2.2) 子弹打掉小敌机----------玩家得1分

子弹打掉大敌机----------玩家得3分

子弹打掉小蜜蜂----------英雄机得奖励(1条命、40火力值)

3) 敌人(小敌机、大敌机、小蜜蜂)可以和英雄机撞,若撞上了:

3.1) 敌人先爆破再消失

3.2) 英雄机减1条命,同时,清空火力值---英雄机命数为0时,游戏结束

4) 英雄机、子弹、小敌机、大敌机、小蜜蜂都在天空上飞

设计规则:

1. 将所有派生类共有的属性和行为,抽到超类中-------------抽共性

2.派生类的行为都一样,设计为普通方法派生类的行为都不一样,设计为抽象方法

3.将部分派生类共有的行为,抽到接口中接口是对继承单根型的扩展-------------实现多继承

 

设计类与游戏对象:

对象: 英雄机、子弹、小敌机、大敌机、小蜜蜂、天空

对象类: Hero、Bullet、Airplane、BigAirplane、Bee、Sky

超类:FlyingObject超类,6个对象类继承超类

图片工具类:Images(封装与图片相关的操作/方法)

接口:Enemy(得分接口),Award( 奖励接口)

窗口:World类 

需求设计:

1.构造法:在FlyingObject中设计2个构造方法,6个对象类分别调用

2.移动方法:在6个对象类中重写step()移动

3.访问控制:给类中成员添加访问控制修饰符

4.画窗口:在World类中,测试,调用即可.

5.画对象:

1) 想画对象得需要获取对象的图片,每个对象都能获取图片,意味获取图片为对象共有的行为,

所以将获取图片行为设计在超类中,每个对象获取图片的行为都是不一样的,所以设计为抽象方法,

在FlyingObject中设计抽象方法getImage()用于获取对象的图片

2) 获取图片时需要去考虑对象的状态,因为在不同状态下获取的图片是不一样的,

每个对象都有状态,意味着状态为对象所共有的属性,所以设计在超类中,

状态一般都是固定的,所以都设计为常量,同时设计一个 state变量来表示当前的状态

,在FlyingObject 中设计LIFE、DEAD、REMOVE三个常量,设计state变量表示当前状态

状态有了,还需要去判断状态,每个对象都得判断,意味着判断状态为共有行为,

所以设计在超类中,每个对象判断状态是方式都是一样的,所以设计为普通方法

,在FlyingObject中设计isLife()、isDead()、isRemove()来判断对象的状态

3) 派生类重写getImage()获取图片:

3.1) 天空Sky,直接返回sky图片即可

3.2) 子弹Bullet:

3.2.1) 若活着的,直接返回bullet图片即可

3.2.2) 若死了的,直接删除(不返回图片)

3.3) 英雄机Hero:

3.3.1) 若活着的,直接返回heros[0]和heros[1]的来回切换

3.4) 小敌机Airplane:

3.4.1) 若活着的,直接返回airs[0]图片即可

3.4.2) 若死的了,返回airs[1]到airs[4]的爆破图,4后删除(不返回图片)

3.5) 大敌机BigAirplane:

3.4.1) 若活着的,直接返回bairs[0]图片即可

3.4.2) 若死的了,返回bairs[1]到bairs[4]的爆破图,4后删除(不返回图片)

3.4) 小蜜蜂Bee:

3.4.1) 若活着的,直接返回bees[0]图片即可

3.4.2) 若死的了,返回bees[1]到bees[4]的爆破图,4后删除(不返回图片)

4) 图片有了就可以开画了,因为是需要往窗口上画,所以在窗口World类中重写paint()方法实现画对象

6.敌人入场:

1) 敌人对象是由窗口产生的,所以在World中设计nextOne()生成敌人对象

2) 敌人入场为定时发生的,所以在 run()中调用enterAction()实现敌人入场

在enterAction中:

每400毫秒,获取敌人对象obj, enemies扩容,将obj添加到enemies的最后一个元素上

不要忘记: 在run()中调用enterAction()的下面调用repaint()方法重画

7.子弹入场:

1) 子弹是由英雄机发射出来的,所以在Hero中设计shoot()生成子弹对象

2) 子弹入场为定时发生的,所以在run()中调用shootAction()实现子弹入场

在shootAction中:

每300毫秒,获取子弹数组对象bs,bullets扩容,将bs追加到bullets的末尾

8.飞行物移动:

1) 飞行物移动为派生类所共有的行为,所以在超类FlyingObject中设计抽象方法step()移动,派生类中重写

2) 飞行物移动为定时发生的,所以在run()中调用 stepAction()实现飞行物移动

在stepAction中:

天空动,遍历敌人敌人动,遍历子弹子弹动

9.英雄机随着鼠标移动:

1) 英雄机随着鼠标动为英雄机的行为,所以在Hero中设计moveTo()实现英雄机随着鼠标动

2) 英雄机随着鼠标移动为事件触发的,所以在侦听器中重写mouseMoved()鼠标移动事件

在mouseMoved()中:

获取鼠标的x和y坐标,调用Hero的moveTo()方法

10.删除越界的敌人和子弹:

1) 在FlyingObject中设计outOfBounds()检测敌人是否越界

在Bullet中重写outOfBounds()检测子弹是否越界

2) 删除越界的敌人和子弹为定时发生的,所以在run中调用outOfBoundsAction()删除越界的敌人和子弹

在outOfBoundsAction()中:

声明不越界敌人/子弹数组,遍历enemies/bullets数组,判断若不越界,则将对象装到不越界数组中

最后将不越界数组复制到enemies/bullets数组中

11.接口设计:

              1)设计Enemy得分接口,Airplane和BigAirplane实现Enemy接口,击中小敌机/大敌机,得1分/3分.

               2)设计Award奖励接口,Bee实现Award接口,击中小蜜蜂随机奖励:生命值加一/火力值加40双倍火力

12.敌人与子弹的碰撞:

1) 在 FlyingObject中设计hit()检测敌人与子弹的碰撞、goDead()飞行物去死

在Hero中设计addLife()增命、addFire()增火力

2) 敌人与子弹的碰撞为定时发生的,所以在run()中调用bulletBangAction()实现敌人与子弹的碰撞

在bulletBangAction()中:

遍历子弹得子弹,遍历敌人得敌人,判断若都活着并且撞上了:

子弹去死、敌人去死

判断若为Enemy分,则玩家得分

若为Award奖励,则英雄机得奖励

13.画分和画命:

1) 在Hero中设计getLife()获取英雄机的命数

2) 在World类的paint()中: 画分和画命

14.敌人与英雄机的碰撞:

1) 借用FlyingObject中的hit()碰撞检测、goDead()去死

在Hero中设计subtractLife()减命、clearFire()清空火力值

2) 敌人与英雄机的碰撞为定时发生的,所以在run()中调用heroBangAction()实现敌人与英雄机的碰撞

在heroBangAction中:

遍历敌人得敌人,判断若都活着并且撞上了:

敌人去死、英雄机减命、英雄机清空火力值

15.检测游戏结束:

1) 借助于Hero的getLife()获取命数

2) 检测游戏结束为定时发生的,所以在run()中调用checkGameOverAction()检测游戏结束

在checkGameOverAction()中:

判断若英雄机的命数<=0,表示游戏结束,则……

16.画状态:

1) 在World中设计四个状态常量,同时设计state变量表示当前状态,默认为START(启动状态)

在Images中设计start、pause、gameover三个状态图片,在static块中赋值

在World类的paint()中设计在不同的状态下画不同的图片

2) 设计run()中那一堆action,仅在运行状态时执行

设计英雄机随着鼠标动,仅在运行状态时执行

3) 重写mouseClicked()鼠标点击: 启动状态时变运行状态,游戏结束状态时先清理现场,再变启动状态

重写mouseExited()鼠标移出: 运行状态变为暂停状态

重写mouseEntered()鼠标移入: 暂停状态变为运行状态

(注:每一次功能的实现都要不断测试调试,防止报错.)

代码实现:

FlyingObject:

package cn.tedu.shoot;
import java.awt.image.BufferedImage;
import java.util.Random;

/**飞行物*/
public abstract class FlyingObject {
	public static final int LIFE = 0;  //活着的
	public static final int DEAD = 1;  //死了的
	public static final int REMOVE = 2; //删除的
	protected int state = LIFE;//当前状态(默认为活着的
	
	protected int width;//宽
	protected int height;//高
	protected int x;     //x 坐标
	protected int y;     //y 坐标
	
	/**专门给小敌机 ,大敌机,小蜜蜂提供的 */
	public FlyingObject(int width,int height){//传2个参是因为敌人只有width 和height 不一样
		this.width=width;
		this.height=height;
		Random rand =new Random();//随机数对象
		x =rand.nextInt(World.WIDTH-width);//0到(窗口宽-敌机宽)的随机数
		y=-height;//负的小敌机的高
		
	}
	
	/**专门给 英雄机, 天空 ,子弹提供*/
	public FlyingObject(int width,int height,int x,int y){//传四个参是因为他们的width,height,x,y都不一样
		this.width=width;
		this.height=height;
		this.x=x;
		this.y=y;
		
	}
	/**飞行物移动*/
	public abstract void step();
	
	/**获取对象的图片方法 */
	public abstract BufferedImage getImage();
	//公开 抽象  返回 值图片
	
	/**判断对象是否活着*/
	public boolean isLife(){	
		return state ==LIFE;//当前状态为LIFE,表示对象是活着的返回true 否则false
	}
	
	/**判断对象是否死了着*/
	public boolean isDead(){	
		return state ==DEAD;//当前状态为DEAD,表示对象是死着的返回true 否则false
	}
	
	/**判断对象是否删除的*/
	public boolean isRemove(){	
		return state ==REMOVE;//当前状态为REMOVE,表示对象是删除的返回true 否则false
	}
	
	/**检测敌人是否越界*/
	public boolean outOfBounds(){
		return this.y>= World.HEIGHT;//敌人的y大于等于窗口的 高 即为越界了
	}
	
	/**判断检测敌人 与 子弹/ 英雄机  this:敌人  other :子弹/英雄机*/
	public boolean hit(FlyingObject other){
		int x1 = this.x - other.width;//x1:敌人的x- 子弹/英雄机的宽
		int x2 = this.x + this.width; //x2: 敌人的x+敌人的width
		int y1 = this.y - other.height;//y1: 敌人的y - 子弹/英雄机的高
		int y2 = this.y + this.height;// y2: 敌人的 y + 敌人的高
		int x = other.x;
		int y = other.y;
		// x在x1 和 x2之间 并且 y在y1和y2之间  即为装上了
		return x>=x1 && x<=x2 && y>=y1 &&y<=y2;
	}
	
	/**飞行物去死*/
	public void goDead(){
		state = DEAD;//将当前状态修改为 DEAD死
	}
	
}

Airplane:

package cn.tedu.shoot;

import java.awt.image.BufferedImage;

/** 小敌机 是飞行物,也能得分*/
public class Airplane extends FlyingObject implements Enemy{
	
	private int speed;//移动速度
	
	/**构造方法*/ //Airplane a=new Airplane
	public Airplane(){
		super(48,50);
		speed=2;
	}
	
	/**重写 step() 移动*/
	public void step(){
		y+=speed;
	}

	private int index=1;//爆破图的下标
	/**重写 getImage() 获取图片方法*/
	public  BufferedImage getImage(){//每10毫秒走一次
		if(isLife()){//活着的
			return Images.airs[0];//返回airs第一张图片
		}else if(isDead()){//死了的
			BufferedImage img = Images.airs[index++];
			if(index==Images.airs.length){
				state = REMOVE;
			}
			return img;
			/*
			 * index= 1;
			 * 10M airs[1] index=2 返回airs[1]
			 * 20M airs[2] index=3 返回airs[2]
			 * 30M airs[3] index=4;返回airs[3]
			 * 40M airs[4] index=5(REMOVE) 返回airs[4]
			 * 50M  因为REMOVE状态 ,所以不走isDead()里面了,直接返回null 
			 */
		}
		return null;//删除状态时,不返回图片
	}
	
	/**重写getScore()得分方法*/
	public int getScore(){
		return 1;//打掉小敌机,玩家得1分;
	}

}

BigAirplane

package cn.tedu.shoot;

import java.awt.image.BufferedImage;

/** 大敌机 是飞行物,也能得分*/
public class BigAirplane extends FlyingObject implements Enemy{
	
	private int speed;//移动速度 
	
	/**构造方法*/
	public BigAirplane(){
		super(66,89);
		speed=2;
	}
	
	/**重写 step() 移动*/
	public void step(){
		y+=speed;//y+为(向下移动
	}
	
	private int index=1;//爆破图的下标
	/**重写 getImage() 获取图片方法*/
	public  BufferedImage getImage(){//每10毫秒走一次
		if(isLife()){//活着的
			return Images.bairs[0];//返回bairs第一张图片
		}else if(isDead()){//死了的
			BufferedImage img = Images.bairs[index++];
			if(index==Images.bairs.length){
				state = REMOVE;
			}
			return img;
		}
		return null;//删除状态时,不返回图片
	}
	
	/**重写getScore()得分方法*/
	public int getScore(){
		return 3;//打掉小敌机,玩家得3分;
	}
	
}

Bee:

package cn.tedu.shoot;

import java.awt.image.BufferedImage;
import java.util.Random;

/** 小蜜蜂 是飞行物, 也是奖励*/
public class Bee extends FlyingObject implements Award{
	
	private int xSpeed;//x坐标移动速度
	private int ySpeed;//y坐标移动速度
	private int awardType;//奖励类型
	
	/**构造方法*/
	public Bee(){
		super(60,51);
		xSpeed=1;
		ySpeed=2;
		Random rand =new Random();//随机数对象
		awardType=rand.nextInt(2);//0-1之内的随机数
	}

	/**重写 step() 移动*/
	public void step(){
		x+=xSpeed;//x+(向左向右)
		y+=ySpeed;//y+一定向下
		//若x<=0  或者 x>=窗口宽-小蜜蜂宽,说明
		if(x<=0||x>=World.WIDTH-this.width){
			xSpeed*=-1;//切换方向(正变负 ,负变正)
		}
	}
	
	private int index=1;//爆破图的下标
	/**重写 getImage() 获取图片方法*/
	public  BufferedImage getImage(){//每10毫秒走一次
		if(isLife()){//活着的
			return Images.bees[0];//返回airs第一张图片
		}else if(isDead()){//死了的
			BufferedImage img = Images.bees[index++];
			if(index==Images.bees.length){
				state = REMOVE;
			}
			return img;
		}
		return null;//删除状态时,不返回图片
	}
	
	/**重写getAwardType()获取奖励类型*/
	public int getAwardType(){
		return awardType;//返回奖励类型
	}
	
}

Hero:

package cn.tedu.shoot;

import java.awt.image.BufferedImage;

/**英雄机:是飞行物*/
public class Hero extends FlyingObject {
	
	private int life;//生命
	private int fire;//火力值
	
	/**构造方法*/
	public Hero(){
		super(97,139,140,400);
		life=3;
		fire=0;
	}
	
	/**重写 step() 移动*/
	public void step(){
		
	}
	
	private int index=0;
	/**重写getImage方法*/
	public BufferedImage getImage(){
		if(isLife()){//若活着
			return Images.heros[index++%Images.heros.length];//heros[0]和heros[1]之间来来回回切换
		}                             //写活 数组长度
		return null;保证程序一定有返回值
	}
	
	
	/**英雄机发射子弹(生成子弹对象)*/
	public Bullet[] shoot(){	
		int xStep = this.width/4;//1/4英雄级的宽
		int yStep = 20; //固定20
		if(fire>0){//双
			Bullet[] bs= new Bullet[2];//2发子弹
			bs[0]= new Bullet(this.x+1*xStep,this.y-yStep);
			bs[1]= new Bullet(this.x+3*xStep,this.y-yStep);
			fire-=2;//发射一次双倍火力 则火力值减2
			return bs;
		}else{//单倍火力
			Bullet[] bs= new Bullet[1];//1发子弹
			// x: 英雄级x+2/4英雄机的宽  y:英雄机的y-固定20
			bs[0]= new Bullet(this.x+2*xStep,this.y-yStep);
			return bs;
		}		
	}
	
	/**英雄机随着鼠标动           x/y 为鼠标坐边*/
	public void  moveTo(int x,int y){
		this.x = x-this.width/2;//英雄机的x = 鼠标x- 1/2英雄机的宽
		this.y = y-this.height/2;英雄机的y = 鼠标x- 1/2英雄机的高
	}
	
	/**英雄机增命*/
	public void addLife(){
		life++;//命数增1
	}
	/**获取英雄机命*/
	public int getLife(){
		return life;//获取命
	}
	/**英雄机减命*/
	public void subtractLife(){
		life--;//命数减1
	}
	/**英雄机增火力值*/
	public void addFire(){
		fire+=40;//火力值增40
	}
	/***/
	public void clearFire(){
		fire=0;//火力值归0
	}
	
}

Sky:

package cn.tedu.shoot;
/**天空  是飞行物*/

import java.awt.Image;
import java.awt.image.BufferedImage;
public class Sky extends FlyingObject{
      //成员变量
	
	private int speed;//移动速度
	private int y1;//第二张图片的y坐标
	
	/**构造方法*/
	public Sky(){
		super(World.WIDTH,World.HEIGHT,0,0);
		speed=1;
		y1=-World.HEIGHT;
		
	}
	
	/**重写 step() 移动*/
	public void step(){
		y+=speed;//y+向下
		y1+=speed;//y1+向下
		if(y>=World.HEIGHT){//y>=窗口高,说明移除窗口
			y=-World.HEIGHT;//则设置y为负的窗口的高(挪到最上面去)
		}
		if(y1>=World.HEIGHT){//y1>=窗口高,说明移除窗口
			y1=-World.HEIGHT;//则设置y1为负的窗口的高(挪到最上面去)
		}
	}
	
	/**重写 getImage() 获取图片方法*/
	public  BufferedImage getImage(){
		return Images.sky;
	}
	
	/**获取天空y1坐标*/
	public int getY1(){
		return y1;//返回y1坐标
	}
}

Bullet: 

package cn.tedu.shoot;

import java.awt.image.BufferedImage;

/** 子弹 是飞行物*/
public class Bullet extends FlyingObject {
	
	private int speed;//移动速度
	
	/**构造的方法*/
	public Bullet(int x,int y){//Bullet b=new Bullet(100,200);
		super(8,20,x,y);
		speed=3;
	}

	/**重写 step() 移动*/
	public void step(){
		y-=speed;//y-为(向上移动
	}
	/**重写 getImage() 获取图片方法*/
	public  BufferedImage getImage(){
		if(isLife()){
			return Images.bullet;//活着
		}else if(isDead()){
			state=REMOVE;//若死了
		}
		return null;
	}
	
	/**重写outofBounds()--检测子弹是否越界*/
	public boolean outOfBounds(){
		return this.y<= - this.height;//敌人的y大于等于窗口的 高 即为越界了
	}
	
}

Images:

package cn.tedu.shoot;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
/**	图片工具类*/
public class Images {
   //公开的 静态的   数据类型 图片   变量名
	public static BufferedImage sky;//天空图片
	public static BufferedImage bullet;//子弹图片
	public static BufferedImage[] heros;//英雄图片
	public static BufferedImage[] airs;//小敌机图片
	public static BufferedImage[] bairs;//大敌机图片
	public static BufferedImage[] bees;//小蜜蜂图片
	
	public static BufferedImage start;//启动图
	public static BufferedImage pause;//暂停图
	public static BufferedImage gameover;//游戏结束图
	
	static{//初始化静态图片
		sky = readImage("background.png");
		bullet = readImage("bullet.png");
		heros =new BufferedImage[2];//两张图片
		heros[0]=readImage("hero0.png");
		heros[1]=readImage("hero1.png");
		
		airs=new BufferedImage[5];
		bairs=new BufferedImage[5];
		bees=new BufferedImage[5];
		
		airs[0]=readImage("airplane1.png");
		bairs[0]=readImage("bigairplane1.png");
		bees[0]=readImage("bee1.png");
		for(int i=1;i<airs.length;i++){
			airs[i]=readImage("bom"+i+".png");
			bairs[i]=readImage("bom"+i+".png");
			bees[i]=readImage("bom"+i+".png");
		}
		
		start = readImage("start.png");
		pause = readImage("pause.png");
		gameover = readImage("gameover.png");
	}
	
	/**读取图片 fileName:图片名字*/
	public static BufferedImage readImage(String fileName){
		try{//与FlyingObject同包中读图片
			BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName));
			return img;
		}catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
}

Award:

package cn.tedu.shoot;
/**奖励接口*/
public interface Award {
	public int FIRE = 0;//火力值  默认..实际public static final int FIRE
	public int LIFE = 1;//命名  ..实际public static final int LIFE
	
	/**获取奖励类型(0 或1)*/
	public int getAwardType();
}

Enemy:

package cn.tedu.shoot;
/**得分接口*/
public interface Enemy {
	/**得分方法*/
	public int getScore();
}

World:

package cn.tedu.shoot;
import java.awt.event.MouseAdapter;//侦听器
import java.awt.event.MouseEvent;
import javax.swing.JFrame;//画框
import javax.swing.JPanel;//画板
import java.awt.Graphics;//绘制
import java.util.Random;
import java.util.Arrays;
import java.util.Timer;//定时器
import java.util.TimerTask;//定时任务
/** 整个窗口 */
public class World extends JPanel{// 测试类 窗口
	/**把游戏界面窗口宽 窗口高固定值*/
	public static final int WIDTH=400;//窗口宽
	public static final int HEIGHT=700;//窗口高
	
	public static final int START = 0;  //启动状态
	public static final int RUNNING =1; //运行状态
	public static final int PAUSE = 2;  //暂停状态
	public static final int GAME_OVER = 3;//游戏结束状态
	private int state = START;//当前状态
	
	/**创建游戏界面对象 窗口出现对象*/
	private Sky sky=new Sky();//天空对象
	private Hero hero=new Hero();//英雄机对象
	private FlyingObject[] enemies={};//敌人(小敌机,大敌机,小蜜蜂)数组
	private Bullet[] bullets={};//子弹数组
	
	/**创建敌人(小敌机 大敌机 小蜜蜂)对象*/
	public FlyingObject nextOne(){
		Random rand = new Random();//随机对象
		int type = rand.nextInt(20);//0-19
		if(type<5){//0-4时  返回小敌机
			return new Bee();
		}else if(type<12){//5-11返回小敌机
			return new Airplane();
		}else{//12到19生成大敌机
			return new BigAirplane();
		}
	}
	//敌人入场, 子弹入场 ,飞行物移动.
	
	private int enterIndex= 0;
	/**敌人(小敌机 大敌机 小蜜蜂)对象*/
	public void enterAction(){//没10毫秒走一次
		enterIndex++;//每10毫秒增1
		if(enterIndex%40==0){//每400(40*10)毫秒走一次
			FlyingObject obj = nextOne();//获取敌人数组
			enemies = Arrays.copyOf(enemies, enemies.length+1);//扩容
			enemies[enemies.length-1] = obj;//将敌人对象添加到最后一个元素上
		}
	}
	
	private int shootIndex=0;
	/**子弹入场*/
	public void shootAction(){//每10毫秒走一次
		shootIndex++;//每10毫秒增1
		if(shootIndex%30==0){//每300(30*10)毫秒走一次
			Bullet[] bs=hero.shoot();//获取英雄机发射出来的子弹对象
			bullets = Arrays.copyOf(bullets, bullets.length+bs.length);//扩容(bs长度为几就扩大几个容量)
			System.arraycopy(bs,0,bullets,bullets.length-bs.length,bs.length);//数组的追加			
		}
	}
	
	/**飞行物移动*/
	public void stepAction(){//每10毫秒
		sky.step();//天空动
		for(int i=0;i<enemies.length;i++){//遍历所有敌人
			enemies[i].step();//敌人移动
		}
		for(int i=0;i<bullets.length;i++){//遍历子弹
			bullets[i].step();//子弹移动
		}
		
	}
	
	/**删除越界敌人和子弹*/
	public void outOfBoundsAction(){//每10毫秒走一次
		int index=0;//1)不越界敌人数组下标 2)不越界敌人个数
		FlyingObject[] enemyLives = new FlyingObject[enemies.length];
		for(int i= 0;i<enemies.length;i++){//遍历所有敌人
			FlyingObject f = enemies[i];//获取每个敌人
			if(!f.outOfBounds() && !f.isRemove()){//若不越界并且 非 删除状态
				enemyLives[index]=f;//将不越界敌人装到越界敌人数组中
				index++;//1)不越界敌人数组下标增1 2)不越界敌人个数增1
			}
		}
		enemies= Arrays.copyOf(enemyLives, index);//将不越界敌人数组复制到enemies数组
		
		index=0;//1)下标归0 ,2)个数归0
		Bullet[] bulletLives = new Bullet[bullets.length];//不越界子弹数组
		for(int i=0;i<bullets.length;i++){
			Bullet b=bullets[i];
			if(!b.outOfBounds() && !b.isRemove()){
				bulletLives[index]=b;
				index++;
			}
		}
		bullets = Arrays.copyOf(bulletLives, index);
	}
	
	private int score=0;
	/**子弹和敌人撞*/
	public void bulletBangAction(){//每10毫秒走一次
		for(int i=0;i<enemies.length;i++){
			FlyingObject f = enemies[i];
			for(int j=0;j<bullets.length;j++){
				Bullet b = bullets[j];
				if( f.isLife() && b.isLife() && f.hit(b)){
					f.goDead();
					b.goDead();
					if( f instanceof Enemy){//撞敌人得分(所有实现Enemy接口的
						Enemy e = (Enemy)f;//对象多态 强转  将被转对象强转为接口
						score +=e.getScore();//调用接口 玩家得分
					}
					if( f instanceof Award){//若被撞对象为奖励(所有实现Award接口的
						Award a = (Award)f;//将被撞对象强转为奖励接口
						int type = a.getAwardType();//获取奖励类型
						switch(type){
						case Award.FIRE://若奖励类型为火力
							hero.addFire();//则英雄机得火力
							break;
						case Award.LIFE://若奖励类型为命
							hero.addLife();//则英雄机得命
							break;
						}
					}
				}
			}
		}
	}
	
	/**英雄机与敌人撞*/
	public void heroBangAction(){//每10个毫秒走一次
		for(int i=0;i<enemies.length;i++){
			FlyingObject f=enemies[i];//获取每一个敌人
			if( f.isLife() && hero.isLife() && f.hit(hero)){//都活着 ,并且撞上了
				f.goDead();//敌人去死
				hero.subtractLife();//减命
				hero.clearFire();//减火力
			}
		}
	}
	
	/**检测游戏结束*/
	public void checkGameOverAction(){//每10毫秒走一次
		if(hero.getLife() <=0){//若英雄机命数<=0,表示游戏结束
			state = GAME_OVER;//修改当前状态为游戏结束状态
		}
	}
	/**启动程序的执行*/
	public void action() {// 测试代码
		MouseAdapter m = new MouseAdapter(){
	    /**重写 mouseMoved()鼠标移动事件*/
		public void mouseMoved(MouseEvent e){
			if(state == RUNNING){//仅在运行状态时 执行
				int x = e.getX();//获取鼠标x坐标
				int y = e.getY();//获取鼠标y坐标
				hero.moveTo(x, y);//英雄机随着鼠标移动
				}
			}
		/**重写 mouseClicked()鼠标点击事件*/
		public void mouseClicked(MouseEvent e){//
			switch(state){//根据当前状态作不同处理
			case START://启动变运行
				state = RUNNING;//则将状态修改为运行
				break;
			case GAME_OVER://结束变启动  游戏结束状态时
				score = 0;
				sky = new Sky();
				hero = new Hero();
				enemies = new FlyingObject[0];
				bullets = new Bullet[0];
				state = START;//则将状态修改为启动状态
				break;
			}
		}
		/**重写 mouseExited()鼠标移除事件*/
		public void mouseExited(MouseEvent e){
			if(state==RUNNING){//运行状态时
				state = PAUSE;//变为暂停状态
			}
		}
		/**重写mouseEntered()鼠标移入事件*/
		public void mouseEntered(MouseEvent e){
			if(state==PAUSE){//暂停状态
				state= RUNNING;//变为运行状态
			}
		}
		
		};//侦听器对象
		this.addMouseListener(m);//将侦听器装到面板上
		this.addMouseMotionListener(m);//将侦听器装到面板上

		Timer timer = new Timer();//定时器对象
		int interevl =10;//定时间隔 (每10毫秒走一次
		timer.schedule(new TimerTask(){
			public void run(){//定时干的那些事---10毫秒走一次
				if(state==RUNNING){//仅在运行状态下执行
					enterAction();//敌人入场
					shootAction();//子弹入场
					stepAction();//飞行物移动
					outOfBoundsAction();//删除越界子弹和敌人
					System.out.println(enemies.length+","+bullets.length);
					bulletBangAction();//子弹与敌人相撞
					heroBangAction();//英雄机与敌人碰撞
					checkGameOverAction();//检测游戏结束
					
				}
				
				repaint();  //重画(重新调用paint方法)
			}
		},interevl ,interevl );
	}
	
	
	/**重写paint 方法  g:画笔*/
	public void paint(Graphics g){//每10毫秒遍历
		g.drawImage(sky.getImage(),sky.x,sky.y,null);//画天空
		g.drawImage(sky.getImage(),sky.x,sky.getY1(),null);//画天空第二张图
		
		g.drawImage(hero.getImage(),hero.x,hero.y,null);//画英雄机
		for(int i=0;i<enemies.length;i++){//遍历所有敌人
			FlyingObject f =enemies[i];//获取所有敌人
			g.drawImage(f.getImage(),f.x,f.y,null);
		}
		for(int i=0;i<bullets.length;i++){
			Bullet b = bullets[i];
			g.drawImage(b.getImage(),b.x,b.y,null);
		}
		
		g.drawString("SCORE:"+score,10,25);//画分
		g.drawString("LIFE:"+hero.getLife(),10,45);//画命
		
		switch(state){//根据当前不同的状态来画不同的图
		case START://启动状态,画启动图
			g.drawImage(Images.start,0,0,null);
			break;
		case PAUSE://暂停状态,画暂停图
			g.drawImage(Images.pause,0,0,null);
			break;
		case GAME_OVER://游戏结束状态,画结束图
			g.drawImage(Images.gameover,0,0,null);
			break;
		}
	}
	
	public static void main(String[] args) {
		JFrame frame = new JFrame();
		World world = new World();
		frame.add(world);
		
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(WIDTH,HEIGHT);
		frame.setLocationRelativeTo(null); 
		frame.setVisible(true); //1)设置窗口可见 
		                       //2)尽快的调用一个方法paint()方法
		world.action();//测试代码   启动程序的执行
		
	}

}

 

 

 

 

 

 

 

 

:
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值