Java编写飞机大战(超级详细的完整版)--附源码及图片

一、基本介绍

首先,先想想要完成一个飞机大战,需要完成那些步骤呢?

①是不是需要有个界面去显示飞机和子弹之类的组件呢?

这个时候是不是需要去绘制一个界面类呢? 答案是必须的!!!

②既然画完了界面,那界面的上的飞机、子弹、敌机啥的是不是也需要创建一个类去绘制呢?答案也是必须的!!!

在绘制子弹和敌机的时候,需要去考虑敌机遇到子弹爆炸的场景,以及每击毁一架飞机,怎么算我的得分的情况,这些都是需要去考虑的。

通过飞机大战能够学到的知识点有:

①面向对象:其中包括了继承、实现接口以及封装;

②学会使用队列ArrayList进行存储;

③明白如何读取图片,然后将该图片放在窗体上;

④学会使用多线程。

二、源码分析

①先绘制飞机大战的界面类GameMain类。

package FlyV4B;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

public class GameMain {
	
	//窗口的宽度和高度
	static int width = 600;
	static int height = 800;
	
	
	public static void main(String[] args) {
		
		//创建一个窗口的大小
		JFrame frame = new JFrame();
		
		//设置标题
		frame.setTitle("飞机大战");
		
		//设置窗口的大小
		frame.setSize(width, height);
		
		//关闭窗口关闭后JVM终止运行
		frame.setDefaultCloseOperation(3);
		
		//设置窗口居中
		frame.setLocationRelativeTo(null);
		
		//创建JPanel容器
		GamePanel panel = new GamePanel();
		
		//把JPanel添加到窗口中
		frame.add(panel);
		
		//添加鼠标监听器
		frame.addMouseMotionListener(panel);
		
				
		//设置可见
		frame.setVisible(true);
		
		//初始化容器
		panel.init();
	}
}

在界面类中添加鼠标移动监听器,目的是鼠标放到界面上或者按压界面时能够使得飞机进行移动。

②英雄机类–GamePanel类

