基于被这款游戏的虐心经历后,决定把刚学的线程应用出来,模仿写出这一个游戏,基本游戏功能实现后打算写个2.0增加左右飞行方向,和别的物体互动,比如道具获得,怪物出现。 现已经基本实现原本游戏功能。
主要是有六个类来实现,游戏界面类,管子类,管子管理线程类,鸟管理线程类,鸟飞行鼠标监听器类,还有一个动画实现管理类。

首先是游戏界面类,用来创建游戏窗口和启动动画实现管理:

public class mainUI {  //程序入口    public static void main(String[] args) {      mainUI ui = new mainUI();    } //构造函数,自动调用初始化方法和开始游戏方法    public mainUI() {     // TODO Auto-generated constructor stub       initUI(); }

   //初始化游戏窗口 public void initUI(){     //判断是否开始游戏的标记     boolean startflag = false; 

        JFrame jf = new JFrame("Flappy Bird");     jf.setSize(600, 500);     jf.setLocationRelativeTo(null);       jf.setResizable(false);       jf.setDefaultCloseOperation(3);       jf.setVisible(true);

      //创建游戏动画线程管理线程        Administration ad = new Administration(jf);      ad.start();   }

}

然后是动画实现管理类,在写这么一个类之前是纠结了好一段时间了,因为刚开始写的时候发现管子的线程,和鸟的线程,和背景的动画实现,没办法协调起来,分别独自画在窗体上会出现相互覆盖的情况,所以后来想出了这么个类,用来获取当前鸟的坐标,还有管子队列中各个管子坐标,然后和背景一起在这个类里面的BufferedImage()里面画出来,再一起显示,没有看过别人写的动画实现方法,就只能先想出这个办法了。

public class Administration extends Thread {

 private JFrame jf;    private boolean die;

    public Administration(JFrame jf){     this.jf = jf;    }

   public void run(){

      //创建柱子队列管理线程,管理柱子的生成       PipeManage pm = new PipeManage(jf);      pm.start();

     //创建鸟管理线程,管理鸟的动态       BirdManage bm = new BirdManage(jf);      bm.start();

     //创建图片图标      ImageIcon baitian = new ImageIcon("image/白天.png");     ImageIcon dimian = new ImageIcon("image/地.png");       ImageIcon zheng = new ImageIcon("image/正.png");        ImageIcon fan = new ImageIcon("image/反.png");      ImageIcon shang = new ImageIcon("image/上.png");        ImageIcon zhong = new ImageIcon("image/中.png");        ImageIcon xia = new ImageIcon("image/下.png");      //飞行状态        int fly = 3;     ImageIcon gameover = new ImageIcon("image/gameover.png");      //图片坐标        int x = 0;       //管子队列起画坐标        int xx = 0;      //创建图片缓冲区     BufferedImage buffer = new BufferedImage(jf.getWidth(), jf.getHeight(), BufferedImage.TYPE_INT_RGB);     //获取缓冲区画布     Graphics g = buffer.getGraphics();       //获取窗体画布      Graphics gg = jf.getGraphics();      while(true){

            //延迟          delay(10);

          //起画坐标移动          x--;          xx--;         if(x <= -baitian.getIconWidth())              x = 0;

         //判断是否碰撞          iscrash(bm,pm,xx,zheng.getIconWidth(),zhong.getIconWidth(),zhong.getIconHeight(),dimian.getIconHeight());         if(die){              gg.drawImage(gameover.getImage(),(jf.getWidth()-gameover.getIconWidth())/2,(jf.getHeight()-gameover.getIconHeight())/2,null);             this.stop();          }

           //清屏          g.setColor(jf.getBackground());           g.fillRect(0, 0, jf.getWidth(), jf.getHeight());

            //----------画背景----------------------         g.drawImage(baitian.getImage(),x,0,null);         g.drawImage(baitian.getImage(),x+baitian.getIconWidth(),0,null);         g.drawImage(baitian.getImage(),x+2*baitian.getIconWidth(),0,null);

           //---------画管子-------------           for(int i=1;i<=pm.getPipeNum();i++){               g.drawImage(fan.getImage(),xx+pm.getPipe(i).position,pm.getPipe(i).gap-fan.getIconHeight(),null);                g.drawImage(zheng.getImage(),xx+pm.getPipe(i).position,pm.getPipe(i).gap+130,null);         }         //---------画地面-------         g.drawImage(dimian.getImage(),x,jf.getHeight()-dimian.getIconHeight(),null);          g.drawImage(dimian.getImage(),x+dimian.getIconWidth(),jf.getHeight()-dimian.getIconHeight(),null);           g.drawImage(dimian.getImage(),x+2*dimian.getIconWidth(),jf.getHeight()-dimian.getIconHeight(),null);

           //---------画鸟--------         if(fly==3){             g.drawImage(shang.getImage(),bm.getX(),bm.getY(),null);               fly--;            }else if(fly==2){               g.drawImage(zhong.getImage(),bm.getX(),bm.getY(),null);               fly--;            }else{                g.drawImage(xia.getImage(),bm.getX(),bm.getY(),null);             fly = 3;         }

           //累计得分            g.setColor(Color.black);          g.drawString(CountScore(bm,pm, xx,zheng.getIconWidth()), 50, jf.getHeight()-dimian.getIconHeight()+50);            

            //显示出图片缓冲区的内容         gg.drawImage(buffer, 0, 0, null);

       } }

   //累计得分     public String CountScore(BirdManage bm,PipeManage pm,int xx,int PipeWidth){       int score=0;         for(int i=1;i<=pm.getPipeNum();i++){           if(bm.getX()>=pm.getPipe(i).position+xx+PipeWidth)              score++;        }         System.out.println(score);        return Integer.toString(score);   }    //判断碰撞方法  public void iscrash(BirdManage bm,PipeManage pm,int xx,int PipeWidth,int birdWidth,int birdHeight,int dimian){        for(int i=1;i<=pm.getPipeNum();i++){           //判断上柱子(右碰)           if(bm.getX()+birdWidth >= pm.getPipe(i).position+xx && bm.getX()+birdWidth <= pm.getPipe(i).position+xx+PipeWidth && bm.getY() <= pm.getPipe(i).gap-5){              die = true;              return;           }         //判断上柱子(左碰)         if(bm.getX() >= pm.getPipe(i).position+xx && bm.getX() <= pm.getPipe(i).position+xx+PipeWidth && bm.getY() <= pm.getPipe(i).gap-5){                die = true;              return;           }         //判断下柱子(右碰)         if(bm.getX()+birdWidth >= pm.getPipe(i).position+xx && bm.getX()+birdWidth <= pm.getPipe(i).position+xx+PipeWidth && bm.getY()+birdHeight >= pm.getPipe(i).gap+145){               die = true;              return;           }         //判断下柱子(左碰)         if(bm.getX() >= pm.getPipe(i).position+xx && bm.getX() <= pm.getPipe(i).position+xx+PipeWidth && bm.getY()+birdHeight >= pm.getPipe(i).gap+145){             die = true;              return;           }         if(bm.getY()+birdHeight >= jf.getHeight()-dimian+12){               die = true;              return;           }     } }

   //延迟方法    public void delay(int t){     try {         sleep(t);     } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();      } }}

