飞机大战分析及代码

射击游戏分析:
射击游戏需求:
1.所参与的角色:英雄机、子弹、小敌机、大敌机、小蜜蜂、天空
2.角色间的关系:
1)英雄机发射子弹(单倍火力、双倍火力)
2)子弹打敌人(小敌机、大敌机、小蜜蜂),若打上了:
2.1)子弹消失、敌人先爆破再消失
2.2)若打的是小敌机,则玩家得1分
若打的是大敌机,则玩家得3分
若打的是小蜜蜂,则英雄机得奖励(1条命或40火力值)
3)敌人(小敌机、大敌机、小蜜蜂)撞英雄机,若撞上了:
3.1)敌人先爆破再消失
3.2)英雄机减1条命,同时,清空火力值
当英雄机命数为0时,则游戏结束
4)英雄机、子弹、小敌机、大敌机、小蜜蜂在天空上飞

1.设计小敌机数组、大敌机数组、小蜜蜂数组、子弹数组,并测试
2.设计FlyingObject超类,6个对象类继承超类
3.给FlyingObject设计两个构造方法,6个对象类分别调用

1.将小敌机数组、大敌机数组、小蜜蜂数组组合为FlyingObject数组,并测试
2.在6个对象类中重写step()移动
3.画窗口:----在World类中
1)import JFrame+JPanel
2)设计World类继承JPanel
3)将main中的代码Ctrl C+V
4)main中: frame.setSize()的参数修改为400,700

1.给类中成员添加访问控制修饰符
2.设计Images图片工具类

1.设计窗口的宽和高为常量,适当地方做修改
2.画对象:
1)想画对象需要获取对象的图片,每个对象都能获取图片,
意味着获取图片行为为共有行为,所以设计在超类FlyingObject中,
每个对象获取图片的行为都是不一样的,所以设计抽象方法
----在FlyingObject中设计抽象方法getImage()获取对象的图片
2)获取图片时需要考虑对象的状态,那是因为在不同状态下获取的图片是不同的,
因为每个对象都有状态,意味着状态为共有属性,所以设计在超类FlyingObject中
状态一般都设计为常量,同时再设计变量state来表示当前状态
----在FlyingObject中设计LIVE、DEAD、REMOVE常量,state变量
获取图片时需在去判断对象的状态,每个对象都得状态判断,
意味着判断状态为共有行为,所以设计在超类FlyingObject中,
每个对象判断状态的行为都是一样的,所以设计为普通方法
----在FlyingObject中设计isLive()、isDead()、isRemove()判断状态
3)重写getImage()获取对象的图片:
3.1)天空Sky,直接返回sky图片即可
3.2)英雄机Hero,直接返回heros[0]和heros[1]来回切换
3.3)子弹Bullet:
3.3.1)若活着的,直接返回bullet图片即可
3.3.2)若死了的,直接删除(不返回图片)
3.4)小敌机Airplane:
3.4.1)若活着的,直接返回airs[0]图片即可
3.4.2)若死了的,依次返回airs[1]到airs[4]图片,4后删除(不返回图片)
3.5)大敌机BigAirplane:
3.5.1)若活着的,直接返回bairs[0]图片即可
3.5.2)若死了的,依次返回bairs[1]到bairs[4]图片,4后删除(不返回图片)
3.6)小蜜蜂Bee:
3.6.1)若活着的,直接返回bees[0]图片即可
3.6.2)若死了的,依次返回bees[1]到bees[4]图片,4后删除(不返回图片)
4)图片有了,则可以开画了
----在World类中重写paint()方法

if(isLive()){ 活着呢 }else{ 死了的+删除的 }

分支结构使用几路结构:
----不是看要干几件事,而是看有几种情况
若不考虑爆破,状态有两种:
1)活着的
2)删除的
若考虑爆破,状态有三种:
1)活着的
2)死了的(半死不活,需爆破)
3)删除的

1.敌人入场:
1)敌人是由窗口产生的,所以在World类中设计nextOne()生成敌人对象
2)敌人入场为定时发生的,所以在run()中调用enterAction()实现敌人入场
在enterAction()中:
每400毫秒,获取敌人对象obj,enemies扩容,将obj装到enemies最后一个元素上
注意:在run()中调用enterAction()后,还得再调用repaint()方法来重画
2.子弹入场:
1)子弹是由英雄机发射出来的,所以在Hero类中设计shoot()生成子弹对象
2)子弹入场为定时发生的,所以在run()中调用shootAction()实现子弹入场
在shootAction()中:
每300毫秒,获取子弹数组对象bs,bullets扩容,将bs追加到bullets的末尾

