【经典游戏】Java实现飞机大战小游戏

25 篇文章 11 订阅 ¥29.90 ¥99.00

【引言】

90、00后的童年是游戏机,当时的飞机大战,一度风靡全球。

 经典项目java实现飞机大战射击游戏资源-CSDN文库

一、游戏设计

实现飞机大战游戏是一个很有趣的项目,可以帮助你学习和练习 Java 编程的各种方面,包括面向对象设计、图形界面编程等。下面是一个详细的分析,涵盖了设计步骤思路和具体功能:

1、设计步骤思路:
  • 游戏框架搭建

    • 创建一个 Java 项目。
    • 使用 Java GUI 库(如Swing或JavaFX)来构建游戏界面。
  • 设计游戏元素

    • 飞机:玩家飞机和敌方飞机,分别有不同的属性(速度、生命值等)。
    • 子弹:玩家飞机和敌方飞机发射的子弹。
  • 游戏逻辑设计

    • 碰撞检测:检测飞机和子弹之间的碰撞。
    • 得分系统:根据击败敌机数量计算得分。
  • 用户交互

    • 键盘控制:玩家通过键盘控制飞机移动和发射子弹。
    • 鼠标控制:可以使用鼠标来控制飞机或者发射子弹。
  • 游戏流程

    • 游戏开始界面:包括开始游戏和退出游戏选项。
    • 游戏进行界面:显示飞机、敌机、得分等信息。
    • 游戏结束界面:显示得分和重新开始游戏选项。
2、具体功能:
  • 飞机移动

    • 玩家飞机随着键盘操作左右移动,避开敌机和敌方子弹。
    • 敌机在屏幕顶部生成并向下移动,玩家需要躲避它们的攻击。
  • 发射子弹

    • 玩家飞机可以发射子弹,击中敌机可以得分。
    • 敌机也可以发射子弹,玩家需要躲避或击毁它们。
  • 碰撞检测

    • 当玩家子弹击中敌机或者敌机子弹击中玩家飞机时,进行碰撞检测,减少生命值或者销毁飞机。
  • 得分计算

    • 根据击败敌机数量来计算得分,可以在界面上显示当前得分。
  • 游戏状态管理

    • 包括游戏开始、进行中和结束等状态的管理,切换不同界面和逻辑。
  • 音效和动画

    • 添加背景音乐、射击音效和爆炸动画等,增强游戏体验。
  • 游戏结束条件

    • 当玩家飞机生命值耗尽或者敌机到达底部时,游戏结束,显示得分和重新开始选项。
  • 优化和扩展

    • 优化游戏性能,处理大量敌机和子弹的情况。
    • 可以扩展游戏内容,如增加不同类型的敌机、道具等。

通过这些步骤和功能,你可以逐步实现一个简单但完整的飞机大战游戏。

二、功能设计

1.1、飞机大类

1.2 构造器

public class Plane extends PlaneWarObject {
	public double speed = 10;// 速度
	public boolean left, up, right, down;
	public int blood;// 血量
	public int level;// 等级
	public int type;// 等级
	public int score = 0;// 积分

	/**
	 * 无参构造
	 */
	public Plane() {
		super();
	}

	public Plane(PlaneWarClient pwc, boolean good) {
		this.fire = false;
		this.x = (Constant.GAME_WIDTH - width) / 2;
		this.y = Constant.GAME_HEIGHT - height;
		this.img = ImageUtil.images.get("myPlane_01_01");
		this.width = img.getWidth(null);
		this.height = img.getHeight(null);
		this.pwc = pwc;
		this.good = good;
		this.blood = Constant.MYPLANE_MAX_BOOLD;
		this.level = 1;
		this.type = 1;
	}

	/**
	 * 带参构造
	 */

	public Plane(int x, int y, Image img, int width, int height) {
		super();
		this.x = x;
		this.y = y;
		this.img = img;
		this.width = width;
		this.height = height;
	}

	public Plane(int x, int y, String imageName) {
		super();
		this.x = x;
		this.y = y;
		this.img = ImageUtil.images.get(imageName);
		this.width = img.getWidth(null);
		this.height = img.getHeight(null);
	}

	public Plane(int x, int y, Image img) {
		super();
		this.x = x;
		this.y = y;
		this.img = img;
		this.width = img.getWidth(null);
		this.height = img.getHeight(null);
	}


}

