完整项目已经放到github上,可以随意下载并直接运行,只求点个星github链接

JAVA实验作业要写一个战舰游戏就作了一个出来



实现战舰游戏的要点:

  • 如何让敌舰自动移动和发射子弹

思路:

  • 使用画笔Graphics类将找到的战舰图片添加到面板中,并控制这个战舰图片移动和发射子弹实现游戏操作
  • 当子弹碰到战舰时战舰就会死亡,若是敌舰剩余量少于一定数量就会自动产生新的敌舰;若是玩家战舰被子弹击中则游戏结束
  • 使用多线程将每一个敌舰、每一颗子弹都独立出一个线程使其可以互不干扰
  • 实现Runnable接口,通过run方法实现时刻监视子弹是否击中战舰

敌舰自动移动和发射子弹:
使用多线程将每一个敌舰形成一个独立的个体,从而每一个敌舰都互不影响分别执行相同的行为,将敌舰都添加到一个Vector的动态数组中,方便提取其中的一个敌舰,也方便随时添加新的敌舰进去。
通过实现Runnable接口,使用run方法不断执行操作,从而可在run方法中不断产生随机数,从而根据随机数的选择进行自动移动。
在run方法中每隔一定的移动次数就自动产生新的子弹出来,而子弹也创建独立的线程,每一颗子弹只需完成各自的移动就可以了。