package FlyV4B;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.List;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class GamePanel extends JPanel implements MouseMotionListener{
	
	//读取英雄机的图片
	ImageIcon heroImage = new ImageIcon("image/hero.png");
	
	//定义一个集合来装所有的敌机
	ArrayList<Enemy> enemys = new ArrayList();
	
	//定义一个队列来装所有的子弹
	ArrayList<Bullet> bullets = new ArrayList();
	
	//定义一个集合来装爆炸的图片
	ArrayList<Bomb> bombs = new ArrayList();
	
	
	
	
	//英雄机的坐标
	int heroX = 300;
	int heroY = 400;
	private int number=0;//分数
	
	public GamePanel() {
		//创建10个敌人
		for(int i=0; i<10; i++){
			enemys.add(new Enemy());
		}
	}
	
	
	//鼠标按下去拖动时调用
	public void mouseDragged(MouseEvent e) {
		System.out.println("鼠标按下去时拖动时调用");
		
		int x = e.getX();//获取鼠标的x
    	int y = e.getY();
    	heroX = x-(heroImage.getIconWidth()/2); //把鼠标的x赋值给英雄机
    	heroY = y-(heroImage.getIconHeight()/2);
    	
    	if(x+heroImage.getIconWidth() > GameMain.width) {
    		heroX = GameMain.width - heroImage.getIconWidth() - 20; 
    	}
    	
    	if(y+heroImage.getIconHeight() > GameMain.height) {
    		heroY = GameMain.height - heroImage.getIconHeight() - 20; 
    	}
    			
    			
    			
    	repaint();//x发生变化后需要重新绘制

		
	}
	
	//鼠标移动时调用
    public void mouseMoved(MouseEvent e) {
    	
    	System.out.println("鼠标放上去时调用");
    	
    	int x = e.getX();//获取鼠标的x值
    	int y = e.getY();//获取鼠标的y值
    	
    	heroX = x-(heroImage.getIconWidth()/2); //把鼠标的x赋值给英雄机
    	heroY = y-(heroImage.getIconHeight()/2);//把鼠标的y赋值给英雄机
    	
    	if(x+heroImage.getIconWidth() > GameMain.width) {
    		heroX = GameMain.width - heroImage.getIconWidth() - 20; 
    	}
    	
    	if(y+heroImage.getIconHeight() > GameMain.height) {
    		heroY = GameMain.height - heroImage.getIconHeight() - 20; 
    	}
    			
    			
    			
    	repaint();//x发生变化后需要重新绘制
    	
    	
    }
    
   //碰撞方法
	public boolean isHit(Enemy e, Bullet b) {
		//指定一个区域
		Rectangle rect = new Rectangle(e.getX(), e.getY(), e.getWidth(), e.getHeight());
		
		//表示(x,y)坐标空间中的位置的点
		Point p = new Point(b.getX()+b.getWidth()/2, b.getY()+b.getHeight());
		
		return rect.contains(p);
	}
  		
  		
  		
    
    //重写paint方法,做绘制图片使用
    public void paint(Graphics g) {
    	super.paint(g);
    	
    	g.setFont(new Font("", Color.RED.getRed(), 30));
    	g.drawString("得分"+number, 20, 30);
    	
    	//1.绘制英雄机
    	g.drawImage(heroImage.getImage(), heroX, heroY, null);
    	
    	//2.绘制敌机
    	for(int i=0; i<enemys.size(); i++) {
    		Enemy enemy = enemys.get(i);
    		enemy.drawImage(g);//重新绘制
    	}
    	
    	//3.绘制子弹
    	for(int i=0; i<bullets.size(); i++) {
    		Bullet bullet = bullets.get(i);
    		bullet.drawImage(g);
    	}
    	
    	//4.绘制爆炸图片
    	for(int i=0; i<bombs.size(); i++) {
    		Bomb bomb = bombs.get(i);
    		bomb.drawImage(g);
    	}
    }

    /*
     * init这个方法做初始化方法使用
     * 创建一些组件(英雄机,子弹,敌人)
     * */

	public void init() {
		int flag = 0;
		while(true) {
			
		flag++;
		//每循环20次创建一个子弹
		if(flag % 15 == 0) {
		
		//创建一些子弹
		Bullet bullet = new Bullet(heroX+heroImage.getIconWidth()/2, heroY);
		
		//把子弹添加到集合中
		bullets.add(bullet);
		}
			
		//让敌机往下移动
		for(int i=0; i<enemys.size(); i++) {
			Enemy enemy = enemys.get(i);
			enemy.move();//改变敌机的y值
			
			//判断敌机的y值是否大于整个窗口的高度
			if(enemy.getY() > GameMain.height){
				//删除敌机
				enemys.remove(enemy);
				
				//再添加一个新的敌机
				enemys.add(new Enemy());
		
			}
		}
		
		//让子弹飞起来
		for(int i=0; i<bullets.size(); i++){
			Bullet tempBullet = bullets.get(i);
			tempBullet.move();
		}
		
		System.out.println("子弹数量:"+bullets.size());
		
		//删除越界的子弹
		for(int i = 0; i<bullets.size(); i++) {
			Bullet bullet = bullets.get(i);
			if(bullet.getY() < 0) {
				//y轴小于零说明越界了
				bullets.remove(bullet);
			}
		}
		
		
		//处理子弹碰撞到敌机的效果
		for(int i=0; i<enemys.size(); i++) {
			Enemy enemy = enemys.get(i);//敌机
			
			for(int j=0; j<bullets.size(); j++) {
				Bullet bullet = bullets.get(j);//得到子弹
				
				if(isHit(enemy, bullet)){
					//先删除敌机
					enemys.remove(enemy);//先删除击中的敌机
					enemys.add(new Enemy());//再添加一个新的敌机
					bullets.remove(bullet);//删除子弹
					
					//创建一个爆炸图片的对象
					Bomb bomb = new Bomb(enemy.getX(), enemy.getY());
					bombs.add(bomb);//添加到集合中
					number+=10;//每次碰撞加10分
				}
			}
		}
		
		//删除爆炸的图片
		for(int i=0; i<bombs.size(); i++) {
			Bomb bomb = bombs.get(i);
			bomb.move();
			if(bomb.getCount()>5) {
			bombs.remove(bomb);
			}
		}
		
		
		
		try {
			Thread.sleep(5);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		repaint();
		}		
	}
}

③敌机类–Enemy类

package FlyV4B;

import java.awt.Graphics;
import java.util.Random;

import javax.swing.ImageIcon;

/*
 * 敌人对象
 * 
 * */
public class Enemy {
	
	private int width;//敌人图片的宽度
	private int height;//敌人图片的高度
	
	//敌人的坐标
	private int x;
	private int y;
	
	//
	private ImageIcon  enemyImageIcon = new ImageIcon("image/enemy.png");
	
	public Enemy() {
		this.width = enemyImageIcon.getIconWidth();
		this.height = enemyImageIcon.getIconHeight();
		
		//设置敌机的位置
		Random random = new Random();
		random.nextInt(10);
		
		this.x = random.nextInt(GameMain.width - (width/2));
		this.y = -random.nextInt(GameMain.height - (height/2));
		
	}

	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public void move() {
		this.y += 1; //速度
		
	}
	
	public void drawImage(Graphics g){
		g.drawImage(enemyImageIcon.getImage(), x, y, null);
	}
}

④子弹类–Bullet类

package FlyV4B;

import java.awt.Graphics;

import javax.swing.ImageIcon;

/*
 * 子弹对象
 * */

public class Bullet {
	
	private int x;
	private int y;
	private int width;
	private int height;
	private ImageIcon bulletImageIcon = new ImageIcon("image/bullet.png");
	
	public Bullet(int x, int y) {
		this.x = x;
		this.y = y;
		this.width = bulletImageIcon.getIconWidth();
		this.height = bulletImageIcon.getIconHeight();
	}
	
	
	
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	public ImageIcon getBulletImageIcon() {
		return bulletImageIcon;
	}
	public void setBulletImageIcon(ImageIcon bulletImageIcon) {
		this.bulletImageIcon = bulletImageIcon;
	}



	public void move() {
		this.y -= 4;
		
	}



	public void drawImage(Graphics g) {
		g.drawImage(bulletImageIcon.getImage(), x, y, null);
		
	}
}

⑤爆炸图效果类–Bomb类

package FlyV4B;

import java.awt.Graphics;

import javax.swing.ImageIcon;

public class Bomb {
	
	private int x;
	private int y;
	private int width;
	private int height;
	private ImageIcon bombimg = new ImageIcon("image/bomb.png");
	private int count;//删除的次数
	
	public int getCount() {
		return count;
	}


	public void setCount(int count) {
		this.count = count;
	}


	public Bomb(int x, int y) {
		this.x = x;
		this.y = y;
		this.width = bombimg.getIconWidth();
		this.height = bombimg.getIconHeight();
	}


	public int getX() {
		return x;
	}


	public void setX(int x) {
		this.x = x;
	}


	public int getY() {
		return y;
	}


	public void setY(int y) {
		this.y = y;
	}


	public int getWidth() {
		return width;
	}


	public void setWidth(int width) {
		this.width = width;
	}


	public int getHeight() {
		return height;
	}


	public void setHeight(int height) {
		this.height = height;
	}


	public ImageIcon getBombimg() {
		return bombimg;
	}


	public void setBombimg(ImageIcon bombimg) {
		this.bombimg = bombimg;
	}


	public void drawImage(Graphics g) {
		g.drawImage(bombimg.getImage(), x, y, null);		
	}


	public void move() {
		count++;
	}	
}

三、总结

通过上述的五个类,就能够画出接下来这样的飞机大战的效果,如下图:
在这里插入图片描述
附件飞机源码+图片(亲测有效)密码: f909

  • 81
    点赞
  • 509
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
package cn.feike.shoot; import java.awt.Graphics; import java.awt.image.BufferedImage; public abstract class FlyingObject { protected double x;//物体的x坐标 protected double y;//物体的y坐标 protected double width;//物体的宽 protected double heigth;//物体的高 protected BufferedImage image;//当前正在显示的图片 protected int index = 0;//图片数组下标序号,子类中使用 protected double step;//飞行物每次(1/24秒)移动的距离 protected int life;//命 protected int state;//飞行物的状态 public static final int ACTIVE=0;//活着状态 public static final int DEAD=1;//死亡状态 public static final int REMOVE=2;//回收状态 //默认构造器 public FlyingObject() { life = 1; state = ACTIVE; } //有参构造器 public FlyingObject(double width,double heigth){ this();//调用无参数的构造器,必须写在第一行. this.x = (int)(Math.random()*(480-width)); this.y = -heigth; this.width = width; this.heigth = heigth; step = Math.random()*3+0.8;//初始化step为[0.8,3.8)之间的数 } //重写toString方法 public String toString() { return x+","+y+","+width+","+heigth+","+image; } //重写paint,方便子类对象的使用 public void paint(Graphics g) { g.drawImage(image, (int)x, (int)y, null);//绘制图片 } //飞行物移动的move方法 /** * 重构了move,方法实现播放销毁动画功能 */ public void move(){ if(state == ACTIVE){ y += step; return ; } if(state == DEAD){ //从子类对象中获取下一张照片 BufferedImage img = nextImage(); if(img == null){ state = REMOVE;//没有照片则回收 }else{ image = img;//否则把子类的图片传给image } //越界则销毁 if(y>=825){ state = REMOVE; } } } /** * 子类中必须有的方法,返回下一个要播放的照片引用, * 如果返回null表示没有可播放的照片了. */ protected abstract BufferedImage nextImage(); /** * 飞行物被打了一下 */ public void hit(){ if(life>0){ life--; } if(life==0){ state = DEAD; } } /** * 碰撞检测的方法 * 检测物体的位置是否在碰撞的范围内. * (子弹是否在飞行物的碰撞范围内) */ public boolean duang(FlyingObject obj){ //this(x,y,w,h) //obj(x,y,w,h) double x1 = this.x - obj.width; double x2 = this.x + this.width; double y1 = this.y - obj.width; double y2 = this.y + this.heigth; return x1<obj.x&&obj;.x<x2&&y1;<obj.y&&obj;.y<y2; } /** 重构FlyingObject,添加了状态检查方法 */ /** 检查飞行物死了吗 */ public boolean isDead(){ return state == DEAD; } /** 检查飞行物是否活动的 */ public boolean isActive(){ return state == ACTIVE; } /** 检查飞行是否可以被删除*/ public boolean canRemove(){ return state == REMOVE; } /** 飞行物添加"去死"方法*/ public void goDead(){ if(isActive()){ state = DEAD; } } }
飞机大战是一款经典的游戏,下面我介绍一下使用Java实现飞机大战的基本思路: 1. 创建游戏窗口 使用Java中的JFrame类创建一个游戏窗口,设置窗口大小、标题、背景色等属性。 2. 加载游戏资源 使用Java中的Image类加载游戏所需的图片资源,包括背景图、飞机图、子弹图、敌机图等。 3. 创建游戏角色 创建游戏角色,包括玩家飞机、敌机、子弹等,使用Java中的JPanel类将它们添加到游戏窗口中。 4. 添加游戏事件 为游戏角色添加事件,包括玩家飞机的移动、子弹的发射、敌机的生成等。 5. 实现游戏逻辑 实现游戏的逻辑,包括碰撞检测、得分计算、游戏结束判断等。 6. 实现游戏界面 使用Java中的Graphics类绘制游戏界面,包括背景图、游戏角色、得分、生命等信息。 7. 运行游戏 将游戏窗口设置为可见状态,启动游戏。 上述是Java实现飞机大战的基本思路,具体实现可以参考以下示例代码: ```java import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.List; import java.util.Random; public class PlaneGame extends JFrame { private static final int WIDTH = 500; private static final int HEIGHT = 700; private final Image background = new ImageIcon("resources/background.jpg").getImage(); private final Image airplane = new ImageIcon("resources/airplane.png").getImage(); private final Image bullet = new ImageIcon("resources/bullet.png").getImage(); private final Image enemyAirplane = new ImageIcon("resources/enemy_airplane.png").getImage(); private final List<Bullet> bullets = new ArrayList<>(); private final List<EnemyAirplane> enemyAirplanes = new ArrayList<>(); private int score = 0; private int life = 3; private final Random random = new Random(); private int playerX = WIDTH / 2 - airplane.getWidth(null) / 2; private int playerY = HEIGHT - airplane.getHeight(null) - 50; private boolean isMovingLeft = false; private boolean isMovingRight = false; private boolean isFiring = false; public PlaneGame() { setSize(WIDTH, HEIGHT); setTitle("Plane Game"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); setResizable(false); addKeyListener(new KeyListener() { @Override public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: isMovingLeft = true; break; case KeyEvent.VK_RIGHT: isMovingRight = true; break; case KeyEvent.VK_SPACE: isFiring = true; break; } } @Override public void keyReleased(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: isMovingLeft = false; break; case KeyEvent.VK_RIGHT: isMovingRight = false; break; case KeyEvent.VK_SPACE: isFiring = false; break; } } @Override public void keyTyped(KeyEvent e) { } }); setVisible(true); } @Override public void paint(Graphics g) { g.drawImage(background, 0, 0, null); g.drawImage(airplane, playerX, playerY, null); for (Bullet bullet : bullets) { g.drawImage(this.bullet, bullet.getX(), bullet.getY(), null); } for (EnemyAirplane enemyAirplane : enemyAirplanes) { g.drawImage(this.enemyAirplane, enemyAirplane.getX(), enemyAirplane.getY(), null); } g.setColor(Color.WHITE); g.setFont(new Font("Arial", Font.BOLD, 20)); g.drawString("Score: " + score, 20, 30); g.drawString("Life: " + life, WIDTH - 100, 30); } public void start() { while (life > 0) { if (isMovingLeft) { playerX -= 5; } if (isMovingRight) { playerX += 5; } if (isFiring) { bullets.add(new Bullet(playerX + airplane.getWidth(null) / 2, playerY)); } for (Bullet bullet : bullets) { bullet.move(); } for (EnemyAirplane enemyAirplane : enemyAirplanes) { enemyAirplane.move(); } if (random.nextInt(100) < 10) { enemyAirplanes.add(new EnemyAirplane(random.nextInt(WIDTH - enemyAirplane.getWidth(null)), -enemyAirplane.getHeight(null))); } for (Bullet bullet : bullets) { for (EnemyAirplane enemyAirplane : enemyAirplanes) { if (bullet.isCollidedWith(enemyAirplane)) { score++; bullets.remove(bullet); enemyAirplanes.remove(enemyAirplane); break; } } } for (EnemyAirplane enemyAirplane : enemyAirplanes) { if (enemyAirplane.isCollidedWith(playerX, playerY, airplane.getWidth(null), airplane.getHeight(null))) { life--; enemyAirplanes.remove(enemyAirplane); break; } } repaint(); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } JOptionPane.showMessageDialog(this, "Game Over!\nScore: " + score); System.exit(0); } private static class Bullet { private static final int SPEED = 10; private final int x; private int y; public Bullet(int x, int y) { this.x = x; this.y = y; } public void move() { y -= SPEED; if (y < -bullet.getHeight(null)) { bullets.remove(this); } } public int getX() { return x; } public int getY() { return y; } public boolean isCollidedWith(EnemyAirplane enemyAirplane) { int bulletX = getX() + bullet.getWidth(null) / 2; int bulletY = getY() + bullet.getHeight(null) / 2; int enemyAirplaneX = enemyAirplane.getX() + enemyAirplane.getWidth(null) / 2; int enemyAirplaneY = enemyAirplane.getY() + enemyAirplane.getHeight(null) / 2; int distance = (int) Math.sqrt(Math.pow(bulletX - enemyAirplaneX, 2) + Math.pow(bulletY - enemyAirplaneY, 2)); return distance < bullet.getWidth(null) / 2 + enemyAirplane.getWidth(null) / 2; } } private static class EnemyAirplane { private static final int SPEED = 5; private final int x; private int y; public EnemyAirplane(int x, int y) { this.x = x; this.y = y; } public void move() { y += SPEED; if (y > HEIGHT) { enemyAirplanes.remove(this); } } public int getX() { return x; } public int getY() { return y; } public boolean isCollidedWith(int x, int y, int width, int height) { int enemyAirplaneX = getX() + enemyAirplane.getWidth(null) / 2; int enemyAirplaneY = getY() + enemyAirplane.getHeight(null) / 2; int distance = (int) Math.sqrt(Math.pow(enemyAirplaneX - x - width / 2, 2) + Math.pow(enemyAirplaneY - y - height / 2, 2)); return distance < enemyAirplane.getWidth(null) / 2 + width / 2; } } public static void main(String[] args) { new PlaneGame().start(); } } ``` 上述代码实现了基本的飞机大战游戏,包括玩家飞机的移动、子弹的发射、敌机的生成、碰撞检测、得分计算、游戏结束等功能。可以根据实际需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值