1.飞行物移动:
1)飞行物移动为对象共有的行为,所以在FlyingObject中设计抽象方法step(),派生类中重写
2)飞行物移动为定时发生的,所以在run()中调用stepAction()实现飞行物移动
在stepAction()中:
天空动,遍历敌人敌人动,遍历子弹子弹动
2.英雄机随着鼠标移动:
1)英雄机随着鼠标动为英雄机的行为,所以在Hero中设计moveTo()实现英雄机随着鼠标移动
2)英雄机随着鼠标移动为事件触发的,所以在侦听器中重写mouseMoved()鼠标移动事件
在mouseMoved()中:
获取鼠标的x坐标和y坐标,调用moveTo()方法
3.删除越界的敌人和子弹:
1)在FlyingObject中设计isOutOfBounds()判断敌人是否越界
在Bullet中重写isOutOfBounds()判断子弹是否越界
2)删除越界敌人和子弹为定时发生的,所以在run()中调用outOfBoundsAction()删除越界的敌人和子弹
在outOfBoundsAction()中:
遍历所有敌人,判断若越界了,则最后一个敌人替换越界的敌人,缩容
遍历所有子弹,判断若越界了,则最后一个子弹替换越界的子弹,缩容
4.设计EnemyScore得分接口,小敌机和大敌机实现EnemyScore
设计EnemyAward奖励接口,小蜜蜂实现EnemyAward

1.子弹与敌人的碰撞:
1)在FlyingObject中设计isHit()检测碰撞、goDead()飞行物去死
在Hero中设计addLife()增命、addFire()增火力
2)子弹与敌人的碰撞为定时发生的,所以在run()中调用bulletBangAction()实现子弹与敌人的碰撞
在bulletBangAction()中:
遍历子弹得子弹,遍历敌人得敌人,判断若都活着并且还撞上了:
子弹去死、敌人去死
判断若为EnemyScore,则将被撞对象强转为EnemyScore,玩家得分
判断若为EnemyAward,则将被撞对象强转为EnemyAward,获取奖励类型,得奖励
2.画分和画命:
1)在Hero中设计getLife()获取英雄机的命数
2)在World类的paint()中: 画分和画命
3.英雄机与敌人的碰撞:
1)借用FlyingObject中的isHit()检测碰撞、goDead()飞行物去死
在Hero中设计subtractLife()减命、clearFire()清空火力值
2)英雄机与敌人的碰撞为定时发生的,所以在run()中调用heroBangAction()实现英雄机与敌人的碰撞
在heroBangAction()中:
遍历所有敌人得敌人,判断若都活着并且还撞上了:
敌人去死、英雄机减命、英雄机清空火力值

1.检测游戏结束:
1)借用Hero的getLife()获取英雄机的命数
2)检测游戏结束为定时发生的,所以在run()中设计checkGameOverAction()实现检测游戏结束
在checkGameOverAction()中:
判断若英雄机的命数<=0,表示游戏结束了,则…
2.画状态:
1)在World类中设计START、RUNNING、PAUSE、GAME_OVER常量,同时设计state变量表示当前状态
在Images类中设计start,pause,gameover状态图片,并赋值
在World类的paint()中: 设计在不同的状态下画不同的图片
2)设计那一堆action,为仅在运行状态下执行
设计英雄机随着鼠标移动,为仅在运行状态下执行
3)重写mouseClicked()鼠标点击事件:
启动变运行,游戏结束先清理现场再变启动
重写mouseExited()鼠标移出事件:
运行变暂停
重写mouseEntered()鼠标移入事件:
暂停变运行

