Java在窗体实现飞机大战小游戏
newlw 人气:0小组项目
飞机大战:用 Java 语言在窗体上实现飞机大战小游戏,运行程序后,出现一个窗体,在窗体上用鼠标控制英雄机的移动,通过子弹打击敌机进行分数的计算,以及英雄机血量的计算等。
主要模块:登陆界面、音乐、子弹、敌机、英雄机、背景图、结束界面、BOSS 机、分数计算、血量计算。
负责模块:登陆界面、音乐、子弹、结束界面。
模块需求描述
登陆界面:运行程序后,弹出窗体,在窗体上显示关卡模式的选择,点击其中的模式后,开始游戏。
结束界面:重新选择关卡模式,即可开始游戏
音乐:登陆音乐,开始游戏音乐。
- 子弹的创建
- 子弹的发射
- 子弹的移动
- 一直向上:中间的子弹
- 左上方向:左边的子弹
- 右上方向:右边的子弹
4.子弹与敌机碰撞
5.子弹的类型升级
描述:当子弹打到道具机时,子弹一次发射的个数增加一个,最大为 3 个,当发射的个数为 3 时,子弹再打到道具机,子弹的类型就升一级,发射的个数置为 1,继续重新计算。第四种子弹只发射 3 个,发射后,子弹类型置为第三种子弹,第四种子弹无敌的,打到敌机不会消失。若期间英雄机被敌机碰到,子弹的类型置为 1,发射的个数置为 1。
类型:
- 第一种子弹:伤害值:1
- 第二种子弹:伤害值:2
- 第三种子弹:伤害值:3
- 第四种子弹:伤害值:100
6.子弹的一次发射个数的升级
描述:在子弹的类型升级中有涉及
类型:
- 一次发射一个子弹
- 一次发射两个子弹
- 一次发射三个子弹
7.子弹与敌机碰撞
描述:当子弹与敌机碰撞后,子弹消失,敌机消失,消灭敌机数增加
总体开发思想
主要的数据结构
集合:用集合来存储子弹的对象,子弹的发射是从集合中调出对象,子弹的消失是从集合中删除相应的子弹对象
List<Fire> fires = new ArrayList<Fire>();
移动与碰撞原理
子弹的移动:子弹图片在窗口中显示位置横纵坐标的改变
移动方向:
直向上:子弹的横坐标不变,纵坐标逐渐变大
左上方向:子弹的横坐标逐渐变小,纵坐标逐渐变大
右上方向:子弹的横坐标逐渐变大,纵坐标逐渐变大
子弹与敌机的碰撞:子弹的位置坐标在敌机图片的位置大小范围内
音乐播放原理
在音乐类中,使用文档输入流来读入音频,再使用多线程实现游戏登陆和播放音乐、游戏运行和播放音乐的同时进行,在主类中调用音乐播放的方法。
界面设计原理
运行程序后,游戏运行状态为 false,此时调用画板画出背景图,选中相应的模式后,游戏运行状态为 ture,登录界面切换为游戏运行界面,游戏结束后,游戏运行状态为 false,重新显示登录界面。
选择关卡模式:调用鼠标监听器,用鼠标点击相应的模式字体区域,获取到鼠标点击的相应坐标后,在相应的坐标区域中选着相应的关卡模式,关卡模式是根据每循环多少次创建一个敌机来实现的。
开发语言:Java
功能实现
1.登录与结束界面
在画板类中:
登陆界面的实现:
// 当游戏结束时, if (gameover) { //画游戏登陆时的界面 try { bg = App.getImg("/img/face.png"); } catch (IOException e) { printStackTrace();//捕获抛出异常 } drawImage(bg, 0 , 0, 512, 728, null);//画背景图片 //选择关卡模式(鼠标点击相应的位置进行操作) //画笔为黑色 setColor(Color.black); //字体大小和类型 setFont(new Font("楷体", Font.BOLD, 30)); //画的内容和位置 drawString("请选择关卡模式:", 130, 450); drawString("(鼠标点击相应的位置进行操作)", 40, 480); //画笔为蓝色 setColor(Color.blue); //字体大小和类型 setFont(new Font("楷体", Font.BOLD, 50)); //画的内容和位置 drawString("1、简单模式", 100, 550); drawString("2、普通模式" , 100, 600); drawString("3、困难模式" , 100, 650); }
读取关卡模式:
//当游戏结束时,读取鼠标的点击位置 if(gameover&&ms==0) { int x=e.getX();//获取鼠标的横坐标 int y=e.getY();//获取鼠标的纵坐标 if(y>=500&&y<550&&x>=100&&x<400) { ms=1;//模式 1 }else if(y>=550&&y<600&&x>=100&&x<400) { ms=2; //模式 2 }else if(y>=600&&y<650&&x>=100&&x<400) { ms=3; //模式 3 } // 刷新界面 repaint(); }
2.播放音乐
在音乐类中:
读取音乐文件的方法:
static Player player = null; static void play(String str) { try { File file = new File(str);//读取文件 FileInputStream fis = new FileInputStream(file); BufferedInputStream stream = new BufferedInputStream(fis);//读取流的转化 player = new Player(stream);//创建一个播放音乐类对象 player.play();//播放音乐 } catch (FileNotFoundException | JavaLayerException e1) { printStackTrace();//抛出捕获异常 } }
播放音乐的方法:
/* 播放音乐的线程 */ //游戏运行音乐 public void music1() { new Thread() { @Override public void run() { while (true) { System.out.println("播放音乐"); //如果游戏没结束就播放 if (!GamePanel.gameover) { Music.play("D:\\java文件\\飞机大战.mp3"); } } } } .start(); } //登陆音乐 public void music2() { new Thread() { @Override public void run() { Music.play("D:\\java文件\\mini.mp3"); } } .start(); }
在主类中:
//创建音乐类对象 Music music =new Music(); //播放登陆音乐 music.music2(); //播放游戏运行音乐 music.music1();
3.子弹
创建
子弹类中:
//hx、hy子弹的横纵坐标,dir子弹的移动方向,num子弹的类型 public Fire(int hx,int hy,int dir,int num) throws IOException { //确定子弹的图片 img=App.getImg("/img/fire"+num+".png"); //确定子弹火力的大小 if(num==1) { fr=1; } else if(num==2) { fr=2; } else if(num==3) { fr=3; } else if(num==4) { fr=100; } w=35; h=35; //确定子弹的位置(初始位置在英雄机上) x=hx; y=hy; this.dir=dir; this.num=num; }
在画板类中:
/* *创建子弹的方法 */ int findex = 0;// 记录shoot方法执行的次数 protected void shoot() throws IOException { findex++; if (findex == 20) {//减少创建的频率 if (power == 1) {//当火力值为1,即一次发射一颗子弹 // 创建子弹,num子弹的类型 Fire fire3 = new Fire(hero.x + 40, hero.y, 1, num); // 将子弹加入到弹药库中 fires.add(fire3); //当火力值为2,即一次发射两颗子弹 } else if (power == 2) { // 创建子弹 Fire fire1 = new Fire(hero.x + 10, hero.y, 1, num); // 将子弹加入到弹药库中 fires.add(fire1); // 创建子弹 Fire fire2 = new Fire(hero.x + 80, hero.y, 1, num); // 将子弹加入到弹药库中 fires.add(fire2); //当火力值为3,即一次发射三颗子弹 } else if (power == 3) { // 创建子弹 Fire fire1 = new Fire(hero.x, hero.y, 0, num); // 将子弹加入到弹药库中 fires.add(fire1); // 创建子弹 Fire fire2 = new Fire(hero.x + 50, hero.y - 20, 1, num); // 将子弹加入到弹药库中 fires.add(fire2); // 创建子弹 Fire fire3 = new Fire(hero.x + 100, hero.y, 2, num); // 将子弹加入到弹药库中 fires.add(fire3); //当火力值为4,即一次发射三颗无敌子弹 } else if (power == 4) { // 创建子弹 Fire fire1 = new Fire(hero.x+15, hero.y, 0, num); // 将子弹加入到弹药库中 fires.add(fire1); // 创建子弹 Fire fire2 = new Fire(hero.x, hero.y - 20, 1, num); // 将子弹加入到弹药库中 fires.add(fire2); // 创建子弹 Fire fire3 = new Fire(hero.x + 70, hero.y, 2, num); // 将子弹加入到弹药库中 fires.add(fire3); //power置为1,无敌子弹创建完后,变成类型3 power=1; num=3; } findex = 0;// 计数器归零 } } -
发射
在画板类中:
// 在窗体上画子弹 // 遍历集合,画出所有的敌机 for (int i = 0; i < fires.size(); i++) { // 获取每一个子弹 Fire fire = fires.get(i); //画出子弹 drawImage(fire.img, fire.x, fire.y, fire.w, fire.h, null); }
移动
子弹类中:
/* * 子弹移动的方法 */ public void move() { if(dir==0) { //左上 y=y-10; x=x-2; }else if(dir==1) { //直走 y=y-10; }else if(dir==2) { //右上 y=y-10; x=x+2; } }
碰撞敌机与升级
在画板类中: /* *判断一颗子弹是否击中了敌机 */ private void bang(Fire fire) { // 遍历所有的敌机 for (int i = 0; i < eps.size(); i++) { // 获取每一个敌机 Ep e = eps.get(i); // 判断该子弹是否击中敌机 if (e.shootBy(fire)) { // 如果敌机被子弹击中 // 如果不是导弹机(导弹机不会死亡,编号是15) if (e.type != 15) { // 1.让敌机的血量减少 hp=e.hp-fire.fr; // 当敌机的血量减少到零时,死亡 if (e.hp <= 0) { // 判断敌机是否是道具机(道具机编号为12,打死道具机,子弹会升级) if (e.type == 12) { // 增加火力值,即一次发射的子弹数 power++; // 如果power值大于3,增加英雄机血量,子弹类型升级 if (power > 3) { hero.hp++;//英雄机增加血量 if (hero.hp > 5) { hero.hp = 5; } //类型1-》类型2 if (num == 1) { num = 2; power=1; //类型2-》类型3 } else if (num == 2) { num = 3; power=1; //类型3-》类型4(创建完子弹类型4后,创建方法后面num置为3,power置为1) } else if(num==3) { num=4; power=4; } } } // 2.敌机死亡(消失:从敌机大本营中删除) eps.remove(e); // 3.增加分数 score =e.type+ score; //4.消灭的敌机数 Ep.number++; } // 4.子弹消失:如果不是类型4(类型4无敌的),就从子弹库中删除 if(num!=4) { fires.remove(fire); } } } } }
运行测试
登陆界面
发射子弹
子弹类型 1
子弹类型 2
子弹类型 3
子弹类型 4
总结
加载全部内容