【小白学习之路】Java实现简单的飞机大战小游戏

    技术2022-07-14  113

    飞机大战小游戏

    目录

    项目介绍框架搭建代码实现总结分析

    前言: 前一段时间写了一个仿QQ的聊天室,主要涉及Java通信有关的知识,今天写的这个飞机大战主要是复习之前写过的,这次我会加入一些其他的元素和对界面进行一些完善。

    这篇博客我会写的比较通透,主要是自己用来复习和巩固知识点的,所以大家如果感兴趣的话,可以参考我的这篇博客!特别是正在学习Java的同学哦!!!

    项目介绍

    实现飞机大战设计的知识点还是比较多的,所以特别推荐编程小白先上手这种简单的游戏,这样既可以巩固简单的Java基础知识,又可以实现自己编写的小作品,展现自己的能力,何乐而不为呢?下面我就简单地介绍一下实现飞机大战要了解和使用的相关知识吧ƪ(˘⌣˘)ʃ

    继承机制 一. 为什么要用继承? 简单说:首先要实现飞机大战,根据Java面向对象编程的特性,我们就必须明白整个游戏有哪几个对象?不难知道有:自己的战机、敌机、子弹(敌机和我机子弹)和背景。观察这几个对象可以知道,它们都有一些共同的属性,如战机和敌机的血量、它们的坐标和移动的方法等等。 由上所述,我们可以合理地采用接口或者抽象类来让子类继承,这样可以充分地复用代码,大大地减少了代码的冗余。让我们更快地完成飞机大战这个小游戏。 二.如何使用继承? 对于为什么要用继承上面我已经说明了,下面就详详细说一下接口和抽象类。我们都知道,但我们用extends去继承一个类的时候,子类就拥有了父类的属性和方法,自然就可以去调用。同时我们也可以覆写父类的方法(如果父类的方法比较不具体),这里就有一个名词:抽象类,该类本身就要声明为abstract,同时抽象的方法也要声明。如果我们就是想要一个十分抽象的类,该类中的方法全部是抽象的方法(只是定义了方法的名称,没有方法体的方法),目的是为了子类可以继承该类从而覆写其中的的所有方法,我们把这个类称为接口,我们用interface来定义接口,implement来实现接口。 接口和抽象类的比较: 从上面可知,按抽象的程度来比较,一般的类<抽象类<接口,下面简单说一下接口和抽象类用法的比较: 大家可以参考这篇博客:java面向对象编程技术详解监听事件 我们都知道,在飞机大战游戏中我们要用鼠标点击开始游戏和停止游戏的按钮,而且我们要通过键盘操控飞机的移动和开火。这里就要用到鼠标点击监听器和键盘监听器,有童鞋可能也会用鼠标移动监听器来控制飞机的运动。不管怎么用,这些监听都是接口,我们用implement实现其中的方法就可以啦!!!
    框架搭建

    综合前面的分析我们就可以搭建一个简单的框架:

    Entity.java:接口,功能:定义子类共有的抽象的方法:移动、画图、设置和获得坐标。MyFeiji.java:自己的战机类,功能:实现接口中的方法,控制移动和检测是否是受到攻击。DiJi.java:敌机类,功能:实现接口中的方法,随机产生敌机并设置敌机相关的一些属性。MyFeiJiBullet.java:战机炮弹类,功能:实现接口中的方法,检测是否攻击到敌方。DiJiBullet.java:敌机炮弹类,功能:实现接口中的全部方法,同时要控制边界。BackGroundPhotosMusic.java:背景图片音乐类,功能:实现接口中的方法,画出移动的图片、一些界面的设置。MainUI.java:主界面类,功能:创建队列控制所有的对象的移动和画图,同时实现键盘监听器控制战机的移动和发射炮弹。RemoveThread.java:去除线程类,功能:创建线程来实现对越界子弹敌机的去除,控制飞机的碰撞。 上面就是大致的飞机大战的一个框架,对于这种封装性比较强的代码,我们接下来的编写是比较容易的,让我们来实现它吧!
    代码实现
    Entity.java:接口 /** * 接口 * @author 梦想少年 * 定义子类共有的抽象的方法:移动、画图、设置和获得坐标 */ public interface Entity { //移动方法 public void move(); //画图的方法 public void draw(Graphics g); //设置和得到X和Y坐标的方法 public void setX(int startX); public void setY(int startY); public int getX(); public int getY(); } MyFeiji.java:自己的战机类 /** * 自己的战机类 * @author 梦想少年 * 实现接口中的方法,控制移动和检测是否是受到攻击 */ public class MyFeiJi implements Entity { //控制飞机上下左右移动 boolean up=false; boolean down=false; boolean left=false; boolean right=false; private int x,y; //得分和血量 private int scores; private int hp; //我机图片 private Image image_myfeiji; public MyFeiJi(){ image_myfeiji=new ImageIcon("D:\\常用\\图片\\" + "Camera Roll\\image\\战机.png").getImage(); } //移动界限 public void move() { if(x<=40){ x=40; } if(x>=1790){ x=1790; } if(y<=100){ y=100; } if(y>=910){ y=910; } //移动速度 if(up){ y-=3; } if(down){ y+=3; } if(left){ x-=4; } if(right){ x+=3; } } public void draw(Graphics g) { g.setFont(new Font("黑体",Font.BOLD, 35)); g.setColor(Color.RED); g.drawString("我的血量:"+hp,30,90); g.setFont(new Font("黑体",Font.BOLD, 35)); g.setColor(Color.RED); g.drawString("我的得分:"+scores,30,140); g.drawImage(image_myfeiji, x, y, null); } //判断是否输赢 public boolean isDefeat(){ if(hp<=0){ return true; }else{ return false; } } //设置和获得坐标的方法 public void setX(int startX) { this.x=startX; } public void setY(int startY) { this.y=startY; } public int getX() { return x; } public int getY() { return y; } //检测我的飞机是否被敌机子弹击中 public boolean isShootByDiJiBullet(DiJiBullet dijibullet){ int x1=this.x;//我的飞机x坐标 int y1=this.y;//我的飞机y坐标 int width1=this.image_myfeiji.getWidth(null);//我机的宽度 int height1=this.image_myfeiji.getHeight(null);//我机的高度 int x11=x1+width1/2; int y11=y1+height1/2;//确定中心位置 //敌机的横纵坐标和高度 int x2=dijibullet.getX(); int y2=dijibullet.getY(); int width2=dijibullet.getDiJiBulletWidth(); int height2=dijibullet.getDiJiBulletHeight(); int x22=x2+width2/2; int y22=y2+height2/2; //计算距离 int distanceX=Math.abs(x22-x11); int distanceY=Math.abs(y22-y11); //是否碰撞 if(distanceX<=30&&distanceY<=25){ return true; }else{ return false; } } //检测我的飞机是否被敌机碰撞 public boolean isShootByDiJi(Diji diji){ int x1=this.x;//我的飞机x坐标 int y1=this.y;//我的飞机y坐标 int width1=this.image_myfeiji.getWidth(null);//我机的宽度 int height1=this.image_myfeiji.getHeight(null);//我机的高度 int x11=x1+width1/2; int y11=y1+height1/2;//确定中心位置 //敌机的横纵坐标和高度 int x2=diji.getX(); int y2=diji.getY(); int width2=diji.getDiJiWidth(); int height2=diji.getDiJiHeight(); int x22=x2+width2/2; int y22=y2+height2/2; //计算距离 int distanceX=Math.abs(x22-x11); int distanceY=Math.abs(y22-y11); //是否碰撞 if(distanceX<=100&&distanceY<=100){ return true; }else{ return false; } } //掉血方法 public void subBlood(){ this.hp--; } public void subDoubleBlood(){ this.hp-=5; } //加分方法 public void addScores(){ scores+=5; } public void addDoubleScores(){ scores+=10; } //设置血量 public void setHP(int hp){ this.hp=hp; } public int getHP(){ return hp; } } DiJi.java:敌机类 /** * 敌机类 * @author 梦想少年 * 实现接口中的方法,随机产生敌机并设置敌机相关的一些属性 */ public class Diji implements Entity{//敌机 private int x,y; //控制敌机可以追踪战机 private int automaticMove; //判断敌机是否爆炸 private boolean isDied; //爆炸音乐 File musicFile; //敌机图片 private Image dijiImage; //爆炸图片 private Image diedImage; //产生子弹的数量 private int dijiBulletCount; //初始化 public Diji(){ musicFile=new File("C:\\Users\\梦想少年\\Music\\" + "AudioConvert\\大爆炸.wav"); dijiImage=new ImageIcon("D:\\常用\\图片\\" + "Camera Roll\\image\\diji.png").getImage(); diedImage=new ImageIcon("D:\\常用\\图片\\" + "Camera Roll\\image\\1\\7.png").getImage(); Random random=new Random(); x=random.nextInt(100)+1900; y=random.nextInt(800)+80; } //移动方法 public void move() { if(automaticMove==1){ y--; } if(automaticMove==2){ y++; } x-=2; } //画出敌机 public void draw(Graphics g) { g.drawImage(dijiImage,x,y,128,128,null); if(isDied){ g.drawImage(diedImage, x, y, null); } } //判断是否越界 public boolean isOutBounds(){ if(x<0){ return true; }else{ return false; } } //设置飞机炮炸的方法 public void Blast(){ isDied=true; } //打开敌机炮炸音乐 @SuppressWarnings("deprecation") public void startMusic(){ URL url; try { url = musicFile.toURL(); AudioClip aud; aud=Applet.newAudioClip(url); aud.play(); try { Thread.sleep(1000); } catch (InterruptedException e) { //TODO Auto-generated catch block e.printStackTrace(); } aud.stop(); } catch (MalformedURLException e) { //e.printStackTrace(); } } //获得和设置坐标 public void setX(int startX) { this.x=startX; } public void setY(int startY) { this.y=startY; } public int getX() { return x; } public int getY() { return y; } //发射子弹计数器和获得产生子弹的数量 public void addBulletCount(){ dijiBulletCount++; } public int getBulletCount(){ return dijiBulletCount; } //获得敌机子弹的高度和宽度 public int getDiJiHeight(){ return dijiImage.getHeight(null); } public int getDiJiWidth(){ return dijiImage.getWidth(null); } } MyFeiJiBullet.java:战机炮弹类 /** * 飞机子弹类 * @author 梦想少年 * 实现接口中的方法,检测是否攻击到敌方 */ public class MyFeiJiBullet implements Entity { //子弹类型 private int bulletType; //坐标 private int x,y; //子弹图片 Image image; //初始化图片 public MyFeiJiBullet(){ image=new ImageIcon("D:\\常用\\图片\\" + "Camera Roll\\image\\bullet2.png").getImage(); } //移动 public void move() { x+=7; } //画图 public void draw(Graphics g) { if(bulletType==1){ g.drawImage(image, x, y, 100, 100, null); } } //检测是否越界 public boolean isOutBounds(){ if(x>1920){ return true; }else{ return false; } } //设置子弹类型的方法 public void setBulletType(int bulletType){ this.bulletType=bulletType; } //设置和获得坐标的方法 public void setX(int startX) { this.x=startX; } public void setY(int startY) { this.y=startY; } public int getX() { return x; } public int getY() { return y; } //检测我的飞机是否被敌机子弹击中 public boolean isShootDiJiBullet(DiJiBullet dijibullet){ int x1=this.x;//我的子弹x坐标 int y1=this.y;//我的子弹y坐标 int width1=this.image.getWidth(null);//我的子弹宽度 int height1=this.image.getHeight(null);//我的子弹高度 int x11=x1+width1/2; int y11=y1+height1/2;//确定中心位置 //敌机的横纵坐标和高度 int x2=dijibullet.getX(); int y2=dijibullet.getY(); int width2=dijibullet.getDiJiBulletWidth(); int height2=dijibullet.getDiJiBulletHeight(); int x22=x2+width2/2; int y22=y2+height2/2; //计算距离 int distanceX=Math.abs(x22-x11); int distanceY=Math.abs(y22-y11); //是否碰撞 if(distanceX<=200&&distanceY<=100){ return true; }else{ return false; } } //检测我的飞机是否被敌机碰撞 public boolean isShootDiJi(Diji diji){ int x1=this.x;//我的子弹x坐标 int y1=this.y;//我的子弹y坐标 int width1=this.image.getWidth(null);//我的子弹宽度 int height1=this.image.getHeight(null);//我的子弹高度 int x11=x1+width1/2; int y11=y1+height1/2;//确定中心位置 //敌机的横纵坐标和高度 int x2=diji.getX(); int y2=diji.getY(); int width2=diji.getDiJiWidth(); int height2=diji.getDiJiHeight(); int x22=x2+width2/2; int y22=y2+height2/2; //计算距离 int distanceX=Math.abs(x22-x11); int distanceY=Math.abs(y22-y11); //是否碰撞 if(distanceX<=100&&distanceY<=100){ return true; }else{ return false; } } } DiJiBullet.java:敌机炮弹类 /** * 敌机子弹类 * @author 梦想少年 * 实现接口中的全部方法,同时要控制边界 */ public class DiJiBullet implements Entity { private int x,y; private Image image; //初始化 public DiJiBullet(){ image=new ImageIcon("D:\\常用\\图片\\" + "Camera Roll\\image\\1\\5.PNG").getImage(); } //移动的方法 public void move() { x-=3; } //画图的方法 public void draw(Graphics g) { g.drawImage(image, x, y, null); } //检测是否越界 public boolean isOutBounds(){ if(x<0){ return true; }else{ return false; } } //设置和获得坐标的方法 public void setX(int startX) { this.x=startX; } public void setY(int startY) { this.y=startY; } public int getX() { return x; } public int getY() { return y; } //获得敌机子弹的高度和宽度 public int getDiJiBulletHeight(){ return image.getHeight(null); } public int getDiJiBulletWidth(){ return image.getWidth(null); } } BackGroundPhotosMusic.java:背景图片类 /** * 背景图片音乐类 * @author 梦想少年 * 实现接口中的方法,画出移动的图片、一些界面的设置 */ public class BackGroundPhotosMusic implements Entity{//添加背景 private int x,y; private Image image; //背景音乐(一定要wav格式的音乐才有效) private AudioClip audio; //播放关闭音乐字符串和状态 private boolean isMusic; private String musicString; //游戏状态 private boolean isGame; private String gameString; //初始化背景图片 public BackGroundPhotosMusic(){ image=new ImageIcon("D:\\常用\\图片\\" + "Camera Roll\\image\\bg11.jpg").getImage(); File musicFile=new File("C:\\Users\\梦想少年\\Music\\" + "AudioConvert\\薛之谦 - 天后 (Live).wav"); try { audio=Applet.newAudioClip(musicFile.toURI().toURL()); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //移动背景 public void move() { x--; } //画出背景 public void draw(Graphics g) { if((x+image.getWidth(null)<=0)){ x=0; } g.drawImage(image, x, y, 1920, 1080, null); g.drawImage(image, x+image.getWidth(null), y, 1920, 1080, null); //相关设置 g.setFont(new Font("黑体",Font.BOLD,30)); g.setColor(Color.BLUE); g.drawString("游戏设置",30,180); //音乐启停 g.setFont(new Font("黑体",Font.BOLD,20)); g.setColor(Color.RED); g.drawString(musicString,35,220); g.setColor(Color.WHITE); g.drawRect(35,200,85,25); //暂停游戏 g.setFont(new Font("黑体",Font.BOLD,20)); g.setColor(Color.RED); g.drawString(gameString,35,250); g.setColor(Color.WHITE); g.drawRect(35,230,85,25); //退出游戏 g.setFont(new Font("黑体",Font.BOLD,20)); g.setColor(Color.RED); g.drawString("退出游戏",35,280); g.setColor(Color.WHITE); g.drawRect(35,260,85,25); } public void setX(int startX){} public void setY(int startY){} public int getX() { return 0; } public int getY() { return 0; } //播放音乐 public void startMusic(){ if(!isMusic){ audio.loop(); musicString="暂停音乐"; isMusic=true; }else{ audio.stop(); musicString="打开音乐"; isMusic=false; } } //游戏停止 public void StartGame(){ if(!isGame){ gameString="暂停游戏"; isGame=true; }else{ gameString="开始游戏"; isGame=false; } } //返回游戏状态 public boolean gameState(){ return isGame; } } MainUI.java:主界面类 /** * 主界面类 * @author 梦想少年 * 创建队列控制所有的对象的移动和画图,同时实现键盘监听器控制战机的移动和发射炮弹 * 其他功能(1.开始界面2.游戏界面3.背景音乐和爆炸音乐) */ public class MainUI implements KeyListener,MouseListener{ //创建主队列 ArrayList<Entity> wholelist=new ArrayList<>(); public static void main(String[] args){ MainUI ui=new MainUI(); ui.showUI(); } //创建飞机对象 MyFeiJi myfeiji=new MyFeiJi(); //创建背景对象 BackGroundPhotosMusic background=new BackGroundPhotosMusic(); //主界面 public void showUI(){ JFrame jframe=new JFrame("雷霆战机"); jframe.setSize(1920, 1080); jframe.setLayout(new FlowLayout()); jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jframe.setLocationRelativeTo(null); jframe.addKeyListener(this); jframe.addMouseListener(this); jframe.setVisible(true); //将背景对象加入主队列 background.startMusic(); background.StartGame(); wholelist.add(background); //将玩家飞机加入队列,注意顺序,避免画图覆盖 myfeiji.setX(300); myfeiji.setY(500); myfeiji.setHP(100); wholelist.add(myfeiji); //开启清除线程 RemoveThread remove=new RemoveThread(wholelist); remove.start(); //定时产生敌机&&&及它的子弹 Timer timer=new Timer(); timer.schedule(new TimerTask() { public void run(){ //敌机 Diji diji1=new Diji(); wholelist.add(diji1); //敌机子弹 for(int i=0;i<=30;i++){ DiJiBullet dijizidan1=new DiJiBullet(); //设置初始坐标 dijizidan1.setX(diji1.getX()-20); dijizidan1.setY(diji1.getY()+45); //子弹计数加1 diji1.addBulletCount(); wholelist.add(dijizidan1); //控制子弹的数量 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if(diji1.getBulletCount()==5){ break; } } } },1,1); //双缓冲改善画面 Graphics g=jframe.getGraphics(); BufferedImage bufferedimage=new BufferedImage(jframe.getWidth(), jframe.getHeight(), BufferedImage.TYPE_3BYTE_BGR); Graphics bufferG=bufferedimage.getGraphics(); //不断遍历主队列并不断调用主方法,画出所有图像 while(true){ for(int i=0;i<wholelist.size();i++){ Entity whole=wholelist.get(i); whole.draw(bufferG); if(!myfeiji.isDefeat()&&background.gameState()){ whole.move(); }else if(myfeiji.getHP()<=0){ //游戏输赢 int result=JOptionPane.showConfirmDialog(jframe,"" + "是否退出游戏?"); if(result==0){ System.exit(0); } } } //画出缓存图片 g.drawImage(bufferedimage,0,0,null); try { Thread.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void keyPressed(KeyEvent e){ //获得键盘事件 int code=e.getKeyCode(); if(code==KeyEvent.VK_F){ //子弹1 MyFeiJiBullet myfeijibullet1=new MyFeiJiBullet(); //设置坐标 myfeijibullet1.setX(myfeiji.getX()+100); myfeijibullet1.setY(myfeiji.getY()-10); //设置子弹类型 myfeijibullet1.setBulletType(1); //加入队列 wholelist.add(myfeijibullet1); //子弹2 MyFeiJiBullet myfeijibullet2=new MyFeiJiBullet(); //设置坐标 myfeijibullet2.setX(myfeiji.getX()+100); myfeijibullet2.setY(myfeiji.getY()+55); //设置子弹类型 myfeijibullet2.setBulletType(1); //加入队列 wholelist.add(myfeijibullet2); } //上下左右控制飞机移动 if(code==KeyEvent.VK_UP){ myfeiji.up=true; } if(code==KeyEvent.VK_DOWN){ myfeiji.down=true; } if(code==KeyEvent.VK_LEFT){ myfeiji.left=true; } if(code==KeyEvent.VK_RIGHT){ myfeiji.right=true; } } public void keyTyped(KeyEvent e){} public void keyReleased(KeyEvent e){ int code=e.getKeyCode(); if(code==KeyEvent.VK_UP){ myfeiji.up=false; } if(code==KeyEvent.VK_DOWN){ myfeiji.down=false; } if(code==KeyEvent.VK_LEFT){ myfeiji.left=false; } if(code==KeyEvent.VK_RIGHT){ myfeiji.right=false; } } //游戏菜单相关设置 public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){ //获得点击的X和Y坐标 int x=e.getX(); int y=e.getY(); //音乐开停 if(x>=35&&x<=85&&y>=200&&y<=225){ background.startMusic(); //界面开停 }else if(x>=35&&x<=85&&y>=230&&y<=255){ background.StartGame(); }else if(x>=35&&x<=85&&y>=260&&y<=285){ System.exit(0); } } public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e){} public void mouseExited(MouseEvent e){} } RemoveThread.java:去除线程类 /** * 去除线程类 * @author 梦想少年 * 创建线程来实现对越界子弹敌机的去除,控制飞机的碰撞 */ public class RemoveThread extends Thread{ //各个对象的队列 ArrayList<Entity> list; //攻击后我机的加分判断 private boolean isShootDiJiBullet; private boolean isShootDiJi; //初始化 public RemoveThread(ArrayList<Entity> list) { this.list=list; } public void run(){ while(true){ //休息一下 try { Thread.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //清除所有的越界敌机、飞机子弹、敌机子弹 for(int i=0;i<list.size();i++){ Entity entity=list.get(i); //清除敌机 if(entity instanceof Diji){ Diji diji=(Diji)entity; if(diji.isOutBounds()){ list.remove(diji); } //清除我机子弹 }else if(entity instanceof MyFeiJiBullet){ MyFeiJiBullet myfeijibullet=(MyFeiJiBullet)entity; if(myfeijibullet.isOutBounds()){ list.remove(myfeijibullet); } //清除敌机子弹 }else if(entity instanceof DiJiBullet){ DiJiBullet dijibullet=(DiJiBullet)entity; if(dijibullet.isOutBounds()){ list.remove(dijibullet); } } //------------------------------------------------------ } //清除和处理碰撞 for(int i=0;i<list.size();i++){ Entity entity1=list.get(i); for(int j=0;j<list.size();j++){ Entity entity2=list.get(j); if(entity1 instanceof MyFeiJi){ MyFeiJi myfeiji=(MyFeiJi)entity1; //设置一个加分的开关 if(isShootDiJi){ myfeiji.addDoubleScores(); isShootDiJi=false; }else if(isShootDiJiBullet){ myfeiji.addScores(); isShootDiJiBullet=false; } //------------------------------- if(entity2 instanceof DiJiBullet){ DiJiBullet dijibullet=(DiJiBullet)entity2; if(myfeiji.isShootByDiJiBullet(dijibullet)){ list.remove(dijibullet);//清除敌机子弹 myfeiji.subBlood();//我机掉血 } }//以上是敌机子弹范围 else if(entity2 instanceof Diji){ Diji diji=(Diji)entity2; if(myfeiji.isShootByDiJi(diji)){ diji.Blast();//敌机爆炸 diji.startMusic();//播放爆炸音乐 list.remove(diji);//去除敌机 myfeiji.subDoubleBlood();//我机掉多倍的血量 } }//以上是敌机范围 }//我的飞机范围 else if(entity1 instanceof MyFeiJiBullet){ MyFeiJiBullet myfeijibullet=(MyFeiJiBullet)entity1; if(entity2 instanceof DiJiBullet){ DiJiBullet dijibullet=(DiJiBullet)entity2; if(myfeijibullet.isShootDiJiBullet(dijibullet)&& i<list.size()&&j<list.size()){ list.remove(myfeijibullet);//去除飞机子弹 list.remove(dijibullet);//去除敌机子弹 isShootDiJiBullet=true;//打开加分开关 } }else if(entity2 instanceof Diji){ Diji diji=(Diji)entity2; if(myfeijibullet.isShootDiJi(diji)&& i<list.size()&&j<list.size()){ list.remove(myfeijibullet);//去除我机子弹 diji.Blast();//打开爆炸图片 diji.startMusic();//打开爆炸音乐 list.remove(diji);//去除敌机 isShootDiJi=true;//打开加分开关 } } }//我的飞机子弹范围 } //------------------------- } //------------------------------------------------------ } } }
    总结分析

    先来看看效果吧!!!! 整体效果还是不错的,代码的可拓展性还是比较好的,大家如果想要添加一些别的功能:大boss、奖赏、添加技能等等。但是在编写的时候我遇到了一些问题: 1.清除线程存在错位和碰撞检测不及时的问题 2.不能很好地解决敌机爆炸和爆炸背景音乐播放的延时问题

    大家如果有问题我们可以相互讨论啊ヾ(≧▽≦*)o,最后记得留下一个赞哦!!!

    Processed: 0.013, SQL: 9