小敌机:Airplane

  package cn.tedu.shoot;
  import java.awt.image.BufferedImage;
  public class Airplane extends FlyingObject implements EnemyScore{
  private int speed;   //移动速度	
	public Airplane(){  //构造方法
		super(48,50);   //小敌机的宽高
		speed = 2;      //移动速度
	}
	/*重写step()移动*/
	public void step() {
		y+=speed;  //y+向下
	}
	
	private int index = 1;  //爆破图的下标
	/*重写getImage()获取图片*/
	public BufferedImage getImage() {  //每十毫秒走一次
		if(isLive()) {
			return Images.airs[0]; 
		}else if(isDead()) {
			BufferedImage img = Images.airs[index++];  //获取爆破图
			if(index==Images.airs.length) {  //到最后一张了
				state = REMOVE;   //将当前状态修改为REMOVE删除状态
			}
			return img;  //返回爆破图
		}
		return null;  //删除状态不返回图片
		
		/*
		 *                    index=1
		 * 10M  img=airs[1]   index=2   airs[1]
		 * 20M  img=airs[2]   index=3   airs[2]
		 * 30M  img=airs[3]   index=4   airs[3]
		 * 40M  img=airs[4]   index=5   airs[4]
		 *                    (REMOVE)
		 * 50M  不返回图片                   
		 */
	}
	
	public int getScore() {
		return 1; //打掉小敌机玩家得1 分
	}
}

大敌机:BigAirplane

package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class BigAirplane extends FlyingObject implements EnemyScore{
	private int speed;
	public BigAirplane(){
		super(66,89);
		speed = 2;
	}
	public void step() {
		y+=speed;  //y+向下
	}
	
	private int index = 1;  //爆破图的下标
	/*重写getImage()获取图片*/
	public BufferedImage getImage() {  //每十毫秒走一次
		if(isLive()) {
			return Images.bairs[0];  
		}else if(isDead()) {
			BufferedImage img = Images.bairs[index++];  //获取爆破图
			if(index==Images.bairs.length) {  //到最后一张了
				state = REMOVE;   //将当前状态修改为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 EnemyAward{
	private int xSpeed;
	private int ySpeed;
    private int awardType;
    
    public Bee(){
    	super(60,51);
		Random rand = new Random();
		xSpeed = 1;
		ySpeed = 2;
		awardType = rand.nextInt(2);   //0到1之间
		
    }
    public void step() {
    	x+=xSpeed;  //x向左向右
    	y+=ySpeed;  //y+向下
    	if(x<=0 || x>=World.WIDTH-width){          //若x<=0或X>=(窗口宽-蜜蜂宽),表示到头了
			xSpeed*=-1;  //切换方向(正便=变负、负变正)
		}
	}
    
    private int index = 1;  //爆破图的下标
	/*重写getImage()获取图片*/
	public BufferedImage getImage() {  //每十毫秒走一次
		if(isLive()) {
			return Images.bees[0]; 
		}else if(isDead()) {
			BufferedImage img = Images.bees[index++];  //获取爆破图
			if(index==Images.bees.length) {  //到最后一张了
				state = REMOVE;   //将当前状态修改为REMOVE删除状态
			}
			return img;  //返回爆破图
		}
		return null;  //删除状态不返回图片
	}
	
	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;
	}
	
	public void step() {
	}
	
	int index = 0;  //下标
	/*重写getImage()获取图片*/
	public BufferedImage getImage() {   //每十个毫毛走一次
		return Images.heros[index++%Images.heros.length];  //在0到1之间来回切换
		
		/*                   index=0;
		  10M   返 回hero[0]   index=1;
		  20M   返 回hero[1]   index=2;
		  30M   返 回hero[0]   index=3;
		  40M   返 回hero[1]   index=4;
		 */
	}
	
	/*英雄机发射子弹(生成子弹对象)*/
	public Bullet[] shoot() {   
		int xStep = this.width/4;   //1/4英雄机的宽
		int yStep = 2;
		if(fire>0) {   //双倍火力
			Bullet[] bs = new Bullet[2];  //2发子弹
			bs[0] = new Bullet(this.x+1*xStep,this.y-yStep);  //x:英雄机的x+1/4英雄机的宽  y:英雄机的y-固定的20
			bs[1] = new Bullet(this.x+3*xStep,this.y-yStep);  //x:英雄机的x+3/4英雄机的宽  y:英雄机的y-固定的20
			fire-=2;    //发射一次双倍火力,则火力值减2
			return bs;
		}else {   //单倍
			Bullet[] bs = new Bullet[1];  //1发子弹
			bs[0] = new Bullet(this.x+2*xStep,this.y-yStep);  //x:英雄机的x+2/4英雄机的宽  y:英雄机的y-固定的20
			return bs;
		}
	}
	
	/*英雄机随着鼠标移动*/
	public void moveTo(int x,int y) {
		this.x = x-this.width/2;   //英雄机的x=鼠标的x-1/2英雄机的宽
		this.y = y-this.height/2;  //英雄机的y=鼠标的y-1/2英雄机的高
	}
	
	/*英雄机增命*/
	public void addLife() {
		life++;  //命数加1
	}
	
	/*获取英雄机的命*/
	public int getLife() {
		return life;    //返回命数
	}
	/*英雄机减命*/
	public void subtractLife() {
		life--;  
	}
	
	/*清空火力值*/
	public void clearFire() {
		fire=0;  //火力值为零
	}
	
	/*英雄机增火力*/
	public void addFire() {
		fire+=40;   //火力值增40
	}
}

天空:Sky

package cn.tedu.shoot;
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;
	}
	public void step() {
		y += speed;   //y+(向下)
		y1+= speed;   //y+(向下)
		if(y>=World.HEIGHT) {  //若y>=窗口的高,意味着y移出去了
			y=-World.HEIGHT;   //则修改y的值为负的窗口的高(挪到最上面去了)
		}
		if(y1>World.HEIGHT) {  //若y1>=窗口的高,意味着y1一出去了
			y1=-World.HEIGHT;  //则修改y1的值为负的窗口的高(挪到最上面去了)
		}
	}
	/*重写getImage()获取图片*/
	public BufferedImage getImage() {
		return Images.sky;  //直接返回sky图片即可
	}
	
	public int getY1() {
		return 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){   //子弹有许多个,每个子弹的初始坐标都不同
		super(8,20,x,y);
		speed = 3;
	}
	public void step() {
		y-=speed;  //y+向上
	}
	
	/*重写getImage()获取图片*/
	public BufferedImage getImage() {   
		if(isLive()) {
			return Images.bullet;    //直接返回图片
		}else if(isDead()){     //若死了的
			state = REMOVE;    //将状态修改为REMOVE删除状态
		}
		return null;  //死了的和删除的,都不反图片
		/*
		//若活着的,返回bullet 图片
		//若死了的,状态改为删除,同时不返回图片
		//若删除的不返回图片
		*/
	}
	
	/*重写isOutOfBounds()判断子弹是否越界*/
	public boolean isOutOfBounds() {
		return y<=-height;  //敌人的y>=窗口的高,即为越界了
	}
}

