小游戏——飞机大战(1)

飞机大战

前言

Java的学习来到了线程的阶段,接下来总结一下如何手撸一个线程飞机大战小游戏

到了这个阶段,我们就要有系统的思维了,制作一款这样的游戏,我们需要什么,我们的顺序又是什么。
在这里插入图片描述
首先借用一张图片,来看看我们的设计思路。
话不多说,开始动手。
我们注意到,无论是敌我飞机,还是子弹等等,都是飞行物,那么我们就可以用到继承的方法,写出一个飞行物的父类,之后的其他飞行物子类,都继承自它,然后重写里面的方法即可。

FlyingObject父类

如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
Abstract关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。

这里的飞行物的飞行方法和越界判断也许不一样,但是碰撞规则是一样的,所以我们写了两个abstract方法。

public abstract class FlyingObject {
	protected BufferedImage image;// 图片命名--java包自有的
	protected int width; // 宽
	protected int height; // 高
	protected int x; // x坐标
	protected int y; // y坐标

	// 飞行方法
	public abstract void step();

	// 越界方法
	public abstract boolean outOfBounds();

	// 敌人被子弹撞,传入Bullet类的对象,获取子弹的x,y坐标
	public boolean shootBy(Bullet bullet) {
		// this:敌人 other:子弹
		int x1 = this.x;
		int x2 = this.x + this.width;
		int y1 = this.y;
		int y2 = this.y + this.height;
		int x = bullet.x;
		int y = bullet.y;
		//矩形检测原理
		return x > x1 && x < x2 && y > y1 && y < y2;
	}

}

在我们的游戏中,我们有计分原则,奖励原则,所以我们需要写一个方法,在所有的类中都可以使用,类似于我们的鼠标监听器一样,这里我们就要用到接口

Enemy接口

//攻击敌人得分
public interface Enemy {
	public int getScore();

}

Award接口

  //l击中特殊飞行物获得奖励
public interface Award {
	public static final int DOUBLE_FIRE = 0; // int DOUBLE_FIRE = 0;
	public static final int LIFE = 1; // int LIFE = 1;
	
	// 获取奖励方法
	public int getType();

}

AirPlane类 (敌机)

这里我们继承FlyingObject父类,以及使用我们定义的Enemy接口

public class AirPlane extends FlyingObject implements Enemy {
	private int speed = 2;// 敌机走步的步数
    //构造方法,实例化类的时候自动调用
	public AirPlane() {
		image = ShootGame.airplane;
		width = image.getWidth();
		height = image.getHeight();
		Random rand = new Random();
		x = rand.nextInt(ShootGame.WIDTH - this.width);
		y = -this.height; // y:负的敌机的高

	}

	// 重写 getScore();
	public int getScore() {
		return 5;
	}
    //重写飞行方法
	public void step() {
		y += speed;
	}
    //重写越界方法
	public boolean outOfBounds() {
		return this.y > ShootGame.HEIGHT; // 敌机的y坐标大于窗口的高

	}

}

Bee类(特殊飞行物)

这里我们继承FlyingObject父类,以及使用我们定义的Award接口

//Bee也是飞行物,击中能获取奖励,并且飞行轨迹不定
public class Bee extends FlyingObject implements Award {
	private int xSpeed = 1; // x坐标走步步数
	private int ySpeed = 2; // y坐标走步步数
	private int awardType; // 奖励类型
    //构造器,实例化类时调用
	public Bee() {
		image = ShootGame.bee;
		width = image.getWidth();
		height = image.getHeight();
		Random rand = new Random();
		x = rand.nextInt(ShootGame.WIDTH - this.width);
		y = -this.height;
		awardType = rand.nextInt(2);// 随机生成奖励类型

	}
    //重写获取奖励方法
	public int getType() {
		return awardType;
	}
    //重写飞行方法
	public void step() {
		if (x >= ShootGame.WIDTH - this.width) {
			xSpeed = -1;
		}
		if (x <= 0) {
			xSpeed = 1;
		}
		x += xSpeed;
		y += ySpeed;
	}
    //重写越界方法
	public boolean outOfBounds() {
		return this.y > ShootGame.HEIGHT;
	}
}

Bullet类(子弹)

这里我们继承FlyingObject父类

public class Bullet extends FlyingObject{
    //子弹走步步数,只有y坐标在变,x发射以后不再改变
	private int speed = 3;  
	
	public Bullet(int x,int y){//子弹的坐标随着英雄机的变化而变化		
		image = ShootGame.bullet;
		width = image.getWidth();
		height = image.getHeight();
		this.x = x;
		this.y = y;
	}
	//重写飞行方法
    public void step(){
		y -= speed;
	}
	//重写越界方法
    public boolean outOfBounds(){
		return this.y < -this.height;
	}

}

Hero类(我机)

这里我们继承FlyingObject父类

//英雄机是飞行物
public class Hero extends FlyingObject {
	private int life; // 命
	private int doubleFire; // 火力值
	private BufferedImage[] images; // 图片数组
	private int index; // 协助图片切换

	public Hero() {
		image = ShootGame.hero0;
		width = image.getWidth();
		height = image.getHeight();
		x = 150;
		y = 400;
		life = 3; // 3条命
		doubleFire = 0; // 单倍火力
		images = new BufferedImage[] { ShootGame.hero0, ShootGame.hero1 };
		index = 0;
	}

	public void step() {
		// 每100毫秒切一次,动态感出现
		image = images[index++ / 10 % images.length];
		
	}

	public Bullet[] shoot() {
		int xStep = this.width / 4;
		if (doubleFire > 0) { // 双发
			Bullet[] bullets = new Bullet[2];
			bullets[0] = new Bullet(this.x + 1 * xStep, this.y - 20);
			bullets[1] = new Bullet(this.x + 3 * xStep, this.y - 20);
			doubleFire -= 2; // 发射双倍火力,每次减2,实际就是2倍火力的持续时间
			return bullets;
		} else { // 单发
			Bullet[] bullets = new Bullet[1];
			bullets[0] = new Bullet(this.x + 2 * xStep, this.y - 20);
			return bullets;
		}
	}
    //飞机随鼠标位置移动
	public void moveTo(int x, int y) {
		this.x = x - this.width / 2;
		this.y = y - this.height / 2;
	}

	public boolean outOfBounds() {
		return false; // 英雄机永不越界
	}

	// 加命
	public void addLife() {
		life++;
	}

	// 获取命
	public int getLife() {
		return life;
	}

	public void addDoubleFire() {
		doubleFire += 40;
	}

	// 活力值清零
	public void setDoubleFire(int doubleFire) {
		this.doubleFire = doubleFire;
	}

	// 英雄机撞敌人
	public boolean hit(FlyingObject other) {
		int x1 = other.x - this.width / 2;
		int x2 = other.x + other.width + this.width / 2;
		int y1 = other.y - this.height / 2;
		int y2 = other.y + other.height + this.height / 2;
		int hx = this.x + this.width / 2;
		int hy = this.y + this.height / 2;
		return hx > x1 && hx < x2 && hy > y1 && hy < y2;
	}

	// 减命
	public void subtractLife() {
		life--;
	}
}

以上就是我们的基础类以及接口,完成了以上的准备以后,可以说我们的游戏已经完成了一大半,接下来只需要完成我们的射击规则以及游戏界面,就可以了,游戏的完成,我会放在(2)中,下面先放上截图。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了13 篇原创文章 · 获赞 1 · 访问量 298

猜你喜欢

转载自blog.csdn.net/Alagagaga/article/details/104481121