public void run() {while(true) {try {Thread.sleep(50);}catch(Exception e) {}switch (direction) {         //上下左右都要有,不然无法移动case 7:          //数字可以随意设置{                         //向下移动for(int i=0;i<3;i++) {if(y<450) {y+=speed;try {Thread.sleep(100);  //控制移动速度}catch (Exception e) {}}}break;}case 2: {                   //向上移动for(int i=0;i<3;i++) {if(y>0) {y-=speed;try {Thread.sleep(100);}catch (Exception e) {}}}break;}case 5: {                    //向左移动for(int i=0;i<3;i++) {if(x>20) {x-=speed;try {Thread.sleep(100);}catch (Exception e) {}}}break;}case 3: {                   //向右移动for(int i=0;i<3;i++) {if(x<730) {x+=speed;try {Thread.sleep(100);}catch (Exception e) {}}}break;}default:break;                //其他情况不移动}count++;if(count%2==0&&islive&&bullets.size()<4)   //控制敌舰发射子弹频率和数量{Shot shot=new Shot(x+8,y-4,2);bullets.addElement(shot);Thread t=new Thread(shot);t.start();}if(count%10==0&&islive)            //敌舰存活时间越长移动速度越快{speed++;if(speed>=14)                //上限速度speed=14;}direction=(int)(Math.random()*10);    //随机数控制敌舰移动的方向if(islive==false)                   //敌舰死亡退出线程break;}}

完整代码如下:

public class Game {      //游戏主类public static void main(String[] args) {MyWindow a=new MyWindow();a.addKeyListener(new KeyAdapter() {public void keyReleased(KeyEvent e)         //不要用keyTyped容易监听不到{if(e.getKeyCode()==KeyEvent.VK_ESCAPE)    //按Esc退出程序                                                                                                                                       {System.exit(0);       //不能用dispose方法会一直出现对话框无法退出}}});}
}public class MyWindow extends JFrame {     //游戏窗口类MyPanel p;                               //游戏面板JPanel home;                          //开始画面面板File file=new File("飞机飞过特效.wav");    //不能是mp3格式URL url = null;URI uri = null ;AudioClip clip = null;MyWindow() {home=new JPanel();                   //开始画面add(home);home.setBounds(0, 0, 800, 600); ImageIcon icon=new ImageIcon("图片/开始画面.gif");icon.setImage(icon.getImage().getScaledInstance(800,600,Image.SCALE_DEFAULT));JLabel gameStart=new JLabel(icon);home.add(gameStart);gameStart.setBounds(0, 0, 800, 600);try {uri = file.toURI() ;      //直接使用URL是过时方法需要先使用URI转化url=uri.toURL();} catch (MalformedURLException e1) {}  clip=Applet.newAudioClip(url);clip.loop();                 //循环播放背景音乐,play方法只会放一遍gameStart.addMouseListener(new MouseAdapter()      //单击任意位置开始游戏{public void mouseClicked(MouseEvent e) {clip.stop();home.setVisible(false);        //先将开始画面不可视,否则看不到游戏画面startGame();                //添加游戏面板remove(home);               //将开始画面面板移除}}); setUndecorated(true);                       //取消标题看起来酷一点setBounds(500,200,800,600);setVisible(true);validate();setDefaultCloseOperation(MyWindow.EXIT_ON_CLOSE);}void startGame()               //创建游戏面板{p=new MyPanel();p.setFocusable(true);p.setVisible(true);Thread t = new Thread(p);t.start();add(p);addKeyListener(p);         //游戏面板需要添加键盘监听器}
}public class MyPanel extends JPanel implements KeyListener,Runnable{   //游戏面板类File file=new File("战斗背景音乐.wav");     //背景音乐File topGoal=new File("最高分.txt");          //本地文件记录游戏最高分URL url = null;URI uri = null ;AudioClip clip = null;PlayerShip hero=null; Vector<Enemy> enemy=new Vector<Enemy>();   //因为敌舰数量不定,用动态数组int num=7;                                  //初始敌舰数量int goal=0;                                    //记录击中敌舰的数量JLabel grade;                                //显示成绩MyPanel() {try {uri=file.toURI();    url = uri.toURL() ;} catch (MalformedURLException e1) {}clip=Applet.newAudioClip(url);clip.loop();                            //循环播放背景音乐setFocusable(true);setLayout(null);                       //不使用null布局无法控制标签的位置grade=new JLabel("0");  grade.setBounds(700,500, 100, 100);grade.setFont(new java.awt.Font("24",20,50));   grade.setForeground(Color.WHITE);add(grade);hero=new PlayerShip(400,500);                  //创建一个玩家战舰for(int i=0;i<num;i++) {                        //创建num个敌舰Enemy enemys=new Enemy((i+1)*100,0);        //控制每个敌舰间的距离Thread t=new Thread(enemys);               //每一个敌舰都要用一个独立的线程控制t.start();enemy.add(enemys);                         //将敌舰添加到动态数组中}}public void paintComponent(Graphics g)               //创建一个画笔{ImageIcon background = new ImageIcon("游戏背景.gif");   // 获取背景图片的路径ImageIcon image1 = new ImageIcon("战舰.png") ;         // 获取战舰图片的路径ImageIcon image2 = new ImageIcon("敌舰.png") ;         // 获取敌舰图片的路径g.drawImage(background.getImage(), 0, 0, 800, 600, null);   // 画游戏背景for(int i=0;i<enemy.size();i++)           //画敌舰{Enemy em=enemy.get(i);               //先将动态数组中的敌舰赋值给一个临时对象if(em.islive) {                        //当前敌舰存活才继续画g.drawImage(image2.getImage(), enemy.get(i).getX(), enemy.get(i).getY(), 70, 70, null) ;    //画敌舰for(int j=0;j<em.bullets.size();j++) {   //画当前敌舰发射出的子弹Shot s=em.bullets.get(j);     //先将动态数组中的子弹赋值给一个临时对象if(s.islive) {                 //当前子弹存活才继续画g.setColor(Color.green);g.fillRect(s.x,s.y+50, 5, 5);      //一定要是临时对象子弹的坐标}else    em.bullets.remove(s);       //当前子弹死亡就将其移除动态数组}}}if(hero.islive)         //玩家战舰仍存活才画g.drawImage(image1.getImage(), hero.getX(), hero.getY(), 70, 70, null) ;     //画玩家战舰for(int i=0;i<hero.bullets.size();i++)     //画玩家子弹{Shot myShot=hero.bullets.get(i);if(myShot.islive==true) {g.setColor(Color.WHITE);g.fillRect(myShot.x,myShot.y, 5, 5);    //一定要是myShot的坐标要不然只会显示一个子弹}if(myShot.islive==false) {     //当前子弹死亡就将其移除动态数组hero.bullets.remove(myShot);           }}} public void hitEnemy(Shot shot,Enemy enemy)         //判断玩家战舰的子弹是否击中敌舰{if(shot.x>=enemy.x-16&&shot.x<=enemy.x+35&&shot.y<=enemy.y+35) {shot.islive=false;         //击中敌舰则该子弹死亡enemy.islive=false;            //击中则该敌舰死亡goal++;                     //每击中一个敌舰就得一分grade.setText(""+goal);}}public void hitHero(Shot shot,PlayerShip hero)     //判断敌舰的子弹是否击中玩家战舰{if(shot.x>=hero.x+10&&shot.x<=hero.x+50&&shot.y>=hero.y-50&&shot.y<=hero.y+20) {shot.islive=false;            //击中玩家战舰则该子弹死亡hero.islive=false;           //击中则玩家战舰死亡}}public void keyTyped(KeyEvent e) {}public void keyPressed(KeyEvent e)      //通过监视器处理移动、发射子弹问题{ if(e.getKeyCode()==KeyEvent.VK_UP) {      //向上移动hero.moveUp();}else if(e.getKeyCode()==KeyEvent.VK_DOWN) {  //向下移动hero.moveDown();}else if(e.getKeyCode()==KeyEvent.VK_LEFT) {    //向左移动hero.moveLeft();}else if(e.getKeyCode()==KeyEvent.VK_RIGHT) { //向右移动hero.moveRight();}repaint();                            //改变坐标后要重新画一遍}public void keyReleased(KeyEvent e) {if(e.getKeyCode()==KeyEvent.VK_F1) //按F1关闭背景音乐{clip.stop();}if(e.getKeyCode()==KeyEvent.VK_F2)   //按F2开启背景音乐{clip.loop();}if(e.getKeyCode()==KeyEvent.VK_SPACE)    //按空格发射子弹{hero.OpenFire();}repaint();}public void run()             //不断监视游戏状态  {while(true) {try {Thread.sleep(100);}catch(Exception e) {}for(int i=0;i<hero.bullets.size();i++)     //因为要不断监视则在run方法中检测是否击中{Shot shot=hero.bullets.get(i);if(shot.islive) {for(int j=0;j<enemy.size();j++) { //每一颗子弹要与所有的敌舰都进行判断Enemy e=enemy.get(j);if(e.islive) {hitEnemy(shot,e);if(e.islive==false)           //敌舰被击中则移除该敌舰{enemy.remove(e);if(enemy.size()<4)     //敌舰数量少于4就会自动补充{for(int k=0;k<4;k++) {Enemy et=new Enemy((k+2)*100,0);  enemy.add(et);Thread t1=new Thread(et);t1.start();}}}} }}}loop:for(int i=0;i<enemy.size();i++)       //判断敌舰是否击中玩家战舰{Enemy em=enemy.get(i);for(int j=0;j<em.bullets.size();j++) {  //每一个敌舰要和所有的玩家子弹检测Shot shot=em.bullets.get(j);if(shot.islive) {hitHero(shot,hero);if(hero.islive==false)         //玩家战舰被击中就跳出所有的循环break loop;}}}repaint();if(hero.islive==false)               //玩家战舰死亡则结束游戏{clip.stop();                  //游戏结束音乐停try {FileReader in1=new FileReader(topGoal);      //比较历史最佳成绩并更新成绩BufferedReader in2=new BufferedReader(in1);String s=in2.readLine();int top=Integer.parseInt(s);   //将文件中最佳成绩导出并转化为int类型if(goal>top) {          //本次游戏记录超过历史最佳就刷新文件中的数据FileWriter out1=new FileWriter(topGoal);BufferedWriter out2=new BufferedWriter(out1);out2.write(""+goal);       //创造新成绩就储存到文件中out2.flush();out2.close();out1.close();JOptionPane.showMessageDialog(this, "更新历史最佳成绩:"+goal,"得分",JOptionPane.WARNING_MESSAGE);        //弹出消息对话框提示游戏结束}else{JOptionPane.showMessageDialog(this, "最终成绩为:"+goal+"    历史最佳成绩:"+top,"得分",JOptionPane.INFORMATION_MESSAGE);}in2.close();in1.close();}catch(Exception e) {}Game.main(null);           //回到开始界面break;}}}
}public class Warship {         //战舰类int x=0;                  //通过坐标确定战舰的位置int y=0;int speed=8;             //控制战舰移动的速度Warship(int x,int y) {this.x=x;this.y=y;}public void setX(int x) {this.x=x;}public void setY(int y) {this.y=y;}public int getX() {return x;}public int getY() {return y;}
}public class PlayerShip extends Warship{       //玩家战舰类Vector<Shot> bullets=new Vector<Shot>();    //通过动态数组存储子弹达到连续发射Shot bullet=null;boolean islive=true;public PlayerShip(int x,int y) {super(x,y);}public void OpenFire()                     //发射子弹方法{this.bullet=new Shot(x+33,y-2,1);        bullets.add(bullet);Thread t=new Thread(bullet);           //创建线程控制子弹t.start();        }//战舰通过坐标的改变进行移动public void moveUp()                    //上{if(y>5)                              //防止超出屏幕范围y-=speed;}public void moveDown()                 //下{if(y<530)y+=speed;}public void moveLeft()                  //左{if(x>0)x-=speed;}public void moveRight()                    //右{if(x<730)x+=speed;}
}public class Enemy extends Warship implements Runnable{        //敌舰类boolean islive=true;                                  //控制敌舰是否存在int direction;                                            //控制移动方向int count=0;                                           //控制敌舰发射子弹Vector<Shot> bullets=new Vector<Shot>();         //通过动态数组存储子弹达到连续发射public Enemy(int x,int y) {super(x,y);speed=8;                           //初始敌舰移动速度}public void run() {while(true) {try {Thread.sleep(50);}catch(Exception e) {}switch (direction) {         //上下左右都要有,不然无法移动case 7:          //数字可以随意设置{                         //向下移动for(int i=0;i<3;i++) {if(y<450) {y+=speed;try {Thread.sleep(100);  //控制移动速度}catch (Exception e) {}}}break;}case 2: {                   //向上移动for(int i=0;i<3;i++) {if(y>0) {y-=speed;try {Thread.sleep(100);}catch (Exception e) {}}}break;}case 5: {                    //向左移动for(int i=0;i<3;i++) {if(x>20) {x-=speed;try {Thread.sleep(100);}catch (Exception e) {}}}break;}case 3: {                   //向右移动for(int i=0;i<3;i++) {if(x<730) {x+=speed;try {Thread.sleep(100);}catch (Exception e) {}}}break;}default:break;                //其他情况不移动}count++;if(count%2==0&&islive&&bullets.size()<4)   //控制敌舰发射子弹频率和数量{Shot shot=new Shot(x+8,y-4,2);bullets.addElement(shot);Thread t=new Thread(shot);t.start();}if(count%10==0&&islive)            //敌舰存活时间越长移动速度越快{speed++;if(speed>=14)                //上限速度speed=14;}direction=(int)(Math.random()*10);    //随机数控制敌舰移动的方向if(islive==false)                   //敌舰死亡退出线程break;}}
}public class Shot implements Runnable{         //子弹类int x;int y;int direction;                             //判断子弹来自玩家还是敌舰int speed=5;                             //子弹移动速度boolean islive=true;                       //判断子弹是否超出屏幕范围public Shot(int x,int y,int direction) {this.x=x;this.y=y;this.direction=direction;}public void run() {while(true) {try {Thread.sleep(50);             //通过暂停防止子弹直接飞出屏幕}catch(Exception e) {}switch (direction) {case 1:                           //1为玩家战舰子弹的方向{y-=speed;                    //子弹向上走break;                       //没有break子弹原地不动}                case 2:                         //2为敌舰子弹的方向{y+=speed;                 //子弹向下走break;}      }if(y<0||y>600)                       //如果子弹超出屏幕子弹就死亡{this.islive=false;break;}}}
}

缺点:
玩家战舰移动不流畅,因为键盘事件一次只能执行一个,一次只能移动一个方向,放开键盘后才能再进行其他方向的移动。设想过的解决方法:

  1. 将键盘事件改为鼠标事件,通过鼠标的移动带动玩家战舰的移动
  2. 创建四个线程分别控制每一个方向的移动

这个游戏还有很多可以完善的地方,只是暂时有点不想再改了,如果有机会的话会改进出更好的版本出来。如果有人想要借鉴一下我的想法或者有什么补充的地方,请在评论中和我说一下。

JAVA实现战舰游戏相关推荐

  1. 用java编写战舰 游戏吗_java – 战舰游戏 – 船舶重叠

    我正在使用ACM库在 Java中编写一个简单的战舰游戏. 游戏开始后,应该将船只放在画布上的随机位置,但问题是船只可能会互相覆盖,这在游戏中是不允许的.如何避免将船放在彼此之上? 我的代码是: pri ...

  2. 用java编写战舰 游戏吗_如何在Java中正确建模战舰游戏

    我正在尝试为我的小组在大学里做的"游戏"项目创建战舰游戏.我之前从未真正使用过GUI,几乎所有输出都在Eclipse控制台中. 首先,我创建了一个GUI类,它实际上是我的" ...

  3. 雷霆战舰 游戏简化版

    雷霆战舰飞机游戏简化版 class MyGameFrame: import java.awt.Color;import java.awt.Font; import java.awt.Frame; im ...

  4. java通用象棋游戏_在通用国际象棋界面周围模拟GraphQL包装器

    java通用象棋游戏 The Universal Chess Interface (UCI) has been around a long time and used by many chess en ...

  5. JAVA实现拼图游戏

    JAVA实现拼图游戏 package org.test; /**  * <p>Title: LoonFramework</p>  * <p>Description: ...

  6. java 3d游戏_不放一行代码分享一下java实现3D游戏逻辑

    这篇日记是对最近几周Java大作业写的一个3D打怪挖矿游戏进行记录和总结.另一个目的也是因为我发现身边很多朋友对3D游戏逻辑很有兴趣.所以写这篇日记可以介绍一下一个3D游戏是如何实现基础功能的.即使没 ...

  7. java生命小游戏_Java修炼——飞机生存小游戏

    在学习了java入门的课程之后,自己动手跟着老师写的一个小游戏,用的是Frame.总共有七个类. 1.飞机游戏的主窗口(MyGameFrame)继承Frame. package com.bjsxt.p ...

  8. java游戏暂停弹出字体_小白写了个java的小游戏 想加个暂停的功能 无从下手 求大佬们帮...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 第一次写java的小游戏 想实现点击右下角的暂停 实现游戏的暂停和继续 不知道该怎么加,自己找了线程的内容但试了还是成功不了,求大佬们帮一下小白.代码有点 ...

  9. 用JAVA制作小游戏——飞机大战(三)

    本篇博客是对飞机大战游戏项目完整代码的展示 详细代码讲解: 用JAVA制作小游戏--飞机大战(一) 用JAVA制作小游戏--飞机大战(二) 最下方附整个程序的文件下载链接 代码展示 主界面 impor ...

  10. 用JAVA制作小游戏——飞机大战(二)

    本篇博客是对飞机大战游戏使用代码的展示 重难点: 首先需要鼠标能够控制战机,使鼠标在窗口内时始终能够使战机的位置与鼠标相同,实现鼠标控制战斗机移动. 其次需要能够以一定的速度产生子弹和敌机,并且以一定 ...

最新文章

  1. 【原】[webkit移动开发笔记]之如何去除android上a标签产生的边框
  2. HTML基础(part5)--常用标签之重文本标签
  3. 超声换能器的原理及设计_超声波发生器、变幅杆、焊头的匹配介绍
  4. vue 跳添加编辑页面传两个值_vuecli3开发多页面项目
  5. python 函数可以作为容器对象的元素_14、函数对象和闭包
  6. html5的canvas动画,Canvas HTML5简介 · Canvas动画教程
  7. 南京林业大学计算机科学技术,南京林业大学信息科学技术学院
  8. 菜鸟学Linux 第031篇笔记 script,控制,while,function
  9. 这3件事发生后,我彻底给 Python“跪了”!
  10. Qt QT_BEGIN_NAMESPACE
  11. 搞懂分布式技术开篇:浅析分布式系统的架构及常用方案
  12. 汇编语言属于计算机科学,汇编语言是一种依赖于计算机的低级程序设计语言吗...
  13. 360宽带测速至少在我的网络环境里有设计缺陷
  14. 3D视频调校技术解决之道重点在3D眼镜
  15. 希捷硬盘查询保修期限的网址
  16. HTC one/M7电信802d 毒蛇ViperOne2.1.0/高级毒蛇工具/完美root,精简/更多自定义,稳定,流畅ROM
  17. 【ERP软件】ERP体系二次开发有哪些危险?
  18. mysql client_multi_statements_MySQL中CLIENT_MULTI_STATEMENTS的用法
  19. python计算器程序设计课程报告_20193120 2019-2020-2 《Python程序设计》实验二报告
  20. 《调教命令行04》触碰Linux的每个角落(长文)

热门文章

  1. 内网渗透靶场(上)加入目标网段,抓取管理员密码 #zkaq
  2. 梯度消失,梯度爆炸产生的原因及解决办法
  3. 【计算理论】图灵机 ( 图灵机设计 )
  4. [Codeforces1148C]Crazy Diamond——构造
  5. 需要一款管理链接的软件
  6. Validation校验属性格式
  7. 必须知道的C语言知识细节:单引号和双引号正确用法
  8. hdu5064 dp
  9. android测试基站,Android iPhone 手机查看基站信息
  10. selenium简单模拟百度搜索点击器