超类:FlyingObject

package cn.tedu.shoot;
import java.util.Random;
import java.awt.image.BufferedImage;
/*飞行物*/
public abstract class FlyingObject {
	public static final int LIVE = 0;   //活着的
	public static final int DEAD = 1;   //死了的
	public static final int REMOVE = 2; //删除的
	protected int state = LIVE;   //当前状态默认为活着的
	
	protected int width;   //宽
	protected int height;  //高
	protected int x;       //x坐标
	protected int y;       //y坐标
	
	//专门给小敌机,大敌机,小蜜蜂提供的
	//因为三种敌人的宽高不同,所以数据得写活,自然传参
	//因为三种敌人的x和y坐标相同,所以直接写死,不需要传参
	public FlyingObject(int width,int height){
		this.width=width;
		this.height=height;
		Random rand = new Random();   //随机数对象
		x = rand.nextInt(World.WIDTH-width);  //0到(窗口宽-小敌机宽)之间是随机数
		y = -height;                  //y:负的敌人的高
	}
	
	/*专门给英雄机、天空、子弹提供的*/
	//因为英雄机,天空,子弹的宽高xy都不同,所以数据都得写活,都得传参过来
	public FlyingObject(int width,int height,int x,int y){
		this.width=width;
		this.height=height;
		this.x=x;
		this.y=y;
		
	}	
	public abstract void step();
	/*获取对象的图片*/
	public abstract BufferedImage getImage();
	/*判断是否活着的*/
	public boolean isLive() {
		return state==LIVE;  //当前状态为LIVE则表示为活着的,返回true,否则返回flase
	}
	   /*判断是死了着的*/
	public boolean isDead() { //当前状态为DEAD则表示为活着的,返回true,否则返回flase
		return state==DEAD;
	}
	  /*判断是否删除的*/ 
	public boolean isRemove() { //当前状态为REMOVE则表示为活着的,返回true,否则返回flase
		return state==REMOVE;
	}
	
	/*判断敌人是否越界*/
	public boolean isOutOfBounds() {
		return y>=World.HEIGHT;  //敌人的y>=窗口的高,即为越界了
	}
	
