2025年3月24日 星期一 甲辰(龙)年 月廿三 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Java

JAVA实现飞机大战小游戏

时间:10-29来源:作者:点击数:55

效果展示及部分代码

  • 这是游戏开始界面,对游戏玩法做了一定介绍,并使用mouseClicked()捕获鼠标指针位置,获取点击位置,判断游戏是否开始~

开始界面

开始界面.png
开始界面.png

源码:

  • public static void main(String[] args) {
  • // 创建MyPlane类的对象
  • PlaneEvent x = new PlaneEvent();
  • // 创建窗体
  • JFrame jf = new JFrame("飞机大战小游戏");
  • // 创建容器
  • Container c = jf.getContentPane();
  • // 创建一个按钮
  • JButton jb = new JButton("开始游戏");
  • // 定义按钮属性
  • jb.setBackground(Color.GRAY);
  • jb.setFont(new Font("华文隶书", 80, 80));
  • // 创建画板
  • class A extends JPanel {
  • @Override
  • public void paint(Graphics g) {
  • // TODO 自动生成的方法存根
  • super.paint(g);
  • // 调用开始图片,并打印相应文字
  • g.drawImage(new ImageIcon("./image/start.jpg").getImage(), 0, 0, 650 ,960, null);
  • g.setFont(new Font("华文楷体", 20,20));
  • g.setColor(Color.BLACK);
  • g.drawString("游戏规则:", 16, 750);
  • g.drawString("小飞机被击中3次消失", 16, 780);
  • g.drawString("大飞机被击中5次消失", 16, 810);
  • g.drawString("飞机碰撞后生命值减少-1/-5", 16, 840);
  • g.drawString("未打掉飞机则生命值减少", 16, 870);
  • g.drawString("分数到一定值出现虫洞,若碰到圆虫则生命值减少", 16, 900);
  • }
  • }
  • // 创建鼠标监听者
  • class Mouse implements MouseListener{
  • @Override
  • public void mouseClicked(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • // 当鼠标点击按钮,则此窗体消失,游戏窗体打开
  • jf.setVisible(false);
  • x.print();
  • }
  • @Override
  • public void mouseEntered(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • @Override
  • public void mouseExited(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • @Override
  • public void mousePressed(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • @Override
  • public void mouseReleased(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • }
  • // 创建画板对象
  • A cp = new A();
  • // 绑定按钮和鼠标监听者
  • jb.addMouseListener(new Mouse());
  • // 将画板分为五行一列
  • cp.setLayout(new GridLayout(5,1));
  • // 设置分块画板属性
  • JPanel jp1 = new JPanel();
  • JPanel jp2 = new JPanel();
  • JPanel jp3 = new JPanel();
  • JPanel jp4 = new JPanel();
  • JPanel jp5 = new JPanel();
  • // 将按钮添加到第四块面板上
  • jp4.add(jb);
  • // 将5块面板都添加到画板上
  • cp.add(jp1);
  • cp.add(jp2);
  • cp.add(jp3);
  • cp.add(jp4);
  • cp.add(jp5);
  • // 将画板添加到窗体容器内
  • c.add(cp);
  • // 设置窗体基本属性
  • jf.setVisible(true);
  • jf.setResizable(false);
  • jf.setLocation(800, 20);
  • jf.setSize(650, 1000);
  • jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  • }

结束页面

  • 基本沿用开始游戏界面相关信息,整个页面捕获鼠标位置,一旦点击页面即退出游戏
结束界面.png
结束界面.png

源码:

  • public void print() {
  • // 创建窗体
  • JFrame jf = new JFrame("飞机大战小游戏");
  • // 获取容器
  • Container c = jf.getContentPane();
  • // 创建画板组件
  • class A extends JPanel {
  • @Override
  • public void paint(Graphics g) {
  • // TODO 自动生成的方法存根
  • super.paint(g);
  • // 调用结束游戏的图片,并在画板上显示各类文字信息
  • g.drawImage(new ImageIcon("./image/end.png").getImage(), 0, 0, 650, 960, null);
  • g.setColor(Color.BLACK);
  • g.setFont(new Font("华文行楷",80,80));
  • g.drawString("游戏结束", 160, 700);
  • g.setColor(Color.red);
  • g.setFont(new Font("小豆岛默陌纸鸢草书简",40,40));
  • g.drawString("点击任意位置结束", 80, 850);
  • }
  • }
  • // 创建鼠标监听者
  • class Mouse implements MouseListener{
  • @Override
  • public void mouseClicked(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • // 鼠标点击则退出
  • System.exit(0);
  • }
  • @Override
  • public void mouseEntered(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • @Override
  • public void mouseExited(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • @Override
  • public void mousePressed(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • @Override
  • public void mouseReleased(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • }
  • // 绑定窗体和监听者
  • jf.addMouseListener(new Mouse());
  • // 创建画板对象
  • A sp = new A();
  • // 将画板添加到窗体容器中
  • c.add(sp);
  • // 设置窗体属性
  • jf.setVisible(true);
  • jf.setResizable(false);
  • jf.setLocation(800, 20);
  • jf.setSize(650, 1000);
  • jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  • }

设置飞机属性

  • 游戏中设置了两类敌机:所需要击中子弹的个数有不同要求,击毁则将飞机的位置数组回到起始位置(横坐标随机,纵坐标固定),图中也能看到有血量分数等信息,通过设置计数器实现
游戏-ing.png
游戏-ing.png

源码(设置属性):

  • // 飞机的数量随机
  • int num = new Random().nextInt(6) + 3;
  • // 飞机的大小
  • int len = 150;
  • // 飞机的坐标
  • int planeX[] = new int[num];
  • // 飞机的坐标
  • int planeY[] = new int[num];
  • // 飞机的速度
  • int speed[] = new int[num];
  • // boss飞机的数量随机
  • int num1 = new Random().nextInt(2) + 2;
  • // boss飞机的大小
  • int len1 = 180;
  • // boss飞机的横坐标
  • int planeX1[] = new int[num1];
  • // boss飞机的纵坐标
  • int planeY1[] = new int[num1];
  • // boss飞机的速度
  • int speed1[] = new int[num1];
  • // 屏幕的大小
  • int jfw = 650;
  • int jfh = 1000;
  • {
  • // 初始化飞机的各个属性
  • for (int i = 0; i < num; i++) {
  • // 横坐标随机 纵坐标固定
  • planeX[i] = new Random().nextInt(jfw - 100);
  • // 纵坐标为负 创造出平滑飞出的结果而不是突然出现
  • planeY[i] = -50;
  • // 设置不同种速度的飞机以增加难度 速度在1到5之间
  • speed[i] = new Random().nextInt(4) + 1;
  • }
  • }
  • {
  • // 初始化boss飞机的各个属性
  • for (int i = 0; i < num1; i++) {
  • // 横坐标随机 纵坐标固定
  • planeX1[i] = new Random().nextInt(jfw - 150);
  • // 纵坐标为负 创造出平滑飞出的结果而不是突然出现
  • planeY1[i] = -80;
  • // 设置不同种速度的飞机以增加难度 速度在1到4之间
  • speed1[i] = new Random().nextInt(3) + 1;
  • }
  • }
  • public void print() {
  • // 1 创建窗体对象
  • JFrame jf = new JFrame("飞机大战");
  • // 2 获取容器
  • Container c = jf.getContentPane();
  • // 3 创建组件 此处只需要创建画板组件
  • class PlanePainter extends JPanel {
  • @Override
  • public void paint(Graphics g) {
  • // TODO Auto-generated method stub
  • super.paint(g);
  • // 画出背景
  • // 画出飞机
  • for (int i = 0; i < num; i++) {
  • g.drawImage(new ImageIcon("./image/普通敌机.png").getImage(), planeX[i], planeY[i], len, len, null);
  • }
  • // 画出boss飞机
  • for (int i = 0; i < num1; i++) {
  • g.drawImage(new ImageIcon("./image/敌方boss.png").getImage(), planeX1[i], planeY1[i], len1, len1, null);
  • }
  • }
  • }
  • // 创建画板组件对象
  • PlanePainter sp = new PlanePainter();
  • sp.setBackground(Color.pink);
  • // 4 添加组件
  • c.add(sp);
  • // 6 设置窗体属性
  • jf.setVisible(true);
  • jf.setSize(jfw, jfh);
  • jf.setLocation(30, 50);// 窗体左上角的位置
  • jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  • // 创建线程 改变图片位置 刷新图片 实现动态效果
  • new Thread(new Runnable() {
  • @Override
  • public void run() {
  • // TODO Auto-generated method stub
  • boolean t = true;
  • while (t) {
  • // 改变位置
  • for (int i = 0; i < num; i++) {
  • planeY[i] += speed[i];
  • if (planeY[i] > jfh) {
  • // 如果飞机超出最下面的窗体,就把飞机送回窗体最上面
  • planeY[i] = -50;
  • // 飞机回去后,重新创建新的横坐标位置
  • planeX[i] = new Random().nextInt(jfw);
  • // 飞机回去后速度也随机
  • speed[i] = new Random().nextInt(4) + 1;
  • }
  • }
  • // 线程休眠
  • try {
  • Thread.sleep(20);
  • } catch (InterruptedException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • }
  • // 图片重绘
  • sp.repaint();
  • }
  • }
  • }).start();
  • new Thread(new Runnable() {
  • @Override
  • public void run() {
  • // TODO Auto-generated method stub
  • boolean m = true;
  • while (m) {
  • // 改变位置
  • for (int i = 0; i < num1; i++) {
  • planeY1[i] += speed1[i];
  • if (planeY1[i] > jfh) {
  • // 如果boss飞机超出最下面的窗体,就把飞机送回窗体最上面
  • planeY1[i] = -80;
  • // boss飞机回去后,重新创建新的横坐标位置
  • planeX1[i] = new Random().nextInt(jfw);
  • // boss飞机回去后速度也随机
  • speed1[i] = new Random().nextInt(3) + 1;
  • }
  • }
  • // 线程休眠
  • try {
  • Thread.sleep(20);
  • } catch (InterruptedException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • }
  • // 图片重绘
  • sp.repaint();
  • }
  • }
  • }).start();
  • }
  • public static void main(String[] args) {
  • Plane z = new Plane();
  • z.print();
  • }

游戏中各种事件的发生

源码(事件发生):

  • // 定义窗体的大小
  • int JFW = 650;
  • int JFH = 1000;
  • // 定义窗体位置
  • int LX = 800;
  • int LY = 20;
  • // 定义获取到的鼠标初始位置
  • int mouseX = 0;
  • int mouseY = 0;
  • // 定义我方飞机大小
  • int LEN = 110;
  • // 定义我方飞机初始位置
  • int CX = 150;
  • int CY = 600;
  • // 定义子弹数量
  • int num = 8;
  • // 定义子弹的大小
  • int BL = 25;
  • // 定义子弹初始位置
  • int BLX[] = new int[num];
  • int BLY[] = new int[num];
  • // 初始化子弹的各项属性
  • {
  • BLX[0] = CX + 30;
  • BLY[0] = CY - 40;
  • for (int i = 1; i < num; i++) {
  • BLX[i] = CX + 50;
  • BLY[i] = BLY[i - 1] - 50;
  • }
  • }
  • /*
  • * 敌方普通飞机
  • */
  • // 飞机的数量随机
  • int num1 = new Random().nextInt(6) + 3;
  • // 飞机的大小
  • int len = 100;
  • // 飞机的坐标
  • int planeX[] = new int[num1];
  • // 飞机的坐标
  • int planeY[] = new int[num1];
  • // 飞机的速度
  • int speed[] = new int[num1];
  • {
  • // 初始化敌方飞机的各个属性
  • for (int i = 0; i < num1; i++) {
  • // 横坐标随机 纵坐标固定
  • planeX[i] = new Random().nextInt(JFW - 150);
  • // 纵坐标为负 创造出平滑飞出的结果而不是突然出现
  • planeY[i] = -50;
  • // 设置不同种速度的飞机以增加难度 速度在1到5之间
  • speed[i] = new Random().nextInt(4) + 2;
  • }
  • }
  • /*
  • * 敌方boss飞机
  • */
  • // boss飞机的数量随机
  • int num2 = new Random().nextInt(2) + 1;
  • // boss飞机的大小
  • int len1 = 160;
  • // boss飞机的横坐标
  • int planeX1[] = new int[num2];
  • // boss飞机的纵坐标
  • int planeY1[] = new int[num2];
  • // boss飞机的速度
  • int speed1[] = new int[num2];
  • {
  • // 初始化boss飞机的各个属性
  • for (int i = 0; i < num2; i++) {
  • // 横坐标随机 纵坐标固定
  • planeX1[i] = new Random().nextInt(JFW - 200);
  • // 纵坐标为负 创造出平滑飞出的结果而不是突然出现
  • planeY1[i] = -80;
  • // 设置不同种速度的飞机以增加难度 速度在1到4之间
  • speed1[i] = new Random().nextInt(3) + 2;
  • }
  • }
  • // 定义虫洞位置
  • int holeX=150;
  • int holeY=200;
  • // 定义虫洞大小
  • int holeS=300;
  • // 虫洞开启钥匙
  • boolean ishole=false;
  • // 定义圆虫数量
  • int insectnum=10;
  • // 定义圆虫大小
  • int insectS[]=new int [insectnum];
  • // 定义圆虫位置
  • int insectX[]=new int [insectnum];
  • int insectY[]=new int [insectnum];
  • // 圆虫移动方向
  • int insectXDirect[]=new int [insectnum];
  • int insectYDirect[]=new int [insectnum];
  • // 初始化圆虫属性
  • {
  • for(int i=0;i<insectnum;i++) {
  • // 圆虫移动方向参数设置
  • insectXDirect[i]=1;
  • insectYDirect[i]=1;
  • // 圆虫的随机大小
  • insectS[i]=new Random().nextInt(5)+25;
  • // 圆虫的随机位置
  • insectX[i]=holeX+holeS/2;
  • insectY[i]=holeY+holeS/2;
  • }
  • }
  • // 生命值所在位置设定
  • int lifeX = JFW-140;
  • int lifeY = 50;
  • // 设置血量
  • int lifenum = 50;
  • // 定义分数并初始化
  • /*
  • * 为什么用数组?在不同的花括号中的运算结果不能够共用,比如A线程分数在我方飞机击落敌机时变化,B线程分数没有改变,运算结果无法共用;
  • * 用数组开辟一个确定的空间来存储运算结果,每次变化都存放在这个地方,要用的时候调用,可以实现运算结果的实时变化和共用,也可用指针实现。
  • */
  • int score[] = new int[1];
  • {
  • for(int s=0;s<1;s++) //因为只需要用到一个分数,所以只开辟一个空间
  • score[s]=0;
  • }
  • // 设置敌方普通飞机爆炸效果参数
  • boolean isboom = false;
  • int boomx = -100; //爆炸位置
  • int boomy = -100; //爆炸位置
  • int booms = 0; //爆炸大小
  • // 设置敌方boss飞机爆炸效果参数
  • boolean isboom1 = false;
  • int boomx1 = -100; //爆炸位置
  • int boomy1 = -100; //爆炸位置
  • int booms1 = 0; //爆炸大小
  • public void print() {
  • // 创建退出类的对象
  • Exit exit = new Exit();
  • // 创建爆炸声的对象
  • TestMusic sound = new TestMusic("./music/BGM.wav");
  • InputStream stream = new ByteArrayInputStream(sound.getSamples());
  • // 创建窗体
  • JFrame jf = new JFrame("飞机大战小游戏");
  • // 获取容器
  • Container c = jf.getContentPane();
  • // 创建画板组件
  • class A extends JPanel {
  • @Override
  • public void paint(Graphics g) {
  • // TODO 自动生成的方法存根
  • super.paint(g);
  • // 在窗体下方划出一道境界红线---敌方飞机未被击毁碰到红线则生命值减少
  • g.setColor(Color.red);
  • g.setFont(new Font("华文琥珀",50,50));
  • g.drawString("———————————————", 0, 973);
  • // 画出虫洞效果图 (在下方会判断是否画出虫洞圆虫,然后对ishole进行进行改变)
  • if(ishole) {
  • if(ishole) {
  • g.drawImage(new ImageIcon("./image/黑洞.png").getImage(), holeX, holeY,holeS,holeS,null);
  • // 画出一定数量的圆虫
  • for(int i=0;i<insectnum;i++) {
  • g.drawImage(new ImageIcon("./image/圆虫.png").getImage(),insectX[i],insectY[i],insectS[i],insectS[i],null);
  • }
  • }
  • }
  • // 调用我方飞机的图片
  • g.drawImage(new ImageIcon("./image/我方飞机.png").getImage(), CX, CY, LEN, LEN, null);
  • // 调用子弹图片 画出一定量子弹
  • for (int i = 0; i < num; i++) {
  • g.drawImage(new ImageIcon("./image/子弹.png").getImage(), BLX[i], BLY[i], BL, BL, null);
  • }
  • // 画出飞机 画出一定量飞机
  • for (int i = 0; i < num1; i++) {
  • g.drawImage(new ImageIcon("./image/普通敌机.png").getImage(), planeX[i], planeY[i], len, len, null);
  • }
  • // 画出boss飞机 画出一定量Boss飞机
  • for (int i = 0; i < num2; i++) {
  • g.drawImage(new ImageIcon("./image/敌方boss.png").getImage(), planeX1[i], planeY1[i], len1, len1,
  • null);
  • }
  • // 画出敌方普通爆炸效果图
  • if(isboom) {
  • g.drawImage(new ImageIcon("./image/爆炸.png").getImage(), boomx, boomy, booms, booms, null);
  • }
  • // 画出敌方boss爆炸效果图
  • if(isboom1) {
  • g.drawImage(new ImageIcon("./image/爆炸.png").getImage(), boomx1, boomy1, booms1, booms1, null);
  • }
  • // 在右上方注释生命值
  • g.setColor(Color.BLACK);
  • g.setFont(new Font("微软雅黑",18,18));
  • for(int s=0;s<1;s++) {
  • g.drawString("分数:"+score[s], lifeX, lifeY+20);
  • }
  • // 生命值颜色低于30时变成红色
  • if(lifenum>=30) {
  • g.setColor(Color.BLACK); //颜色属性
  • g.drawString("血量:"+lifenum, lifeX, lifeY); //文字、位置
  • }
  • else {
  • g.setColor(Color.RED); //颜色属性
  • g.drawString("血量:"+lifenum, lifeX, lifeY); //文字、位置
  • }
  • }
  • }
  • // 创建画板的对象
  • A sp = new A();
  • // 创建鼠标移动监听者
  • class S implements MouseMotionListener {
  • @Override
  • public void mouseDragged(MouseEvent arg0) {
  • // TODO 自动生成的方法存根
  • }
  • @Override
  • public void mouseMoved(MouseEvent e) {
  • // TODO 自动生成的方法存根
  • // 将获取到的鼠标位置赋值给飞机的中心位置坐标 实现飞机随着鼠标动的效果
  • CX = e.getX() - LEN / 2;
  • CY = e.getY() - LEN / 2;
  • // 重绘画板
  • sp.repaint();
  • }
  • }
  • // 绑定画板和监听者
  • sp.addMouseMotionListener(new S());
  • // 将画板添加到容器
  • c.add(sp);
  • // 设置窗体属性
  • // jf.setUndecorated(true);
  • jf.setVisible(true); //显示窗体
  • jf.setResizable(false); //窗体大小不可调
  • jf.setLocation(LX, LY); //窗体位置
  • jf.setSize(JFW, JFH); //窗体大小
  • jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //窗体关闭则程序结束运行
  • /*
  • * 创建子弹飞行线程
  • */
  • new Thread(new Runnable() {
  • @Override
  • public void run() {
  • // TODO 自动生成的方法存根
  • boolean t = true;
  • // 创建一个死循环,让子弹一直飞行
  • while (t) {
  • for (int i = 0; i < num; i++) {
  • // 子弹飞行速度为80(向上飞)
  • BLY[i] -= 80;
  • // 判断子弹是否到达窗体顶端,如果是回到飞机现在为止并逐个射出
  • if (BLY[i] < 0) {
  • BLX[i] = CX + 40;
  • BLY[i] = CY - 40*i;
  • }
  • // 设置休眠时间
  • try {
  • Thread.sleep(3);
  • } catch (InterruptedException e) {
  • // TODO 自动生成的 catch 块
  • e.printStackTrace();
  • }
  • }
  • // 重绘画板
  • sp.repaint();
  • }
  • }
  • }).start();
  • /*
  • * 创建敌机线程 改变图片位置 刷新图片 实现动态效果
  • */
  • new Thread(new Runnable() {
  • @Override
  • public void run() {
  • // TODO Auto-generated method stub
  • boolean t = true;
  • while (t) {
  • /*
  • * 敌方普通飞机
  • */
  • // 改变位置
  • for (int i = 0; i < num1; i++) {
  • if (planeY[i] > JFH) {
  • lifenum -= 1;
  • // 如果飞机超出最下面的窗体,就把飞机送回窗体最上面
  • planeY[i] = -100;
  • // 飞机回去后,重新创建新的横坐标位置
  • planeX[i] = new Random().nextInt(JFW-150);
  • // 飞机回去后速度也随机
  • speed[i] = new Random().nextInt(4) + 2;
  • }
  • // 创建一个子弹撞击敌方普通飞机的计数器 b,并初始化为0
  • int b=0;
  • for(int j = 0 ;j < num; j++ ) {
  • // 三个if判断子弹是否击中敌方普通飞机
  • if(((BLX[j]+BL)>=planeX[i]) && (BLX[j]<=planeX[i]) && BLY[j]<=(planeY[i]+len)) {
  • // 如果击中,计数器加一
  • b++;
  • //如果子弹打中敌机子弹消失
  • BLX[j] = CX + 40;
  • BLY[j] = CY - 40*j;
  • }
  • else if(((BLX[j]+BL)>=(planeX[i]+len)) && (BLX[j]<=(planeX[i]+len)) && BLY[j]<=(planeY[i]+len)) {
  • b++;
  • BLX[j] = CX + 40;
  • BLY[j] = CY - 40*j;
  • }
  • else if(((BLX[j]+BL)<=(planeX[i]+len)) && (BLX[j]>=(planeX[i])) && BLY[j]<=(planeY[i]+len)) {
  • b++;
  • BLX[j] = CX + 40;
  • BLY[j] = CY - 40*j;
  • }
  • // 爆炸效果实现,判断计数器次数是否到达三次
  • if(b>=3) {
  • // 是否爆炸
  • isboom = true;
  • // 爆炸的位置
  • boomx = planeX[i];
  • boomy = planeY[i];
  • // 爆炸的大小和敌方普通飞机一致
  • booms = len;
  • }
  • // 子弹击中敌方普通飞机3次及以上敌方飞机就会回到起始位置,即窗体上面不可见的位置
  • if(b>=3) {
  • planeY[i] = -100;
  • planeX[i] = new Random().nextInt(JFW-150);
  • speed[i] = new Random().nextInt(4) + 2;
  • // 打爆一个敌方普通飞机加一分
  • for(int s=0;s<1;s++){
  • score[s] +=1;
  • }
  • // 如果爆炸则子弹遍历循环停止,否则分数会一直增加
  • break;
  • }
  • }
  • /*
  • * 敌方普通飞机与我方飞机碰撞减少生命值并且敌方普通飞机消失(三种情况的判断)
  • */
  • // 我方飞机左端在敌机X轴范围内的碰撞
  • if(((CX+LEN)/2>=(planeX[i]/2))&&((CX/2)<=(planeX[i]/2)) && (((CY/2)<=((planeY[i]+len)/2))&&(CY+LEN)/2>=(planeY[i]/2))) {
  • // 如果敌方普通飞机与我方飞机相撞,则生命值减一,并且敌方普通飞机回到起始随机位置
  • lifenum -=1;
  • isboom = true;
  • boomx = planeX[i];
  • boomy = planeY[i];
  • booms = len;
  • planeY[i] = -100;
  • planeX[i] = new Random().nextInt(JFW-150);
  • speed[i] = new Random().nextInt(4) + 2;
  • }
  • // 我方飞机右端在敌机X轴范围内的碰撞
  • else if((CX/2<=((planeX[i]+len)/2))&&(((CX+LEN)/2)>=((planeX[i]+len)/2)) && (((CY/2)<=((planeY[i]+len)/2))&&(CY+LEN)/2>=(planeY[i]/2))) {
  • // 如果敌方普通飞机与我方飞机相撞,则生命值减一,并且敌方普通飞机回到起始随机位置
  • lifenum -=1;
  • isboom = true;
  • boomx = planeX[i];
  • boomy = planeY[i];
  • booms = len;
  • planeY[i] = -100;
  • planeX[i] = new Random().nextInt(JFW-150);
  • speed[i] = new Random().nextInt(4) + 2;
  • }
  • // 敌方飞机在我方飞机X轴范围内的碰撞(因为我方飞机模型大于地方飞机模型)
  • else if((CX/2<=(planeX[i]/2))&&(((CX+LEN)/2)>=((planeX[i]+len)/2)) && (((CY/2)<=((planeY[i]+len)/2))&&(CY+LEN)/2>=(planeY[i]/2))) {
  • // 如果敌方普通飞机与我方飞机相撞,则生命值减一,并且敌方普通飞机回到起始随机位置
  • lifenum -=1;
  • isboom = true;
  • boomx = planeX[i];
  • boomy = planeY[i];
  • booms = len;
  • planeY[i] = -100;
  • planeX[i] = new Random().nextInt(JFW-150);
  • speed[i] = new Random().nextInt(4) + 2;
  • }
  • // 普通飞机飞机向下飞行的速度
  • planeY[i] += speed[i];
  • }
  • /*
  • * 敌方boss飞机
  • */
  • // 改变位置
  • for (int i = 0; i < num2; i++) {
  • // 如果boss飞机超出最下面的窗体,就把飞机送回窗体最上面
  • if (planeY1[i] > JFH) {
  • lifenum -= 3;
  • // boss飞机回到窗体外看不见的位置
  • planeY1[i] = -150;
  • // boss飞机回去后,重新创建新的横坐标位置
  • planeX1[i] = new Random().nextInt(JFW-200);
  • // boss飞机回去后速度也随机
  • speed1[i] = new Random().nextInt(3) + 2;
  • }
  • // 创建一个子弹撞击敌方普通飞机的计数器 a,并初始化为0
  • int a = 0;
  • for (int k = 0; k < num; k++) {
  • // 三种子弹撞击boss飞机的情况判断
  • if((((BLX[k]+BL)>=planeX1[i]) && (BLX[k]<=planeX1[i])) && (BLY[k]<=(planeY1[i]+len1))) {
  • // 若相撞,则计数器加一
  • a++;
  • // 子弹回到飞机现在的位置
  • BLX[k] = CX + 40;
  • BLY[k] = CY - 40*i;
  • }
  • else if((((BLX[k]+BL)>=(planeX1[i]+len1)) && (BLX[k]<=(planeX1[i]+len1))) && (BLY[k]<=(planeY1[i]+len1))) {
  • a++;
  • BLX[k] = CX + 40;
  • BLY[k] = CY - 40*i;
  • }
  • else if((((BLX[k]+BL)<=(planeX1[i]+len1)) && (BLX[k]>=(planeX1[i]))) && (BLY[k]<=(planeY1[i]+len1))) {
  • a++;
  • BLX[k] = CX + 40;
  • BLY[k] = CY - 40*i;
  • }
  • // 计数器到达5,爆炸效果实现
  • if(a>=5) {
  • // 撞击判断条件设置为true
  • isboom1 = true;
  • // 将boss飞机被击毁的位置附给爆炸图片
  • boomx1 = planeX1[i];
  • boomy1 = planeY1[i];
  • // 将boss飞机的大小附给爆炸图片
  • booms1 = len1;
  • }
  • // boss飞机被击毁后消失(回到初始随机位置)
  • if(a>=5) {
  • planeY1[i] = -150;
  • planeX1[i] = new Random().nextInt(JFW-200);
  • speed1[i] = new Random().nextInt(3) + 2;
  • // 击毁一架敌方boss飞机,score分数加5分
  • for(int s=0;s<1;s++) {
  • score[s] +=5;
  • }
  • // 击毁后,则停止子弹遍历,否则分数无限累计
  • break;
  • }
  • }
  • /*
  • *敌方boss飞机与我方飞机碰撞减少生命值并且敌方boss飞机消失
  • */
  • // 我方飞机左端在敌方boss机X轴范围内的碰撞
  • if(((CX+LEN)/2>=(planeX1[i]/2))&&((CX/2)<=(planeX1[i]/2)) && (((CY/2)<=((planeY1[i]+len1)/2))&&(CY+LEN)/2>=(planeY1[i]/2))) {
  • // 我方飞机与敌方boss飞机相撞,则生命值减五
  • lifenum -=5;
  • // 判断是否爆炸
  • isboom1 = true;
  • // 将boss飞机被击毁的位置附给爆炸图片
  • boomx1 = planeX1[i];
  • boomy1 = planeY1[i];
  • // 将boss飞机的大小附给爆炸图片
  • booms1 = len1;
  • // 敌方boss飞机回到初始随机位置
  • planeY1[i] = -150;
  • planeX1[i] = new Random().nextInt(JFW-200);
  • speed1[i] = new Random().nextInt(3)+2;
  • }
  • // 我方飞机右端在敌方boss机X轴范围内的碰撞
  • else if((CX/2<=((planeX1[i]+len1)/2))&&(((CX+LEN)/2)>=((planeX1[i]+len1)/2)) && (((CY/2)<=((planeY1[i]+len1)/2))&&(CY+LEN)/2>=(planeY1[i]/2))) {
  • lifenum -=5;
  • // 判断是否爆炸
  • isboom1 = true;
  • // 将boss飞机被击毁的位置附给爆炸图片
  • boomx1 = planeX1[i];
  • boomy1 = planeY1[i];
  • // 将boss飞机的大小附给爆炸图片
  • booms1 = len1;
  • planeY1[i] = -150;
  • planeX1[i] = new Random().nextInt(JFW-200);
  • speed1[i] = new Random().nextInt(3)+2;
  • }
  • // 我方飞机在敌方boss机范围内的碰撞(敌方boss机比我方飞机大)
  • else if((CX/2>=(planeX1[i]/2))&&(((CX+LEN)/2)<=((planeX1[i]+len1)/2)) && (((CY/2)<=((planeY1[i]+len1)/2))&&(CY+LEN)/2>=(planeY1[i]/2))) {
  • lifenum -=5;
  • // 判断是否爆炸
  • isboom1 = true;
  • // 将boss飞机被击毁的位置附给爆炸图片
  • boomx1 = planeX1[i];
  • boomy1 = planeY1[i];
  • // 将boss飞机的大小附给爆炸图片
  • booms1 = len1;
  • planeY1[i] = -150;
  • planeX1[i] = new Random().nextInt(JFW-200);
  • speed1[i] = new Random().nextInt(3)+2;
  • }
  • // 敌方boss飞机向下飞行的速度
  • planeY1[i] += speed1[i];
  • }
  • // 如果生命值小于等于0,调出退出界面,并关闭此窗口
  • if(lifenum<=0) {
  • t=false;
  • jf.setVisible(false);
  • exit.print();
  • }
  • // 线程休眠
  • try {
  • Thread.sleep(20);
  • } catch (InterruptedException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • }
  • // 图片重绘
  • sp.repaint();
  • // 将敌方普通飞机的爆炸效果清除
  • isboom = false;
  • // 将敌方boss飞机的爆炸效果清除
  • isboom1 = false;
  • }
  • }
  • }).start();
  • /*
  • * 播放背景音乐
  • */
  • new Thread(new Runnable() {
  • @Override
  • public void run() {
  • // TODO 自动生成的方法存根
  • while(true) {
  • sound.play(stream);
  • }
  • }}).start();
  • /*
  • * 虫洞线程
  • */
  • new Thread(new Runnable() {
  • @Override
  • public void run() {
  • // TODO 自动生成的方法存根
  • // 分数达到一定值,出现虫洞
  • boolean insectT=true;
  • while(insectT) {
  • for(int s=0;s<1;s++) {
  • score[s]=score[s];
  • // 当分数大于100,启动虫洞,增加游戏难度
  • if(score[s]>=100)
  • {
  • ishole=true;
  • for(int i=0;i<insectnum;i++)
  • {
  • // 当圆虫碰到窗体,改变方向反弹回去
  • if(insectX[i]>JFW)
  • insectXDirect[i]=-1;
  • else if(insectX[i]<0)
  • insectXDirect[i]=1;
  • // 圆虫的移动速度
  • insectX[i]+=(i+1)*insectXDirect[i];
  • // 当圆虫碰到窗体,改变方向反弹回去
  • if(insectY[i]>JFH)
  • insectYDirect[i]=-1;
  • else if(insectY[i]<0)
  • insectYDirect[i]=1;
  • // 圆虫的移动速度
  • insectY[i]+=(i+1)*insectYDirect[i];
  • // 判断飞机是否碰到圆虫,碰到则生命值减2,然后圆虫从窗体外的随机位置出现,划入窗体,找飞机碰瓷
  • if((((insectX[i]+insectS[i])>=CX) && (insectX[i]+insectS[i]<=CX+LEN)) && ((insectY[i]+insectS[i]>=CY) && insectY[i]<=CY)) {
  • lifenum-=2;
  • insectX[i]=JFW+new Random().nextInt(20);
  • insectY[i]=0-new Random().nextInt(20);
  • }
  • else if(((insectX[i]>=CX) && (insectX[i]<=CX+LEN)) && ((insectY[i]+insectS[i]>=CY)&& insectY[i]<=CY)) {
  • lifenum-=2;
  • insectX[i]=0-new Random().nextInt(20);
  • insectY[i]=JFH;
  • }
  • else if((insectX[i]+insectS[i]>=CX)&&(insectX[i]+insectS[i]<=CX+LEN)&&((insectY[i]<=CY+LEN)&&(insectY[i]+insectS[i])>=CY+LEN)){
  • lifenum-=2;
  • insectX[i]=0-new Random().nextInt(20);
  • insectY[i]=0-new Random().nextInt(20);
  • }
  • else if((insectX[i]>=CX)&&(insectX[i]<=CX+LEN)&&((insectY[i]<=CY+LEN)&&(insectY[i]+insectS[i])>=CY+LEN)) {
  • lifenum-=2;
  • insectX[i]=JFW+new Random().nextInt(20);
  • insectY[i]=JFH+new Random().nextInt(20);
  • }
  • }
  • }
  • // 设置休眠时间
  • try {
  • Thread.sleep(50);
  • } catch (InterruptedException e) {
  • // TODO 自动生成的 catch 块
  • e.printStackTrace();
  • }sp.repaint();
  • }
  • }
  • }}).start();
  • }

小特点:设置虫洞

  • 在上面事件发生代码中有一个我们自己想出来增加游戏难度的东西:设置虫洞,当游戏分数到一定程度后,产生冲动,飞出来的小虫随机往各个方向飞,遇到窗体四周则被弹回,若英雄机碰到小虫则小虫消失,自身血量降低。

源码:

  • // 初始化圆虫属性
  • {
  • for(int i=0;i<insectnum;i++) {
  • // 圆虫移动方向参数设置
  • insectXDirect[i]=1;
  • insectYDirect[i]=1;
  • // 圆虫的随机大小
  • insectS[i]=new Random().nextInt(5)+25;
  • // 圆虫的随机位置
  • insectX[i]=holeX+holeS/2;
  • insectY[i]=holeY+holeS/2;
  • }
  • }
  • 在画板上画出虫洞代码:
  • //画出虫洞效果图 (在下方会判断是否画出虫洞圆虫,然后对ishole进行进行改变)
  • if(ishole) {
  • if(ishole) {
  • g.drawImage(new ImageIcon("./image/黑洞.png").getImage(), holeX, holeY,holeS,holeS,null);
  • // 画出一定数量的圆虫
  • for(int i=0;i<insectnum;i++) {
  • g.drawImage(new ImageIcon("./image/圆虫.png").getImage(),insectX[i],insectY[i],insectS[i],insectS[i],null);
  • }
  • }
  • }

音乐类

  • 播放背景音乐
  • public TestMusic(String filename) {
  • try {
  • //打开音频输入流
  • //从文件对象构建AudioInputStream stream,这个stream对象包含文件的格式数据和音频数据
  • AudioInputStream stream = AudioSystem.getAudioInputStream(new File(filename));
  • format = stream.getFormat();
  • //获得音频样本
  • samples = getSamples(stream);
  • } catch (UnsupportedAudioFileException ex) {
  • ex.printStackTrace();
  • } catch (IOException ex) {
  • ex.printStackTrace();
  • }
  • }
  • public byte[] getSamples() {
  • return samples;
  • }
  • private byte[] getSamples(AudioInputStream audioStream) {
  • // 获取要读取的字节数
  • int length = (int) (audioStream.getFrameLength() * format.getFrameSize());
  • // 阅读整个流
  • byte[] samples = new byte[length];
  • DataInputStream is = new DataInputStream(audioStream);
  • try {
  • is.readFully(samples);
  • } catch (IOException ex) {
  • ex.printStackTrace();
  • }
  • // 返回样品
  • return samples;
  • }
  • public void play(InputStream source) {
  • // 使用一个短的100ms(1/10秒)的缓冲区进行实时处理
  • // 切换到音频流
  • int bufferSize = format.getFrameSize() * Math.round(format.getSampleRate() / 10);
  • byte[] buffer = new byte[bufferSize];
  • // create a line to play to(创建播放线)
  • // SourceDataLine意思是"源数据流",是指AudioSystem的输入流,把音频文件写入到AudioSystem中,AudioSystem就会播放音频文件.
  • // TargetDataLine意思是"目标数据流",是指AudioSystem的输出流,是AudioSystem的target.
  • SourceDataLine line;
  • try {
  • DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
  • line = (SourceDataLine) AudioSystem.getLine(info);
  • // 打开管道入口端
  • line.open(format, bufferSize);
  • } catch (LineUnavailableException ex) {
  • ex.printStackTrace();
  • return;
  • }
  • // 启动线 line.start()打开管道的出口端
  • line.start();
  • // 将数据复制到线中
  • try {
  • int numBytesRead = 0;
  • while (numBytesRead != -1) {
  • numBytesRead = source.read(buffer, 0, buffer.length);
  • if (numBytesRead != -1) {
  • line.write(buffer, 0, numBytesRead);
  • }
  • }
  • } catch (IOException ex) {
  • ex.printStackTrace();
  • }
  • //等待所有数据播放,然后关闭线
  • //line.drain()将管道的出口端导入另一个地方将管道中剩余的数据流放空
  • line.drain();
  • //line.close()关住了管道的出口端.
  • line.close();
  • }

下载

【点击下载】

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门