1.3 内部方法

 * 是否开火
	 */
	public boolean fire;

	/**
	 * 我方飞机发子弹的方法
	 */
	public void fire() {
		// pwc.musics.add(mu);
		new MusicUtil("fire3").start();
		Missile missile = new Missile(pwc, this.x, this.y, "myPlane_missile_0" + type + "_0" + level, good);
		missile.x += (this.width - missile.width) / 2;
		missile.y -= height;
		pwc.missiles.add(missile);
	}

	boolean superFire;

	/**
	 * 超级子弹
	 */
	public void superFire() {
		if (superFireCount > 0) {
			int num = 24;
			for (int i = 1; i <= num; i++) {
				Missile missile = new Missile(pwc, this.x, this.y, "myPlane_missile_super", 6, good);
				int r = (int) (Math.sqrt(width * width + height * height) / 2);
				int theta = 360 * i / num;
				missile.setTheta(theta);
				missile.x = (int) (missile.x + (width / 2 + r * Math.sin(Math.toRadians(theta)) - missile.width / 2));
				missile.y = (int) (missile.y
						- ((r * Math.cos(Math.toRadians(theta)) - height / 2 + missile.height / 2)));
				pwc.missiles.add(missile);
			}
			superFireCount--;
		}
		superFire = false;
	}

	/**
	 * 判断是否存活
	 */
	public boolean live = true;

	@Override
	public void move() {
		if (left) {
			x -= speed;
		}
		if (right) {
			x += speed;
		}
		if (up) {
			y -= speed;
		}
		if (down) {
			y += speed;
		}
		outOfBounds();
		if (fire)
			fire();
		if (superFire)
			superFire();
	}

	@Override
	public void draw(Graphics g) {
		img = ImageUtil.images.get("myPlane_0" + type + "_0" + level);
		if (blood <= 0 && live) {
			live = false;
			Explode ex = new Explode(pwc, x, y);
			ex.x += (width - ex.width) / 2;
			ex.y += (height - ex.height) / 2;
			pwc.explodes.add(ex);
			pwc.enemyPlanes.clear();
			pwc.missiles.clear();
			pwc.items.clear();

		}

		if (live) {
			g.drawImage(img, x, y, null);
			move();
		}
		drawBloodAndScore(g);
	}

	/**
	 * 画血条和积分
	 * 
	 * @param g
	 */
	private void drawBloodAndScore(Graphics g) {
		Image bloodImg = ImageUtil.images.get("myBlood");
		Image blood_blank = ImageUtil.images.get("myBlood_blank");
		Image scoreImg = ImageUtil.images.get("score");
		int i = 0;
		g.drawImage(bloodImg, 10, 40, null);
		int num = (int) (((double) ((bloodImg.getWidth(null)) - 56) / (Constant.MYPLANE_MAX_BOOLD))
				* (Constant.MYPLANE_MAX_BOOLD - blood) / blood_blank.getWidth(null));
		for (int j = 0; j < num; j++) {
			g.drawImage(blood_blank, 10 + bloodImg.getWidth(null) - blood_blank.getWidth(null) * (j + 1), 40 + 14,
					null);
		}
		// 画积分
		g.drawImage(ImageUtil.images.get("score"), 10, 40 + bloodImg.getHeight(null) + 12, null);
		g.setFont(new Font("微软雅黑", Font.BOLD, 40));
		g.setColor(Color.WHITE);
		g.drawString(score + "", 10 + scoreImg.getWidth(null) + 10, 40 + bloodImg.getHeight(null) + 50);
	}

	/**
	 * 大招剩余次数
	 */
	public int superFireCount = 0;

	/**
	 * 按下键盘的方法
	 * 
	 * @param e
	 */
	public void keyPressed(KeyEvent e) {
		switch (e.getKeyCode()) {
		case KeyEvent.VK_A:
			left = true;
			break;
		case KeyEvent.VK_S:
			down = true;
			break;
		case KeyEvent.VK_D:
			right = true;
			break;
		case KeyEvent.VK_W:
			up = true;
			break;
		case KeyEvent.VK_J:// 发子弹
			superFire = false;
			fire = true;
			break;
		case KeyEvent.VK_SPACE:// 发超级子弹
			fire = false;
			superFire = true;
			break;
		}
	}

	/**
	 * 松开键盘的方法
	 * 
	 * @param e
	 *            键盘事件
	 */
	public void keyReleased(KeyEvent e) {
		switch (e.getKeyCode()) {
		case KeyEvent.VK_A:
			left = false;
			break;
		case KeyEvent.VK_S:
			down = false;
			break;
		case KeyEvent.VK_D:
			right = false;
			break;
		case KeyEvent.VK_W:
			up = false;
			break;
		case KeyEvent.VK_J:// 发子弹
			fire = false;
			break;
		}
	}