	/*检测敌人与子弹/英雄机的碰撞  this:敌人  other:子弹/英雄机*/
	public boolean isHit(FlyingObject other) {
		int x1 = this.x-other.width;  //x1:敌人的x-子弹/英雄机的宽
		int x2 = this.x+this.width;   //x2:敌人的x+敌人的宽
		int y1 = this.y-other.height; //y1:敌人的y-子弹/英雄机的高
		int y2 = this.y+this.height;  //y2:敌人的y+敌人的高
		int x = other.x;    //x:子弹/英雄机的x
		int y = other.y;    //y:子弹/英雄机的y
		
		return x>=x1 && x<=x2 && y>=y1 && y<=y2;
	}
	
	/*飞行物去死*/
	public void goDead() {
		state = DEAD;  //将当前状态修改为DEAD死了的
	}
}

图片工具类: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 {
		start = readImage("start.png");
		pause = readImage("pause.png");
		gameover = readImage("gameover.png");
		
		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];
		airs[0] = readImage("airplane.png");
		bairs = new BufferedImage[5];
		bairs[0] = readImage("bigairplane.png");
		bees = new BufferedImage[5];
		bees[0] =  readImage("bee.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");
		}
	}
	public static BufferedImage readImage(String fileName){
		try{
			BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName));
			return img;
		}catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
}

得分奖励接口:EnemyScore

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

得命或火力值奖励接口:EnemyAward

package cn.tedu.shoot;
/*奖励接口*/
public interface EnemyAward {
	public int FIRE = 0;  //火力
	public int LIFE = 1;  //命
	
	/*获取奖励类型*/
	public int getAwardType();
}

测试类:World