然后是管子线程管理类,用来生成管子对象,并移动管子坐标,用来给动画实现管理类提供管子坐标,实现动画还有碰撞判断:

public class PipeManage extends Thread {

 private static nodeQuene nq = new nodeQuene();;  private int position, Heigh;  private int gap;  private JFrame jf;

  public PipeManage(JFrame jf) {        this.position = jf.getWidth();       this.Heigh = jf.getHeight(); }

   public void run() {       Random rd = new Random();

        while (true) {            // 延迟         try {             sleep(10);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();          }         // 移动管子坐标             position++;

           // 管子队列           if (nq.size() == 0) {               // 产生管子随机缝隙纵坐标                gap = 70 + rd.nextInt(Heigh - 300);             pipe pp = new pipe(position, gap);               nq.add(pp);           } else {              // 产生管子随机缝隙纵坐标                gap = 70 + rd.nextInt(Heigh - 300);             // 如果前一个管子移动得足够远,生成管子,加入队列              if (nq.get(nq.size()).o.position <= position -180) {                  pipe pp = new pipe(position, gap);                   nq.add(pp);               }         }     }

   }

   public pipe getPipe(int i) {      return nq.get(i).o;   }

   public int getPipeNum() {     return nq.size(); }}

这个是管子类:

public class pipe {

  public int position;  public int gap;

 public pipe(int position,int gap){        this.gap = gap;      this.position = position;    }}

然后就是鸟线程管理类,由于只有一直鸟,就没有再特地写一个鸟的类了,就直接放在这个类里面了:

public class BirdManage extends Thread{

  private int X=150,Y=250;    static boolean flyingFlag;    static int dist = 25;    private JFrame jf;