2、敌人出场

创建敌人对象过程中是随机的,有可能是小敌机、大敌机、也有可能是小道具;
工厂方法都是生产对象的;

若方法操作仅仅与参数相关而与对象无关时用静态方法,方法分为工具方法和工厂方法,工厂方法返回值类型为对象。

3、子弹击打方法接口

public class Missile extends PlaneWarObject {
	boolean live;
	int speed;
	int type;
	public Missile() {
		super();
	}

	public Missile(PlaneWarClient pwc, int x, int y, String imageName,boolean good) {
		this.live = true;
		this.x = x;
		this.y = y;
		this.img = ImageUtil.images.get(imageName);
		this.width = img.getWidth(null);
		this.height = img.getWidth(null);
		this.pwc = pwc;
		this.speed=10;
		this.good=good;
	}
	public Missile(PlaneWarClient pwc, int x, int y, String imageName,int type,boolean good) {
		this(pwc, x, y, imageName,good);
		this.type=type;
	}


	public void setTheta(int theta) {
		this.theta = theta;
	}

	private int theta;
	/**
	 * 子弹击打飞机的方法
	 */
	public boolean hitPlane(Plane p){
		if(this.getRectangle().intersects(p.getRectangle())&&this.good!=p.isGood()&&p.live){
			this.live=false;
			if(p.level>=1){
				p.blood-= 10*p.level;
			}else{
				p.blood-= 20;
			}
			pwc.missiles.remove(this);
			return true;
		}else{
			return false;
		}
	}
	/**
	 * 子弹击打飞机的方法
	 */
	public boolean hitPlanes(List<EnemyPlane> enemyPlanes){
		for (EnemyPlane enemyPlane : enemyPlanes) {
			if(this.hitPlane(enemyPlane)){
				return true;
			}
		}
		return false;
	}
	

	/**
	 * 子弹出界
	 */
	private void outOfBounds() {
		if ((x >= (Constant.GAME_WIDTH-width) || x <= 0) || (y >= (Constant.GAME_HEIGHT - height) || y <= 0)) {
			this.live = false;
			this.pwc.missiles.remove(this);
		}
	}

}

4、子弹类型

@Override
	public void move() {
		switch (type) {
		case 100:// 水平平移
			if (x >= (Constant.GAME_WIDTH) || x <= 0 - width) {
				speed = -speed;
			}
			x += speed;
			break;
		case 1:// 水平平移
			x += speed * 3;
			if (x >= (Constant.GAME_WIDTH - width)) {
				speed = -speed;
			}
			break;
		case 2:// 竖直平移
			y += speed * 3;
			break;
		case 3:// 正弦线
			x = (int) (center.x - width + (center.x - width) * Math.sin(theta));
			theta += speed / 10;
			y += speed * 10;
			break;
		case 4:// 余弦线
			x = (int) (center.x - width + (center.x - width) * Math.cos(theta));
			theta += speed / 10;
			y += speed * 10;
			break;
		case 5:// 双曲线
			x = (int) (center.x - width + 50 * 1 / Math.cos(theta));
			y = (int) (center.y - height + 50 * Math.sin(theta) / Math.cos(theta));
			theta += speed / 20;
			break;
		case 6:// 星形线
			x = (int) (center.x - width / 2 + 200 * Math.pow(Math.cos(theta), 3));
			y = (int) (center.y + 200 * Math.pow(Math.sin(theta), 3)) - 200;
			theta += speed / 20;
			break;
		case 7:// 心形线
			x = (int) (center.x + r * (2 * Math.cos(theta + Math.PI / 2) + Math.cos(2 * theta + Math.PI / 2)));
			y = (int) (center.y + r * (2 * Math.sin(theta + Math.PI / 2) + Math.sin(2 * theta + Math.PI / 2)));
			theta += speed;
			break;
		}
		if (type!=100&&random.nextInt(1000) > 995 && live) {
			fire();
		}
		if(type==100&&random.nextInt(1000)>990&&live){
			fire();
		}
	}

三、效果展示

1、游戏

2、拾取道具

3、游戏结束

四、资源获取

经典项目java实现飞机大战射击游戏资源-CSDN文库

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫蜜柚子茶

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值