package cn.tedu.shoot;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Arrays;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
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 < 13) { // 5到12返回小蜜蜂对象
			return new Airplane();
		} else { // 13到19返回大敌机对象
			return new BigAirplane();
		}
	}

	private int enterIndex = 0;
	/* 敌人(小敌机,大敌机,小蜜蜂)入场 */	
    public void enterAction() { // 每10毫秒做一次
		enterIndex++; // 每10毫秒增1
		if (enterIndex % 40 == 0) { // 每400毫秒走一次
			FlyingObject obj = nextOne(); // 获取敌人对象
			enemies = Arrays.copyOf(enemies, enemies.length + 1); // 扩容
			enemies[enemies.length - 1] = obj; // 将obj添加到最后一个元素上
		}
	}

	private int shootIndex = 0; // 子弹入场计数
	/* 子弹入场 */
	public void shootAction() { // 每10毫秒走一次
		shootIndex++; // 每10毫秒走一次
		if (shootIndex % 30 == 0) { // 每300毫秒走一次
			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() {
		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毫秒走一次
		for(int i=0;i<enemies.length;i++) {  //遍历所有敌人
			if(enemies[i].isOutOfBounds() || enemies[i].isRemove()) { //判断是否出界或爆破
				enemies[i] = enemies[enemies.length-1];  //把最后一个敌人放在出界敌人的位置
				enemies = Arrays.copyOf(enemies,enemies.length-1);  //缩容
			}
		}
		for(int i=0;i<bullets.length;i++) {   //遍历所有子弹
			if(bullets[i].isOutOfBounds() || bullets[i].isRemove()) {  //判断是否出界或爆破
				bullets[i] = bullets[bullets.length-1];   //把最后一个子弹放在出界子弹的位置
				bullets = Arrays.copyOf(bullets,bullets.length-1);  //缩容
			}
		}
	}
	
	private int score = 0;   //玩家得分
	/*子弹与敌人的碰撞*/
	public void bulletBangAction() {
		for(int i=0;i<bullets.length;i++) {  //遍历所有子弹
			Bullet b = bullets[i];   //获取每个子弹
			for(int j=0;j<enemies.length;j++) {   //遍历所有敌人
				FlyingObject f = enemies[j];    //获取每个敌人
				if(b.isLive() && f.isLive() && f.isHit(b)) {  //若都活着并且还撞上了 
					b.goDead();   //子弹去死
					f.goDead();   //敌人去死
					
					if(f instanceof EnemyScore) {  //若被撞敌人为分
						EnemyScore es = (EnemyScore)f;  //将被撞敌人强转为得分接口
						score += es.getScore();   //玩家得分
					}
					if(f instanceof EnemyAward) {  //若被撞敌人为奖励
						EnemyAward ea = (EnemyAward)f;   //将被撞敌人强转为奖励接口
						int type = ea.getAwardType();    //获取奖励类型
						switch(type) {    //根据奖励类型来获取不同的奖励
						case EnemyAward.FIRE:  //若奖励类型为火力
							hero.addFire();    //则英雄机增火力
							break;
						case EnemyAward.LIFE:  //若奖励类型为名
							hero.addLife();    //则英雄机增命
							break;
						}
					}
				}
			}
		}
	}
	
	/*英雄机与敌人撞*/
	public void heroBangAction() {  //每10毫秒走一次
		for(int i=0;i<enemies.length;i++) {  //遍历所有敌人
			FlyingObject f = enemies[i];  //获取每个敌人
			if(hero.isLive() && f.isLive() && f.isHit(hero)) {
				f.goDead();  //敌人去死
				hero.subtractLife();  //英雄机减命
				hero.clearFire();   //英雄机清空火力
			}
		}
	}
	
	public void checkGameOverAction() {
		if(hero.getLife()<=0) {   //表示游戏结束了
			state = GAME_OVER;  //将当前状态修改为游戏结束状态
		}
	}
	
	/* 启动程序的执行 */
	public void action() {
		MouseAdapter m = new MouseAdapter() {
			public void mouseMoved(MouseEvent e) {
				if(state==RUNNING) {
					int x = e.getX();  //获取鼠标的x坐标
					int y = e.getY();  //获取鼠标的y坐标
					hero.moveTo(x,y);  //英雄机随着鼠标移动
				}			
			}
			
			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 intervel = 10; // 定时间隔(以毫秒为单位)
		timer.schedule(new TimerTask() {
			public void run() { // 定时器干的事(每十毫秒走一次)
				// 敌人入场 子弹入场 飞行物移动 子弹与敌人碰撞 英雄机与敌人碰撞
				if(state==RUNNING) {   //仅在运行状态下执行
					enterAction();  //敌人(小敌机,大敌机,小蜜蜂)入场
					shootAction();  //子弹入场
					stepAction();   //飞行物移动
					outOfBoundsAction();  //删除越界敌人
					bulletBangAction();   //子弹与敌人碰撞
					heroBangAction();   //英雄机与敌人的碰撞
					checkGameOverAction();  //检测游戏结束
				}				
				repaint(); // 重画 调用repaint() 画笔
			}
		}, intervel, intervel);  //定时计划表
	}
                                 	
	/* 重写paint()画 */
	public void paint(Graphics g) { // 每10毫秒走一次
		g.drawImage(sky.getImage(), sky.x, sky.y, null); // 画天空1
		g.drawImage(sky.getImage(), sky.x, sky.getY1(), null); // 画天空2
		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("LIVE:"+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);
		}
	}

	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); // 设置窗口可见 尽快调用

		world.action();
	}

}
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(){ } /**专门给小敌机、大敌机、小蜜蜂提供的构造方法 */ public FlyingObject(int width,int height){ this.width = width; this.height = height; Random rand = new Random(); x = rand.nextInt(World.WIDTH-width); //x:0到(窗口-小敌机的宽)之间的随机数 y = -height; //y:负的小敌机的高 } /** 专门给英雄机、子弹、天空提供的构造方法 */ public FlyingObject(int width,int height,int x,int y){ this.width = width; this.height = height; this.x = x; this.y = y; } /** 读取图片 */ public static BufferedImage loadImage(String fileName){ try{ BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName)); return img; }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(); } } /** 飞行物移动了 */ public abstract void step(); public abstract BufferedImage getImage(); /** 判断是否活着 */ public boolean isLife(){ return state==LIFE; } /** 判断是否死了的 */ public boolean isDead(){ return state==DEAD; } /** 判断是否删除的 */ public boolean isRemove(){ return state==REMOVE; } /** 画对象 g:画笔 */ public void paintObject(Graphics g){ g.drawImage(getImage(), x, y, null); } /** 检测飞行物是否越界 */ public abstract boolean outOfBounds(); /** 敌人与子弹/英雄机的碰撞 this:敌人 other:子弹或英雄机 */ public boolean hit(FlyingObject other){ int x1 = this.x-other.width; //x1:敌人的x int x2 = this.x+this.width; //x2:敌人的x int y1 = this.y-other.height; //y1:敌人的y int y2 = this.y+this.height; //y2:敌人的y int x = other.x; //x:子弹的x int y = other.y; //y:子弹的y return x>=x1 && x=y1 && y<=y2; } public void goDead(){ state = DEAD; //修改当前状态为死了的 } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值