  public BirdManage(JFrame jf){     this.jf = jf;    } public void run(){        //鼠标监听器       BirdListener bl = new BirdListener();        jf.addMouseListener(bl);

        while(true){          //延迟          try {             sleep(10);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();          }

           //如果按下了起飞         if(flyingFlag){

             if(dist<=0){                  dist=25;                 flyingFlag = false;              }             else{                 Fly();                    dist--;               }             continue;         }

           //自动下落            DownBird();       } } public void Fly(){        Y-=3;    } public void DownBird(){       Y+=2;   } public int getX(){        return X; } public int getY(){        return Y; }}

还有就是点击事件,让鸟改变方向移动一段距离:

public class BirdListener extends MouseAdapter {

   public void mousePressed(MouseEvent e) {      BirdManage.flyingFlag = true;        BirdManage.dist = 25;    }}

还有就是一个队列类nodeQueue(),就不拿出来啦。。

最后感觉做出来的游戏,动画上还是和原作差不多,但是鸟的移动就感觉有点生硬,在考虑重力加速度而不是单纯地匀速移动之后应该会有更好的效果。然后看到最近挺火的超难游戏I Wanna 之后,感觉添上一些未知陷阱会添加更多欢乐,接下来往这方面修改。

线程游戏实战之像素肥鸟相关推荐

  1. java线程游戏V4之飞机大战(一)

    关于实现飞机大战线程游戏,需要几点,首先是战机类,然后我方与敌方战机分别作为子类继承它.然后是子弹类,也分为敌方子弹和我方子弹.接着是需要的线程. 首先创建一个界面,创建GameUI类继承JFrame ...

  2. 【微信小游戏实战】零基础制作《欢乐停车场》二、关卡设计

    1.游戏立项 微信小游戏中有一款<欢乐停车场Plus>的小游戏,大家可以搜索玩下.这是一款益智类的小游戏,游戏中有红.黄.绿.蓝.紫5辆豪车6个停车位,玩家通过可行走路线移动小车,最终让各 ...

  3. Swift游戏实战-跑酷熊猫 01 创建工程导入素材

    原文:Swift游戏实战-跑酷熊猫 01 创建工程导入素材 在这节里,我们将建立一个游戏工程,并导入一些必要的素材,例如序列帧动画文件,声音素材文件.动画文件我们使用atlas形式.在打包发布或者模拟 ...

  4. python 写游戏好简单啊,我用键盘可以随意控制角色了【python 游戏实战 04】

    前言 本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课 ...

  5. 这是我第一次使用代码创建出一个窗口【python 游戏实战 01】

    前言 本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课 ...

  6. 《看聊天记录都学不会Python到游戏实战?太菜了吧》(8)我们开始做一个数字小游戏吧

    本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课程也将 ...

  7. 《看聊天记录都学不会Python到游戏实战?太菜了吧》(10)无底洞的循环

    本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课程也将 ...

  8. 《看聊天记录都学不会Python到游戏实战?太菜了吧》(7)我用函数写了个特洛伊木马

    本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课程也将 ...

  9. 【Java线程】“打工人”初识线程池及自定义线程池实战

    目录 理论 原理 线程池创建 工作流程图 拒绝策略 参数设置 四种线程池 实战 理论 聊一下为什么要使用线程池? 程序的运行本质,就是通过使用系统资源(CPU.内存.网络.磁盘等等)来完成信息的处理, ...

最新文章

  1. python ftp文件夹文件递归上传推送
  2. 1002: A+B for Input-Output Practice (II)
  3. iOS从零开始学习直播之音频2.后台播放和在线播放
  4. android常见面试问题
  5. 第一百零一期:如何处理ASP .NET Core中的cookie?
  6. butterknife 不能绑定错误
  7. 逻辑表达式是否合法_Linux shell 逻辑运算符、逻辑表达式详解
  8. phoenix timestamp字段查询
  9. 最简单的c 语言打开串口程序,一个简单的串口程序
  10. 实对称矩阵的特征值求法_旋转之三 - 旋转矩阵
  11. 【历史上的今天】7 月 3 日:人体工程学标准法案;消费电子领域先驱诞生;育碧发布 Uplay
  12. Cocos2d-x手机游戏开发视频教程
  13. 以太网结构框架的学习
  14. 2022树莓派安装甜糖 步骤分享
  15. springboot+mybatis打包时,单元测试类报错
  16. Python学习笔记_获取猫耳广播剧
  17. JVM参数-XXMatespaceSize的含义
  18. Python 二分法求多项式单根
  19. 开发微信小程序都需要哪些资质?
  20. 鸿蒙系统运行内存为啥只有8g,为什么手机运存是8G的,但是可用却只有5G?

热门文章

  1. 【示波器专题】数字示波器的主要指标——采样率
  2. python读conf配置文件_python读写配置文件操作示例
  3. STM32标准外设库
  4. 【谦川解读】特斯拉事件:安全,智能汽车的达摩克利斯之剑
  5. 【实验】流量控制之分为流量抑制和风暴控制
  6. 数字图像处理matlab实践
  7. 2018 中国大陆网速排名世界 141 位;Linux 4.18 内核发布
  8. MASM32连接程序时error A2006: undefined symbol : u
  9. 记武汉疫情期间的一次数据库和翻译记忆库的数据恢复 (一)
  10. mysql select符合查询_mysql学习-select查询,子查询,联接查询,union,intersect,except联合...