• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

java小游戏——飞翔的小鸟java初学作品

武飞扬头像
不会飞的鹤
帮助1

注:学习了java基础后,做出来的一个小作品,可以用来巩固学习

概述:

飞翔的小鸟能够作为Java基础的收官之作,包涵了Java很多的基础知识,在学习完Java基础后,尝试编写一些东西,能够起到很好的查漏补缺的作用。这里实现了Java小游戏飞翔的小鸟的一些基本功能。另外,随着学习水平的提高,以后也有可能会进行不断地改进。

同时,以下代码我也会尽我所能做好注释解释清楚

编写要求:

Java基础知识的掌握,Java的三大特性(多态,封装,继承),窗口的绘制,画笔的使用,io流,异常处理,数组,集合等

目录

概述:

编写要求:

游戏思路:

具体分析:

app包:

GameApp类:实现游戏的启动运行

main包:

GameFrame类:游戏主窗口类

Bird类:编写与小鸟有关的内容的类

Coloud类:

Barrier类:

GameBarrierLayer类:

Barrierpool类:

GameFrontGround类:

GameTime类:

Music类:

util包:


游戏共用到了三个包app包,放入游戏运行的入口类;main包,存放实现游戏各功能类的包;util包,存放游戏工具类以及一些常量的包;13个类,每个类都有各自的不同功能,方便进行查找和修改。

具体分析:

app包:

GameApp类:实现游戏的启动运行

GameApp类作为游戏的入口,进行初始化主窗口类的对象,来加载主窗口类的内容

代码为:

  1.  
     
  2.  
     
  3.  
    import main.GameFrame;
  4.  
     
  5.  
     
  6.  
    public class GameApp {
  7.  
    public static void main(String[] args){
  8.  
    //实例化GameFrame类
  9.  
    new GameFrame();
  10.  
    }
  11.  
    }

main包:

GameFrame类:游戏主窗口类

所有游戏中绘制的内容都在这个窗口中完成,进行编写的功能具体有:实例化各类;

初始化游戏中一些内容的对象;

添加监听事件;

重写update方法实现双缓冲技术,避免屏幕闪烁问题,同时添加上游戏暂停结束的画面;

代码具体的实现

  1.  
    package main;
  2.  
     
  3.  
    import static util.Constant.*;
  4.  
     
  5.  
    import java.awt.*;
  6.  
    import java.awt.event.*;
  7.  
    import java.awt.image.BufferedImage;
  8.  
     
  9.  
    //游戏的主窗口类,所有在游戏中绘制的内容都在此窗口中完成
  10.  
    //GameFrame继承Frame,使GameFrame类有创建窗口的功能
  11.  
    public class GameFrame extends Frame {
  12.  
     
  13.  
    //实例化GameBackGround中的类
  14.  
    private GameBackGround gameBackGround;
  15.  
     
  16.  
    //实例化小鸟的类
  17.  
    private Bird bird;
  18.  
     
  19.  
    //实例化障碍物层类
  20.  
    private GameBarrierLayer gameBarrierLayer;
  21.  
     
  22.  
    //实例化前景类
  23.  
    private GameFrontGround gameFrontGround;
  24.  
     
  25.  
    //实例化云彩类
  26.  
    private Cloud cloud;
  27.  
     
  28.  
    //存放图片的 图片
  29.  
    //设置一张图片
  30.  
    //传进图片的长度和高度
  31.  
    private BufferedImage buffimg = new BufferedImage(FRAM_WIDTH, FRAM_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
  32.  
     
  33.  
     
  34.  
    //定义一个构造方法初始化一些参数
  35.  
    public GameFrame(){
  36.  
    //窗口是否可见
  37.  
    setVisible(true);
  38.  
    //窗口大小(没有定义静态之前,需要使用类名进行调用)
  39.  
    // setSize(Constant.FRAM_WIDTH, Constant.FRAM_HEIGHT);
  40.  
    //如果把Constant=包定义成静态的,后面加上.*,则可以省略Constant的调用
  41.  
    setSize(FRAM_WIDTH, FRAM_HEIGHT);
  42.  
     
  43.  
    //窗口标题
  44.  
    setTitle(FRAM_TITLE);
  45.  
    //窗口的初始化位置
  46.  
    setLocation(FRAM_X, FRAM_Y);
  47.  
    //窗口的大小不可改变
  48.  
    setResizable(false);
  49.  
    //给窗口添加关闭事件
  50.  
     
  51.  
    /*该代码为在 Swing 程序中添加一个窗口监听器,
  52.  
    并为窗口关闭事件添加一个监听函数。当用户关闭窗口时,
  53.  
    代码会调用 System 类的 exit() 方法,将程序正常结束。
  54.  
    由于传入的窗口适配器是匿名内部类,
  55.  
    这意味着我们可以简单地在构建对象时指定事件,
  56.  
    而不用创建新的自定义窗口适配器类。
  57.  
    */
  58.  
    addWindowListener(new WindowAdapter() {
  59.  
    @Override
  60.  
    public void windowClosing(WindowEvent e) {
  61.  
    System.exit(0);//结束程序
  62.  
    }
  63.  
    });
  64.  
     
  65.  
    //在构造器中调用下面初始化的对象
  66.  
    initGame();
  67.  
     
  68.  
    //启动线程
  69.  
    new run().start();
  70.  
     
  71.  
    //添加监听
  72.  
    /*KeyAdapter是一个类
  73.  
    KeyAdapter中已经实现了对键盘事件的监听方法,
  74.  
    但这些方法的实现是空的,我们需要在使用时重写这些方法,
  75.  
    根据需求处理键盘事件。*/
  76.  
    addKeyListener(new KeyAdapter() {
  77.  
    @Override
  78.  
    public void keyPressed(KeyEvent e) {
  79.  
    //调用add方法,实现相应的键盘监听
  80.  
    add(e);
  81.  
    }
  82.  
     
  83.  
    @Override
  84.  
    public void keyReleased(KeyEvent e) {
  85.  
    minu(e);
  86.  
    }
  87.  
    });
  88.  
     
  89.  
     
  90.  
     
  91.  
    }
  92.  
     
  93.  
    //初始化对象
  94.  
    /*在GameFrame类中,
  95.  
    实例化了GameBackGround类的对象gameBackGround,
  96.  
    即在GameFrame对象初始化的同时也初始化了gameBackGround对象。
  97.  
    这是因为在游戏的主窗口中,需要在窗口中绘制游戏的背景。
  98.  
    在GameBackGround类中封装了绘制背景的方法,
  99.  
    因此需要创建一个GameBackGround对象,通过调用其方法来绘制背景。
  100.  
    同时,在GameBackGround类中还包含了游戏中玩家、敌人、子弹等对象的初始化,
  101.  
    这些对象同样需要在GameFrame中使用,因此需要实例化GameBackGround类的对象。*/
  102.  
    public void initGame(){
  103.  
    //分别实例化GameBackGround类,Bird类,GameFrontGround类,GameBarrierLayer类的对象,
  104.  
    gameBackGround = new GameBackGround();
  105.  
    bird = new Bird();
  106.  
     
  107.  
    gameFrontGround = new GameFrontGround();
  108.  
     
  109.  
    gameBarrierLayer = new GameBarrierLayer();
  110.  
     
  111.  
    }
  112.  
     
  113.  
    //写一个线程
  114.  
    /*
  115.  
    * 这是一个继承自Thread类的run类。
  116.  
    * 它重写了Thread类中的run方法。
  117.  
    * 在这个run方法中,它执行了repaint()方法,
  118.  
    * 这个方法会调用paint()方法重新绘制组件。
  119.  
    * 在多线程环境下,这个类的实例可以与其他线程并发执行。
  120.  
    * 当这个线程启动时,它会自动调用run方法。
  121.  
    * 所以在这个run方法中,它会反复调用repaint方法来不断刷新界面。
  122.  
    */
  123.  
    class run extends Thread{
  124.  
    @Override
  125.  
    public void run(){
  126.  
    while (true) {
  127.  
    repaint();
  128.  
    try {
  129.  
    Thread.sleep(30);
  130.  
    } catch (InterruptedException e) {
  131.  
    e.printStackTrace();
  132.  
    }
  133.  
    }
  134.  
     
  135.  
    }
  136.  
    }
  137.  
    //定义初始化是否开始的状态为true,在后面方便实现游戏暂停
  138.  
    public static boolean isStarted = true;
  139.  
    //写一个update方法,所有需要绘制的内容都在这里面绘制
  140.  
     
  141.  
    /*这段代码是Java中的重写方法,通常用于在每次图形界面需要更新时,
  142.  
    自动调用该方法。
  143.  
     
  144.  
    具体而言,该方法首先调用了gameBackGround对象的draw方法,绘制了背景图像。
  145.  
    然后调用了bird对象的draw方法,绘制了小鸟图像。
  146.  
     
  147.  
    这里需要注意的是,Graphics对象是一个类似于画布的实例,
  148.  
    draw方法则是用来在画布上绘制图像的方法。因此,在调用draw方法时,
  149.  
    需要将该对象作为参数传递进去,使得绘制的图像可以正确显示在画布上。
  150.  
    实现了游戏界面的绘制
  151.  
     
  152.  
    需要注意的是,该方法实现了双缓冲技术,即先将需要绘制的所有元素绘制在缓存图片上,
  153.  
    然后再一次性绘制到屏幕上,避免了图像闪烁等问题。*/
  154.  
    @Override
  155.  
    public void update(Graphics g){
  156.  
    //进行判断,如果小鸟的生命值大于0,并且处于游戏开始状态,执行代码
  157.  
    if (bird.life > 0 && isStarted == true){
  158.  
    //播放音乐
  159.  
    Music.playMusic();
  160.  
    //得到图片的画笔
  161.  
    Graphics graphics = buffimg.getGraphics();
  162.  
    //把所有要绘制的东西全部放在这张图片上,绘制背景,小鸟,前景,障碍物
  163.  
    gameBackGround.draw(graphics);
  164.  
    bird.draw(graphics);
  165.  
    gameFrontGround.draw(graphics);
  166.  
    gameBarrierLayer.draw(graphics,bird);
  167.  
     
  168.  
    //然后一次性把这张图片绘制在屏幕中
  169.  
    g.drawImage(buffimg, 0, 0, null);
  170.  
     
  171.  
    }//如果小鸟的生命值大于0,游戏处于暂停状态,执行下列代码
  172.  
    else if(bird.life > 0 && isStarted == false){
  173.  
    //停止播放音乐
  174.  
    Music.stopMusic();
  175.  
    // 设置字体颜色为白色
  176.  
    g.setColor(Color.WHITE);
  177.  
    // 设置字体,风格,字号
  178.  
    g.setFont(new Font("微软雅黑", 1, 40));
  179.  
    //打印游戏暂停时的提示语)
  180.  
    g.drawString("点击空格键开始", 120, 180);
  181.  
    }
  182.  
    else{//小鸟死亡时执行下列语句
  183.  
    // 停止播放音乐
  184.  
    Music.stopMusic();
  185.  
    // 定义游戏结束的提示
  186.  
    String over = "游戏结束";
  187.  
    // 设置字体的颜色为红色
  188.  
    g.setColor(Color.red);
  189.  
    // 设置字体,风格,字号
  190.  
    g.setFont(new Font("微软雅黑", 1,60));
  191.  
    // 字体打印的语句,xy对应的位置
  192.  
    g.drawString(over, 180, 200);
  193.  
    // 重新开始的提示语
  194.  
    String reset = "Space Reset Game";
  195.  
    // 打印的内容,对应xy轴的位置
  196.  
    g.drawString(reset, 25, 300);
  197.  
    }
  198.  
     
  199.  
    }
  200.  
    //调整up与down的true与false情况
  201.  
    //fly等于1,up为true,为5,up为false
  202.  
    //按键
  203.  
    public void add(KeyEvent e){
  204.  
    switch(e.getKeyCode()){
  205.  
    case KeyEvent.VK_UP:
  206.  
    // 如果点击的是上建,up定义为true,Bird类中会根据up的值定义小鸟的飞行状态
  207.  
    bird.fly(1);
  208.  
    break;
  209.  
    // 点击的是空格键
  210.  
    case KeyEvent.VK_SPACE:
  211.  
    // 如果小鸟生命值为0,小鸟死亡时
  212.  
    if (bird.life == 0){
  213.  
    // 重新开始游戏
  214.  
    restart();
  215.  
    }else{
  216.  
    // 小鸟没有死亡,isStarted取相反值,使游戏停止
  217.  
    isStarted = !isStarted;
  218.  
    }
  219.  
    break;
  220.  
    }
  221.  
     
  222.  
    }
  223.  
    //松键方法
  224.  
    public void minu(KeyEvent e){
  225.  
    switch (e.getKeyCode()){
  226.  
    // 松开向上按键,调用小鸟类中的fly方法,up定义为false,小鸟飞翔状态改变
  227.  
    case KeyEvent.VK_UP:
  228.  
    bird.fly(5);
  229.  
    break;
  230.  
    }
  231.  
    }
  232.  
    public void restart(){
  233.  
    //清空障碍物
  234.  
    gameBarrierLayer.restant();
  235.  
    //小鸟回原来位置
  236.  
    bird.restarDraw();
  237.  
    //重新定义是否开始的状态为true
  238.  
    isStarted = true;
  239.  
     
  240.  
    }
  241.  
     
  242.  
    }
学新通

Bird类:编写与小鸟有关的内容的类

定义小鸟的初始状态;给小鸟添加矩形框,方便进行碰撞检测;定义控制小鸟移动,改变小鸟移动,重新定义小鸟位置与生命值的方法

  1.  
    package main;
  2.  
     
  3.  
    import static util.Constant.*;
  4.  
    import util.GameUtil;
  5.  
     
  6.  
    import java.awt.*;
  7.  
    import java.awt.image.BufferedImage;
  8.  
     
  9.  
    public class Bird {
  10.  
    //定义一个加速度acceleration
  11.  
    private int acceleration =0;
  12.  
     
  13.  
    //给小鸟添加矩形框
  14.  
    private Rectangle rect;
  15.  
     
  16.  
    //小鸟设定生命值
  17.  
    public int life = 3;
  18.  
     
  19.  
    //定义一个数组,存放小鸟图片,三张
  20.  
    private BufferedImage[] images;
  21.  
    public static final int BIRD_IMAGE_COUNT = 3;
  22.  
     
  23.  
    //小鸟移动的方向
  24.  
    private boolean up = false, down = false;
  25.  
     
  26.  
    //小鸟初始化速度
  27.  
    private int speed = 4;
  28.  
     
  29.  
    //小鸟状态,小鸟的状态等于对应的数字时,把小鸟的图片换成对应的图片
  30.  
    private int state;
  31.  
    public static final int STATE_NORMAL = 0;//平着飞
  32.  
    public static final int STATE_UP = 1;//向上飞
  33.  
    public static final int STATE_DOWN = 2;//向下飞
  34.  
     
  35.  
    //小鸟位置
  36.  
    private int x = 150, y = 200;
  37.  
     
  38.  
    //构造方法中对资源初始化
  39.  
    public Bird(){
  40.  
    //初始化集合用来存储小鸟的个数
  41.  
     
  42.  
    /*这段代码是用来初始化小鸟对象的构造方法,
  43.  
    其中主要包含了对小鸟图片资源的初始化。
  44.  
    具体来说,
  45.  
    该构造方法通过定义一个名为images的实例变量来存储小鸟的图片资源,
  46.  
    其长度为BIRD_IMAGE_COUNT,即小鸟图片的数量。
  47.  
    接下来使用了一个for循环,循环次数为BIRD_IMAGE_COUNT,
  48.  
    即将每张小鸟图片的路径传进GameUtil.loadBufferedImage方法中,
  49.  
    获得对应的BufferedImage对象后存入images数组中,
  50.  
    使得小鸟对象的images变量存储了所有小鸟图片资源。
  51.  
    其中loadBufferedImage是一种自定义的方法,
  52.  
    用于将指定路径的图片文件读入内存并返回对应的BufferedImage对象。
  53.  
    在游戏中,小鸟的各个动作需要对应不同的图片资源,
  54.  
    因此此步骤对所有小鸟图片资源的读取和存储是十分必要的。
  55.  
    */
  56.  
    images = new BufferedImage[BIRD_IMAGE_COUNT];
  57.  
    for (int i = 0; i < BIRD_IMAGE_COUNT; i ) {
  58.  
    //把路径传进来,把每张小鸟图片的路径传入GameUtil.loadBufferedImage方法中
  59.  
    images[i] = GameUtil.loadBufferedImage(BIRD_IMG[i]);
  60.  
     
  61.  
    }
  62.  
    //定义矩形框的宽高,宽高为小鸟图片的宽高
  63.  
    int w = images[0].getWidth();
  64.  
    int h = images[0].getHeight();
  65.  
    // 实例化矩形框
  66.  
    rect = new Rectangle(w,h);
  67.  
    }
  68.  
    //绘制小鸟
  69.  
    public void draw(Graphics g){
  70.  
    // 调用控制小鸟移动的方法
  71.  
    flyLogic();
  72.  
     
  73.  
    //画出对应的小鸟图片
  74.  
    //小鸟图片放到数组中。直接使用数组即可
  75.  
    g.drawImage(images[state], x, y, null);
  76.  
    //绘制小鸟矩形
  77.  
    // g.drawRect(x, y, (int)rect.getWidth(), rect.height);
  78.  
    //给矩形的宽高进行赋值
  79.  
    rect.x = this.x;
  80.  
    rect.y = this.y;
  81.  
    }
  82.  
     
  83.  
    //控制小鸟移动的方向
  84.  
    public void flyLogic(){
  85.  
    //点击上建,up的值为true
  86.  
    if (up == true){
  87.  
    // y -= speed;
  88.  
    // 小鸟的加速度自减
  89.  
    acceleration--;
  90.  
    // 设置小鸟y坐标的移动
  91.  
    y =acceleration;
  92.  
    // 如果加速度小于10,令加速度等于-10
  93.  
    if (acceleration < -10){
  94.  
    acceleration = -10;
  95.  
    }
  96.  
    // 如果y坐标小于20,令y坐标不变,加速度为0
  97.  
    if (y < 20){
  98.  
    y = 20;
  99.  
    acceleration = 0;
  100.  
    }
  101.  
    }
  102.  
    //松开向上箭头键,up为false,情况与上面类似
  103.  
    if (up != true){
  104.  
    // y = speed;
  105.  
    acceleration ;
  106.  
    y =acceleration;
  107.  
    if (acceleration > 10){
  108.  
    acceleration = 10;
  109.  
     
  110.  
    }
  111.  
    if (y > 475){
  112.  
    y = 475;
  113.  
    acceleration = 0;
  114.  
    }
  115.  
    }
  116.  
    }
  117.  
    //改变小鸟状态的方法
  118.  
    public void fly(int fly){
  119.  
    switch(fly){
  120.  
    case 1:
  121.  
    state = 1;
  122.  
    up = true;
  123.  
    break;
  124.  
    case 5:
  125.  
    state = 2;
  126.  
    up = false;
  127.  
    break;
  128.  
    }
  129.  
    }
  130.  
    //定义矩形框的get方法,方便障碍物画矩形框
  131.  
    public Rectangle getRect() {
  132.  
    return rect;
  133.  
    }
  134.  
    //重新绘制小鸟位置与小鸟生命值
  135.  
    public void restarDraw(){
  136.  
    life = 3;
  137.  
    x = 200;
  138.  
    y = 200;
  139.  
    }
  140.  
    }
学新通

Coloud类:与云彩有关的类

详细有云彩速度,位置的定义,画出云彩的方法,判断云彩是否飞出屏幕以外的方法

  1.  
    package main;
  2.  
     
  3.  
     
  4.  
    import java.awt.*;
  5.  
    import java.awt.image.BufferedImage;
  6.  
     
  7.  
    //云彩类
  8.  
    public class Cloud {
  9.  
    //云彩图片
  10.  
    private BufferedImage img;
  11.  
     
  12.  
    //云彩速度
  13.  
    private int speed;
  14.  
    //云彩位置
  15.  
    private int x, y;
  16.  
    //构造函数 空参实参
  17.  
    // 在调用实参构造方法时进行赋值
  18.  
    public Cloud(){}
  19.  
    public Cloud(BufferedImage img, int speed, int x, int y){
  20.  
    this.img = img;
  21.  
    this.speed = speed;
  22.  
    this.x = x;
  23.  
    this.y = y;
  24.  
     
  25.  
    }
  26.  
    //写一个draw方法画出云彩
  27.  
    public void draw(Graphics g){
  28.  
    // 实现云的移动,云在x轴上以speed的速度不断移动
  29.  
    x -= speed;
  30.  
    // 画出云的位置,参数分别为云的图片,xy轴的坐标,转换了更多图像时要通知的对象
  31.  
    g.drawImage(img, x, y, null);
  32.  
    }
  33.  
     
  34.  
    //判断云彩是否飞出屏幕以外,根据返回值的类型在GameFrontGround类中判断是否需要移除云
  35.  
    public boolean isOutFrame(){
  36.  
    // 如果云的x坐标小于-50
  37.  
    if(x < -50){
  38.  
    // 返回true
  39.  
    return true;
  40.  
    }else{
  41.  
    return false;
  42.  
    }
  43.  
    }
  44.  
    }
学新通

Barrier类:障碍物类

与障碍物有关的操作的编写,定义障碍物的矩形,速度,存放障碍物的数组,障碍物的状态;

静态代码块初始化障碍物的参数,在加载类时优先执行;

draw方法,绘制障碍物;

绘制四种障碍物的方法;

给障碍物绘制矩形用于进行碰撞检测的方法;

判断绘制障碍物时机的方法;

  1.  
    package main;
  2.  
     
  3.  
     
  4.  
    import util.Constant;
  5.  
    import util.GameUtil;
  6.  
     
  7.  
    import java.awt.*;
  8.  
    import java.awt.image.BufferedImage;
  9.  
     
  10.  
    //障碍物类
  11.  
    public class Barrier {
  12.  
    //用于判断障碍物是否要进行移动
  13.  
    private boolean mob = true;
  14.  
    //定义一个矩形
  15.  
    private Rectangle rect;
  16.  
     
  17.  
    //定义障碍物的速度
  18.  
    private int speed = 3;
  19.  
    //定义一个数组,来存放障碍物的三种图片
  20.  
    private static BufferedImage[] imgs;
  21.  
     
  22.  
    //障碍物状态
  23.  
    private boolean visible;
  24.  
     
  25.  
    //写一个静态代码块,初始化参数,在加载类时会优先执行
  26.  
    static {
  27.  
    //记录障碍物图片的张数
  28.  
    final int COUNT = 3;
  29.  
     
  30.  
    //类加载时初始化三张障碍物图片,传入图片个数
  31.  
    imgs = new BufferedImage[COUNT];
  32.  
    for (int i = 0; i < COUNT; i ) {
  33.  
    //把图片存放到障碍物的数组中
  34.  
    imgs[i] = GameUtil.loadBufferedImage(Constant.BARRIER_IMG_PATH[i]);
  35.  
     
  36.  
    }
  37.  
     
  38.  
    }
  39.  
    //定义障碍物的位置,宽高,类型,创建障碍物图像时能够使用到
  40.  
    private int x, y;
  41.  
    private int width, height;//height是障碍物的一个属性,每个障碍物的高度都可能不同
  42.  
    private int type;
  43.  
    // 绘制不同种障碍物类型的参数
  44.  
    public static final int TYPE_TOP_NORMAL = 0;
  45.  
    public static final int TYPE_BOTTOM_NORMAL = 2;
  46.  
    public static final int TYPE_NOVER_NORMAL = 4;
  47.  
    public static final int TYPE_MOBLE = 6;
  48.  
     
  49.  
    //获得障碍物的宽度和高度
  50.  
    //中间
  51.  
    // imgs[]数组中第一张图片的宽高
  52.  
    public static final int BARRIRE_WIDTH = imgs[0].getWidth();
  53.  
    public static final int BARRIRE_HEIGHT = imgs[0].getHeight();
  54.  
    //上下朝向
  55.  
    // 分别为imgs[]数组中第二张图片的宽高
  56.  
    public static final int BARRIRE_HEAD_WIDTH = imgs[1].getWidth();
  57.  
    public static final int BARRIRE_HEAD_HEIGHT = imgs[1].getHeight();
  58.  
     
  59.  
    //定义构造器
  60.  
    public Barrier(){
  61.  
    //初始化矩形参数
  62.  
    rect = new Rectangle();
  63.  
    }
  64.  
     
  65.  
    //编写draw方法,根据不同的类型绘制障碍物
  66.  
    public void draw(Graphics g){
  67.  
    switch(type){
  68.  
    case TYPE_TOP_NORMAL:
  69.  
    // 画出从上到下的障碍物
  70.  
    drawTopNormal(g);
  71.  
    break;
  72.  
    // 画出从下到上的障碍物
  73.  
    case TYPE_BOTTOM_NORMAL:
  74.  
    drawNormalTop(g);
  75.  
    break;
  76.  
    // 画出中间的障碍物
  77.  
    case TYPE_NOVER_NORMAL:
  78.  
    drawHoverNormal(g);
  79.  
    break;
  80.  
    // 画出中间移动的障碍物
  81.  
    case TYPE_MOBLE:
  82.  
    drawMobile(g);
  83.  
    break;
  84.  
     
  85.  
    }
  86.  
    }
  87.  
    //绘制从上到下的障碍物
  88.  
    public void drawTopNormal(Graphics g){
  89.  
     
  90.  
    //求出所需要的障碍物的块数
  91.  
    //高度减去头的高度,再除以中间的高度加1就是中间障碍物所需要的块数
  92.  
    int count = (height - BARRIRE_HEAD_HEIGHT)/BARRIRE_HEIGHT 1;
  93.  
     
  94.  
    //使用for循环绘制中间障碍物
  95.  
    for (int i = 0; i < count; i ) {
  96.  
    //drawImage方法用来绘制图片
  97.  
    g.drawImage(imgs[0], x, y i*BARRIRE_HEIGHT, null);
  98.  
     
  99.  
    }
  100.  
    //绘制头
  101.  
    int y = height - BARRIRE_HEAD_HEIGHT;
  102.  
    // 画出imgs数组中第三张图片,参数分别为对应的图片,xy轴的坐标,转换更多图像时
  103.  
    //要通知的对象,这里不进行通知
  104.  
    g.drawImage(imgs[2], x - (BARRIRE_HEAD_WIDTH - BARRIRE_WIDTH)/2, y, null);
  105.  
    // 头的左边左移,实现障碍物的移动
  106.  
    x -= speed;
  107.  
    if (x < -50){
  108.  
    // 设置visible的值,判断是否需要移除障碍物
  109.  
    visible = false;
  110.  
    }
  111.  
    // 调用绘制矩形框的方法绘制矩形框
  112.  
    rect(g);
  113.  
     
  114.  
    }
  115.  
    //绘制从下往上的障碍物
  116.  
    public void drawNormalTop(Graphics g){
  117.  
    //障碍物所需要的块数
  118.  
    int count = height / BARRIRE_HEIGHT 1;
  119.  
     
  120.  
    //for循环绘制中间障碍物
  121.  
    for (int i = 0; i < count; i ) {
  122.  
    // drawImage方法画出图片,
  123.  
    g.drawImage(imgs[0], x, y imgs[1].getHeight() i*imgs[0].getHeight(), null);
  124.  
     
  125.  
    }
  126.  
     
  127.  
    //绘制头
  128.  
    int y = Constant.FRAM_HEIGHT-height;
  129.  
    // this.y = y;
  130.  
    g.drawImage(imgs[1], x - (BARRIRE_HEAD_WIDTH-BARRIRE_WIDTH)/2, y, null);
  131.  
     
  132.  
    x -= speed;
  133.  
     
  134.  
    //如果障碍物除了屏幕以外,状态改为false
  135.  
    if (x < -50){
  136.  
    visible = false;
  137.  
    }
  138.  
    rect(g);
  139.  
    }
  140.  
     
  141.  
    //绘制中间的障碍物
  142.  
    public void drawHoverNormal(Graphics g){
  143.  
     
  144.  
    //求出所需要的障碍物的块数
  145.  
    //高度减去头的高度,再除以中间的高度加1就是中间障碍物所需要的块数
  146.  
    int count = (height - BARRIRE_HEAD_HEIGHT) / BARRIRE_HEIGHT;
  147.  
    // System.out.println(count "aaaa");
  148.  
    //绘制上头
  149.  
    g.drawImage(imgs[1], x, y, null);
  150.  
    //使用for循环绘制中间障碍物
  151.  
    for (int i = 0; i < count; i ) {
  152.  
    //drawImage方法用来绘制图片
  153.  
    g.drawImage(imgs[0], x, y BARRIRE_HEAD_HEIGHT i*BARRIRE_HEIGHT, null);
  154.  
     
  155.  
    }
  156.  
    rect(g);
  157.  
    //绘制下头
  158.  
    int y11 = y height - BARRIRE_HEAD_HEIGHT;
  159.  
    // System.out.println(y);
  160.  
    g.drawImage(imgs[2], x, y11, null);
  161.  
     
  162.  
    x -= speed;
  163.  
    if (x < -50){
  164.  
    visible = false;
  165.  
    }
  166.  
     
  167.  
     
  168.  
    }
  169.  
     
  170.  
    //绘制可以移动的障碍物
  171.  
    public void drawMobile(Graphics g){
  172.  
     
  173.  
    //求出所需要的障碍物的块数
  174.  
    //高度减去头的高度,再除以中间的高度加1就是中间障碍物所需要的块数
  175.  
    int count = (height - BARRIRE_HEAD_HEIGHT) / BARRIRE_HEIGHT;
  176.  
    // System.out.println(count "aaaa");
  177.  
    //绘制上头
  178.  
    g.drawImage(imgs[1], x, y, null);
  179.  
    //使用for循环绘制中间障碍物
  180.  
    for (int i = 0; i < count; i ) {
  181.  
    //drawImage方法用来绘制图片
  182.  
    g.drawImage(imgs[0], x, y BARRIRE_HEAD_HEIGHT i*BARRIRE_HEIGHT, null);
  183.  
     
  184.  
    }
  185.  
    // 调用画矩形框的方法绘制矩形框
  186.  
    rect(g);
  187.  
    //绘制下头
  188.  
    int y11 = y height - BARRIRE_HEAD_HEIGHT;
  189.  
    g.drawImage(imgs[2], x, y11, null);
  190.  
     
  191.  
    x -= speed;
  192.  
    if (x < -50){
  193.  
    visible = false;
  194.  
    }
  195.  
    //让障碍物移动
  196.  
    if (mob){
  197.  
    y =5;
  198.  
    if(y >=250){
  199.  
    mob = false;
  200.  
    }
  201.  
    }else if (!mob){
  202.  
    y-=5;
  203.  
    if (y<=100){
  204.  
    mob = true;
  205.  
    }
  206.  
    }
  207.  
     
  208.  
    }
  209.  
     
  210.  
    /*rect(Graphics g):
  211.  
    绘制障碍物碰撞的矩形。
  212.  
    该方法接收一个 Graphics 对象 g,
  213.  
    用于在指定区域绘制障碍物的矩形。
  214.  
    它使用障碍物的 x、y 坐标来确定绘制的矩形的位置,
  215.  
    使用障碍物图片数组 imgs[0] 的宽度 w1 来
  216.  
    确定矩形的宽度,而 height 则作为矩形的高度。
  217.  
    在绘制矩形时,使用了预设的颜色 Color.red。*/
  218.  
    //绘制障碍物碰撞的矩形
  219.  
    public void rect(Graphics g){
  220.  
    int x1 = this.x;
  221.  
    int y1 = this.y;
  222.  
    int w1 = imgs[0].getWidth();
  223.  
    g.setColor(Color.red);
  224.  
    // g.drawRect(x1, y1, w1, height);
  225.  
    //调用障碍物矩形参数的方法
  226.  
    setRecyangle(x1, y1, w1, height);
  227.  
     
  228.  
    }
  229.  
     
  230.  
    /*setRecyangle(int x, int y, int width, int height):
  231.  
    障碍物的矩形参数。该方法接收四个整数参数,
  232.  
    分别表示矩形的位置和大小。
  233.  
    它将这四个参数值赋值给对象的矩形参数 rect,
  234.  
    以便后续在游戏中进行碰撞检测。*/
  235.  
    //障碍物的矩形参数
  236.  
    public void setRecyangle(int x, int y, int width, int height){
  237.  
    rect.x = x;
  238.  
    rect.y = y;
  239.  
    rect.width = width;
  240.  
    rect.height = height;
  241.  
     
  242.  
    }
  243.  
     
  244.  
     
  245.  
    //判断什么时候绘制障碍物,可以调节障碍物之间的距离,让游戏简单或困难
  246.  
    public boolean isInFrame(){
  247.  
    return 600-x>180;
  248.  
    }
  249.  
     
  250.  
    public int getX() {
  251.  
    return x;
  252.  
    }
  253.  
     
  254.  
    public void setX(int x) {
  255.  
    this.x = x;
  256.  
    }
  257.  
     
  258.  
    public int getY() {
  259.  
    return y;
  260.  
    }
  261.  
     
  262.  
    public void setY(int y) {
  263.  
    this.y = y;
  264.  
    }
  265.  
     
  266.  
    public int getHeight() {
  267.  
    return height;
  268.  
    }
  269.  
     
  270.  
    public void setHeight(int height) {
  271.  
    this.height = height;
  272.  
    }
  273.  
     
  274.  
    public int getType() {
  275.  
    return type;
  276.  
    }
  277.  
     
  278.  
    public void setType(int type) {
  279.  
    this.type = type;
  280.  
    }
  281.  
    public boolean getVisible(){
  282.  
    return visible;
  283.  
    }
  284.  
    public void setVisible(boolean visible){
  285.  
    this.visible = visible;
  286.  
    }
  287.  
     
  288.  
    public Rectangle getRect() {
  289.  
    return rect;
  290.  
    }
  291.  
    }
学新通

GameBarrierLayer类:障碍物层类

定义一个数据记录小鸟飞行的最大时间;

实例化时间类,获取随机数,定义List集合存放障碍物,定义构造器初始化数据;

编写drw方法绘制障碍物;

编写logic方法定义游戏开始,暂停,结束状态;

编写insert方法获得障碍物对象,添加障碍物;

ran方法产生随机数;

判断小鸟发生碰撞的方法;

清空障碍物池;

储存和得到数据方法;

  1.  
    package main;
  2.  
     
  3.  
     
  4.  
    import java.awt.*;
  5.  
    import java.io.*;
  6.  
    import java.util.ArrayList;
  7.  
    import java.util.List;
  8.  
    import java.util.Random;
  9.  
     
  10.  
    //障碍物层类
  11.  
    public class GameBarrierLayer {
  12.  
     
  13.  
    //定义一个数据
  14.  
    private int txt;
  15.  
     
  16.  
    //实例化时间类
  17.  
    private GameTime gameTime;
  18.  
     
  19.  
     
  20.  
    private Random random = new Random();
  21.  
    /*这是一个Java类定义,主要作用是创建一个障碍物图层,
  22.  
    并且使用ArrayList来存储障碍物对象。
  23.  
     
  24.  
    代码中的 "List<Barrier> barriers" 是一个成员变量,
  25.  
    表示一个障碍物对象的列表,其中每个障碍物对象的类型是 "Barrier"。
  26.  
     
  27.  
    在构造函数中,使用 "ArrayList<>()" 初始化了 "barriers" 列表,
  28.  
    该列表将用于存储障碍物对象。
  29.  
    由于 "ArrayList" 类实现了 "List" 接口,
  30.  
    因此它提供了一些方便的方法来管理和访问列表中的元素。
  31.  
     
  32.  
    因此,在创建 "GameBarrierLayer" 对象时,
  33.  
    可以使用构造函数来初始化 "barriers" 列表,
  34.  
    然后将其用于存储障碍物对象。
  35.  
    */
  36.  
     
  37.  
    //定义一个数组存放障碍物
  38.  
    private List<Barrier> barriers;
  39.  
     
  40.  
    //定义构造器初始化数组
  41.  
    public GameBarrierLayer(){
  42.  
    barriers = new ArrayList<>();
  43.  
    gameTime = new GameTime();
  44.  
    }
  45.  
     
  46.  
    //绘制障碍物
  47.  
    /*该代码是一个游戏中生成障碍物的功能实现。
  48.  
    在draw方法中,首先通过for循环遍历所有已存在的障碍物对象并进行绘制。
  49.  
    接着调用logic方法,该方法用于检测是否需要生成新的障碍物。
  50.  
     
  51.  
    在logic方法中,首先判断已存在的障碍物数量是否为0,
  52.  
    若为0则调用ran方法生成一个随机数作为障碍物的高度,
  53.  
    并创建上下两个障碍物对象。这两个对象的x坐标都为600,
  54.  
    即在屏幕最右边生成,并分别设置其高度为numberTop和500-numberDown。
  55.  
     
  56.  
    若已存在障碍物,
  57.  
    则检测最后一个障碍物是否已经完全进入屏幕内(即其x坐标是否小于0),
  58.  
    若已经进入则和上述过程相同再生成一个新的障碍物对。
  59.  
     
  60.  
    总的来说,这段代码的作用是实现游戏中不断生成障碍物的效果,
  61.  
    并且保证生成的障碍物数量始终能够满足游戏的需求。
  62.  
    */
  63.  
    public void draw(Graphics g,Bird bird){
  64.  
    // 如果不使用循环进行编写
  65.  
    //new一个障碍物类
  66.  
    // Barrier barrier = new Barrier(200, 0, 200, 0);
  67.  
    // barrier.draw(g);
  68.  
    // barriers.add(barrier);
  69.  
    // barriers.get(0).draw(g);
  70.  
    // Barrier barrier1 = new Barrier(300, 0, 300, 2);
  71.  
    // barriers.add(barrier1);
  72.  
    // barriers.get(1).draw(g);
  73.  
     
  74.  
     
  75.  
    // 定义了一个循环变量i,初始值为0,每次循环自增1,
  76.  
    // 直到i小于barriers的大小(即barriers列表中元素的数量)时循环结束。
  77.  
    for(int i = 0; i < barriers.size(); i ){
  78.  
    // 通过get(i)方法从barriers列表中获取当前元素
  79.  
    // 并给barrier变量赋值,用于之后的操作。
  80.  
    Barrier barrier = barriers.get(i);
  81.  
    // 判断barrier元素的可见属性是否为true,
  82.  
    // 如果是,就执行下一行的代码;否则执行else语句块中的代码。
  83.  
     
  84.  
    if (barrier.getVisible() == true){
  85.  
    //调用barrier元素的draw()方法来绘制该元素的外观,
  86.  
    // 即在屏幕上显示。
  87.  
    barrier.draw(g);
  88.  
    }else{
  89.  
    // 从barriers列表中移除当前元素并将其赋给remove变量。
  90.  
     
  91.  
    Barrier remove =barriers.remove(i);
  92.  
    // 将remove元素放回对象池(可以理解为回收该对象,
  93.  
    //以便之后重复利用)。
  94.  
     
  95.  
    Barrierpool.setPool(remove);
  96.  
    //由于remove元素被移除后,
  97.  
    //后面的元素都往前移了一位,
  98.  
    //所以需要将循环变量i减去1以便下一次循环能正确地处理所有元素。
  99.  
    i--;
  100.  
    }
  101.  
     
  102.  
    }
  103.  
    // 判断小鸟是否发生碰撞
  104.  
    collideBird(bird);
  105.  
    //
  106.  
    logic(g,bird);
  107.  
    }
  108.  
     
  109.  
    /*游戏的主要逻辑部分。首先判断是否已经生成了障碍物,如果没有则调用 `ran()` 方法生成随机数来决定生成障碍物的种类和数量,并开始计时。然后根据障碍物种类和数量调用 `insert()` 方法创建相应数量的障碍物对象,添加到 `barriers` 集合中。
  110.  
     
  111.  
    如果已经存在障碍物,则显示已经坚持的时间和当前小鸟的生命值,并根据上一次的最高记录调用 `getTxt()` 方法获取最高纪录,如果当前时间比最高纪录长,则更新最高纪录并调用 `setTxt()` 方法保存到文件中。接着判断最后一个障碍物是否已经完全进入屏幕内,如果是则再次随机生成障碍物种类和数量,并调用 `insert()` 方法创建新的障碍物对象后添加到 `barriers` 集合中。最后刷新游戏窗口,并继续下一次循环*/
  112.  
    public void logic(Graphics g,Bird bird){
  113.  
    // 如果障碍物集合为空
  114.  
    if(barriers.size() == 0){
  115.  
    // 随机数方法,得到两个随机数
  116.  
    ran();
  117.  
    //添加计时
  118.  
    gameTime.begin();
  119.  
     
  120.  
     
  121.  
    //障碍物从屏幕最右边生成
  122.  
    //上方
  123.  
    // Barrier top = new Barrier(600, 0, numberTop, 0);
  124.  
    // barriers.add(top);
  125.  
    //下方
  126.  
    // Barrier down = new Barrier(600, 500-numberDown, numberDown, 2);
  127.  
    // barriers.add(down);
  128.  
    // 获取到一个障碍物并进行赋值,上方的
  129.  
    insert(600, 0, numberTop, 0);
  130.  
    // 获取到一个下方的障碍物并进行赋值,同时把障碍物存入集合中
  131.  
    insert(600, 500-numberDown, numberDown, 2);
  132.  
     
  133.  
    }else{
  134.  
    // 获得游戏时间,并把游戏时间打印出来
  135.  
    long differ = gameTime.differ();
  136.  
    //设置字体,格式,大小
  137.  
    g.setFont(new Font("微软雅黑", 1, 20));
  138.  
    //设置字体颜色
  139.  
    g.setColor(Color.black);
  140.  
    //画出经历的时间
  141.  
    g.drawString("坚持了" differ "秒", 30, 50);
  142.  
    //画出小鸟生命值剩余情况
  143.  
    g.drawString("小鸟生命:" bird.life,450,50);
  144.  
    //获得文本内储存的数据
  145.  
    txt = getTxt();
  146.  
    if (differ <= txt){
  147.  
    //如果经历的时间小于文本内储存的数据,打印最高成绩为文本内数据
  148.  
    g.drawString("最高成绩 :" txt, 200, 50);
  149.  
    }else{
  150.  
    //否则,储存最高记录
  151.  
    setTxt(String.valueOf(differ));
  152.  
    // 打印最高记录
  153.  
    g.drawString("最高成绩:" differ, 200, 50);
  154.  
    }
  155.  
    //判断最后一个障碍物是否完全进入屏幕内
  156.  
    Barrier last = barriers.get(barriers.size() - 1);
  157.  
    //如果进入屏幕内
  158.  
    if (last.isInFrame()){
  159.  
    //重新生成随机数
  160.  
    ran();
  161.  
    // 生成的随机数小于50
  162.  
    if(number < 50){
  163.  
    // 画
  164.  
    insert(600, 50, 350, 4);
  165.  
    // System.out.println("440的障碍物");
  166.  
    }else if(number > 450){
  167.  
    insert(600, 125, 200, 6);
  168.  
    // System.out.println("220的一个障碍物");
  169.  
    }else{
  170.  
    insert(600, 0, numberTop, 0);
  171.  
    insert(600, 500-numberDown, numberDown, 2);
  172.  
    }
  173.  
    // //障碍物从屏幕最右边生成.创建上下两个障碍物对象
  174.  
    // //上方
  175.  
    // Barrier top = new Barrier(600, 0, numberTop, 0);
  176.  
    // barriers.add(top);
  177.  
    // //下方
  178.  
    // Barrier down = new Barrier(600, 500-numberDown, numberDown, 2);
  179.  
    // barriers.add(down);
  180.  
     
  181.  
    }
  182.  
    }
  183.  
    }
  184.  
    //从池中获取对象,把参数封装成barrier存入barriers数组中
  185.  
    /*这段代码的作用是往一个存储障碍物的列表中添加一个新的障碍物,
  186.  
    总体来说,这段代码是实现了从对象池中获取一个Barrier对象,
  187.  
    并通过给其属性赋值的方式来创建一个新的障碍物,
  188.  
    最后将其添加到存储障碍物的列表中。
  189.  
    这种方式可以避免频繁地创建和销毁对象带来的性能问题。
  190.  
    */
  191.  
    //定义了一个公共方法insert,传入参数包括障碍物的位置和类型信息
  192.  
    public void insert(int x, int y, int num, int type){
  193.  
    // 从一个对象池中获取一个Barrier对象,并赋值给top变量
  194.  
    Barrier top = Barrierpool.getPool();
  195.  
    // 给top对象设置x坐标
  196.  
    top.setX(x);
  197.  
    // 给top对象设置y坐标。
  198.  
     
  199.  
    top.setY(y);
  200.  
    // //给top对象设置长度
  201.  
    top.setHeight(num);
  202.  
     
  203.  
    // 给top对象设置类型。
  204.  
    top.setType(type);
  205.  
    //设置visiable的值为true
  206.  
    top.setVisible(true);
  207.  
    // 将top对象添加到一个存储障碍物的列表中。
  208.  
    barriers.add(top);
  209.  
    }
  210.  
     
  211.  
    //上方障碍物高度
  212.  
    private int numberTop;
  213.  
    //下方障碍物高度
  214.  
    private int numberDown;
  215.  
    //中间悬浮的障碍物
  216.  
    private int number;
  217.  
     
  218.  
    //产生三个100~500的随机数的方法
  219.  
    public void ran(){
  220.  
    numberTop = random.nextInt(400) 100;
  221.  
    numberDown = random.nextInt(400) 100;
  222.  
    number = random.nextInt(500);
  223.  
     
  224.  
     
  225.  
    //如果管道重合(两个管道的高度和大于450,小鸟无法飞过),重新生成随机数
  226.  
    if (numberTop numberDown >= 450){
  227.  
    ran();
  228.  
    }
  229.  
    }
  230.  
    //判断障碍物与小鸟发生碰撞
  231.  
    public boolean collideBird(Bird bird){
  232.  
    for (int i = 0; i < barriers.size(); i ) {
  233.  
    // 获得障碍池中的障碍物对象
  234.  
    Barrier barrier = barriers.get(i);
  235.  
    // 矩形框的碰撞方法,判断矩形框是否有重合
  236.  
    if (barrier.getRect().intersects(bird.getRect())){
  237.  
    System.out.println("撞上了");
  238.  
    // 撞上后小鸟的生命值减一
  239.  
    bird.life--;
  240.  
    // 移除与小鸟相撞的障碍物对象
  241.  
    barriers.remove(barrier);
  242.  
     
  243.  
    }
  244.  
    }
  245.  
     
  246.  
    return false;
  247.  
     
  248.  
    }
  249.  
    //清空障碍物池的方法
  250.  
    public void restant(){
  251.  
    barriers.clear();
  252.  
    }
  253.  
     
  254.  
    //创建一个File,传入记录最高分数文件的路径,创建的文件内传入一个数字,否则会报出异常
  255.  
    static File file = new File("传入txt文件的路径");
  256.  
    //储存数据了,写入一个字符串到文件中
  257.  
    public static void setTxt(String str){
  258.  
    // 创建一个FileWrite的对象,该对象是FileWriter的实现类,置为null,方便异常处理
  259.  
    FileWriter fileWriter = null;
  260.  
    try {//利用传入的文件对象,创建FileWriter对象,指定写入的文件
  261.  
    fileWriter = new FileWriter(file);
  262.  
    } catch (IOException e) {
  263.  
    e.printStackTrace();
  264.  
    }
  265.  
    try {//调用write方法,把参数str写入到文件中
  266.  
    fileWriter.write(str);
  267.  
    } catch (IOException e) {
  268.  
    e.printStackTrace();
  269.  
    }
  270.  
    try {//关闭文件
  271.  
    fileWriter.close();
  272.  
    } catch (IOException e) {
  273.  
    e.printStackTrace();
  274.  
    }
  275.  
     
  276.  
    }
  277.  
    //得到文件中的数据
  278.  
    public int getTxt(){
  279.  
    //创建一个名为in的BufferedReader对象,该对象取至file文件,null方便进行异常处理
  280.  
    BufferedReader in = null;
  281.  
    // 通过readLine方法逐行读取文件内容,并将其解析为整数值,赋值给read
  282.  
    try {//利用传入的文件file,创建BufferedReader的对象
  283.  
    in = new BufferedReader(new FileReader(file));
  284.  
    } catch (FileNotFoundException e) {
  285.  
    e.printStackTrace();
  286.  
    }
  287.  
    // String s = in.readLine();
  288.  
    int read = 0;
  289.  
     
  290.  
    try {//从文件中读取一行字符串,并将其转换为整型值
  291.  
    read = Integer.parseInt(in.readLine());
  292.  
    } catch (IOException e) {
  293.  
    e.printStackTrace();
  294.  
    }
  295.  
    try {//关闭文件流
  296.  
    in.close();
  297.  
    } catch (IOException e) {
  298.  
    e.printStackTrace();
  299.  
    }//返回读到的整型值
  300.  
    return read;
  301.  
    }
  302.  
     
  303.  
    }
学新通

Barrierpool类:障碍物池类

创建用于管理池中所有对象的容器

定义池中初始化对象的个数和池中对象的最大个数

使用静态代码块初始化池中的对象

分别定义从从池中获取对象和把对象归还容器的方法

  1.  
    package main;
  2.  
     
  3.  
     
  4.  
    import java.util.List;
  5.  
    import java.util.ArrayList;
  6.  
     
  7.  
    /*每次需要障碍物的时候都会创建一个对象,占用大量内存,需要创建一个对象池类
  8.  
    为了避免反复创建和销毁对象,使用对象池来创建好一些对象,
  9.  
    使用的时候从池中获得,使用完毕后,归还*/
  10.  
    public class Barrierpool {
  11.  
     
  12.  
    /*这段代码是一个使用对象池技术实现的管理器。
  13.  
    对象池是一种重复利用已经创建的对象来避免重复创建和
  14.  
    销毁对象的技术,从而提高程序性能。
  15.  
     
  16.  
    在这个示例中,对象池中存储的是Barrier对象。
  17.  
    这个对象池使用一个静态的List<Barrier>来存储对象,
  18.  
    而不是每次需要一个Barrier对象时都重新创建。
  19.  
    对象池的大小是之前定义的initCount。*/
  20.  
    //用于管理池中所有对象的容器
  21.  
    private static List<Barrier> pool = new ArrayList<>();
  22.  
    //池中初始化对象的个数
  23.  
    public static final int initCount = 16;
  24.  
    //对象池中最大个数
  25.  
    public static final int maxCount = 20;
  26.  
     
  27.  
    /*初始化对象池的过程在static块中进行,
  28.  
    这个块是在类加载时运行的,并且只会执行一次。
  29.  
    在这个示例中,
  30.  
    static块创建了initCount个Barrier对象,
  31.  
    并将它们添加到对象池中。
  32.  
    这样,在需要Barrier对象的时候,
  33.  
    程序可以从对象池中获取可用的对象,
  34.  
    而不是重新创建一个新的对象。
  35.  
    */
  36.  
    //初始化池中的对象
  37.  
    static{
  38.  
    for (int i = 0; i < initCount; i ) {
  39.  
    pool.add(new Barrier());
  40.  
    }
  41.  
    }
  42.  
     
  43.  
    //从池中获取一个对像
  44.  
    public static Barrier getPool(){
  45.  
    //获得池中对象的个数
  46.  
    int size = pool.size();
  47.  
    //如果池中有对象才可以拿对象
  48.  
    if (size > 0){
  49.  
    //移除并返回对象
  50.  
    System.out.println("拿走一个");
  51.  
    return pool.remove(size - 1);
  52.  
    }else{
  53.  
    //池中没有对象,只能new
  54.  
    System.out.println("新的对象");
  55.  
    //新定义一个对象,返回给方法
  56.  
    return new Barrier();
  57.  
    }
  58.  
    }
  59.  
    //把对象归还容器
  60.  
    public static void setPool(Barrier barrier){
  61.  
    //如果池中障碍物的数量小于最大数量
  62.  
    if (pool.size() < maxCount){
  63.  
    //向池中添加障碍物
  64.  
    pool.add(barrier);
  65.  
    System.out.println("容器归还了");
  66.  
    }
  67.  
    }
  68.  
    }
学新通

GameFrontGround类:背景类

定义云彩的个数,存放云彩的集合,云彩的飞行速度;

得到资源图片,制造随机数的函数;

构造器初始化数据;

绘制云彩的方法;

控制云彩个数的方法;

  1.  
    package main;
  2.  
     
  3.  
    import util.GameUtil;
  4.  
     
  5.  
    import java.awt.*;
  6.  
    import java.awt.image.BufferedImage;
  7.  
    import java.util.ArrayList;
  8.  
    import java.util.List;
  9.  
    import java.util.Random;
  10.  
     
  11.  
    //背景类
  12.  
    public class GameFrontGround {
  13.  
    //云彩的个数
  14.  
    private static final int CLOUND_COUNT = 2;
  15.  
    //存放云彩的容器
  16.  
    /*这行代码是定义了一个名为clouds的List对象,
  17.  
    其中存储了一组Cloud对象。
  18.  
    这个List是Java中的一种集合,
  19.  
    使用它可以把若干个元素放在一起,
  20.  
    进行批量操作,比如添加元素、遍历元素、
  21.  
    删除元素等等。
  22.  
    具体的使用方式可能需要根据具体的场景和业务需求来进行调整。
  23.  
    */
  24.  
    private List<Cloud> clouds;
  25.  
    //云彩飞行的速度
  26.  
    private static final int CLOUND_SPEED = 1;
  27.  
    /*这行代码定义了一个类型
  28.  
    为 BufferedImage 数组的变量 img。
  29.  
     
  30.  
    BufferedImage 是 Java 中表示图像的类,
  31.  
    它是一个实现了 RenderedImage 接口的缓存图像类,
  32.  
    可以用于操作和修改图像数据。
  33.  
    数组表示可以存储多张图片数据的数组,
  34.  
    每个元素代表一张图片,可以对每张图片单独进行操作。
  35.  
    因此,private BufferedImage[] img;
  36.  
    定义了一个变量 img,
  37.  
    它可以存储多张 BufferedImage 图像,
  38.  
    可以对每张图片进行单独处理。*/
  39.  
    //使用到的图片资源
  40.  
    private BufferedImage[] img;
  41.  
     
  42.  
    //制造随机数的函数
  43.  
    private Random random;
  44.  
     
  45.  
    //构造器初始化数据
  46.  
    public GameFrontGround(){
  47.  
     
  48.  
    /*这行代码声明了一个名
  49.  
    为 "clouds" 的 ArrayList(动态数组)对象,
  50.  
    并对其进行初始化。在这个例子中,
  51.  
    "<>" 符号表示 ArrayList 存储的是未知类型的元素,
  52.  
    这样声明和初始化 ArrayList 对象后,
  53.  
    就可以在其中存储和操作元素。通常,
  54.  
    开发人员使用 add() 方法将元素添加到 ArrayList中,
  55.  
    使用 get() 方法访问 ArrayList 中的特定元素,
  56.  
    使用 size() 方法获取 ArrayList 的大小等。*/
  57.  
    //实例化存放云彩的容器
  58.  
    clouds = new ArrayList<>();
  59.  
    //定义数组中储存元素的最大数量
  60.  
    img = new BufferedImage[CLOUND_COUNT];
  61.  
    //容器中添加云彩图片
  62.  
    for (int i = 0; i < CLOUND_COUNT; i ) {
  63.  
    //调用GameUtil方法中的loadBufferedImage方法来获取图片添加到
  64.  
    //img数组中
  65.  
    img[i] = GameUtil.loadBufferedImage("newBird\\img\\cloud" i ".png");//括号内填写图片的路径
  66.  
    }
  67.  
    //创建一个随机数的对象
  68.  
    random = new Random();
  69.  
    }
  70.  
     
  71.  
    //绘制云彩
  72.  
    public void draw(Graphics g){
  73.  
    // //传入图片(创建对象)
  74.  
    //没有使用循环
  75.  
    // Cloud cloud = new Cloud(img[1], CLOUND_SPEED, 300, 300);
  76.  
    // //把云彩添加到容器中
  77.  
    // //clouds是一个集合
  78.  
    // clouds.add(cloud);
  79.  
    //调用方法控制云彩的个数
  80.  
    logic();
  81.  
    for (int i = 0; i < clouds.size(); i ) {
  82.  
    //画出云彩
  83.  
    clouds.get(i).draw(g);
  84.  
    }
  85.  
    }
  86.  
    //控制云彩个数的方法
  87.  
    private void logic(){
  88.  
    //产生一个0~500的随机数
  89.  
    //Math.random()方法产生一个0~1的随机数
  90.  
    //如果生成的随机数小于8
  91.  
    if((int)(500*Math.random())< 8){
  92.  
    ///生成一个新的云的图像,使用了随机的图片速度,位移参数
  93.  
    Cloud cloud = new Cloud(img[random.nextInt(CLOUND_COUNT)], CLOUND_SPEED, 600, random.nextInt(180));
  94.  
    //将新生成的云添加到云列表中
  95.  
    clouds.add(cloud);
  96.  
    }
  97.  
    //去除云彩
  98.  
    for (int i = 0; i < clouds.size(); i ) {
  99.  
    //得到云
  100.  
    Cloud cloud = clouds.get(i);
  101.  
    //如果当前的云对象已经移出了场景
  102.  
    if(cloud.isOutFrame()){
  103.  
    //将当前云对象从云列表删除
  104.  
    clouds.remove(i);
  105.  
    //将当前遍历到的云对象的下标减一,以便下一次循环能够正确遍历到所有的云对象
  106.  
    i--;
  107.  
    System.out.println("云被移除了" cloud);
  108.  
    }
  109.  
    }
  110.  
    }
  111.  
    }
学新通

GameTime类:时间类

定义变量开始时间,游戏结束时的时间,时间差;

计算时间差的方法

计时开始的方法;

  1.  
    package main;
  2.  
     
  3.  
    public class GameTime {
  4.  
    //开始
  5.  
    private long beginTime;
  6.  
    //结束
  7.  
    private long endTime;
  8.  
    //时间差
  9.  
    private long differ;
  10.  
     
  11.  
    public GameTime(){}
  12.  
    //计时开始方法,System调用方法,计算从起始时间开始到现在的时间
  13.  
    public void begin(){
  14.  
    beginTime = System.currentTimeMillis();
  15.  
    }
  16.  
     
  17.  
    //时间差方法
  18.  
    public long differ(){
  19.  
    //获得从起始时间开始到游戏结束时的时间
  20.  
    endTime = System.currentTimeMillis();
  21.  
    // 得到时间差,除以1000是以秒为单位
  22.  
    return differ = (endTime - beginTime)/1000;
  23.  
    }
  24.  
    }
学新通

Music类:音乐类

声明背景音乐文件

静态代码块加载背景音乐文件

循环播放音乐的方法

停止播放音乐的方法

  1.  
    package main;
  2.  
     
  3.  
    import javax.sound.sampled.*;
  4.  
    import java.io.File;
  5.  
     
  6.  
    public class Music {
  7.  
    //声明了名为music的private static Clip变量,表示音乐文件
  8.  
    private static Clip music;
  9.  
    //加载背景音乐文件,并将其储存在music变量中
  10.  
    static{
  11.  
    File bgMusicFile = new File("newBird\\\\img\\\\bgm2.wav");
  12.  
    try{
  13.  
    AudioInputStream ais = AudioSystem.getAudioInputStream(bgMusicFile);
  14.  
    music = AudioSystem.getClip();
  15.  
    music.open(ais);
  16.  
    }catch (Exception e){
  17.  
    e.printStackTrace();
  18.  
    }
  19.  
    }
  20.  
    public static void playMusic(){
  21.  
    //循环播放
  22.  
    music.loop(Clip.LOOP_CONTINUOUSLY);
  23.  
    }
  24.  
    //停止播放音乐
  25.  
    public static void stopMusic(){
  26.  
    music.stop();
  27.  
    }
  28.  
    }
学新通

util包:

Constant类:初始化游戏中需要用到的一些参数

定义窗口大小的变量;

定义窗口标题,窗口初始化位置;

定义背景颜色;

定义数组存放小鸟图片的路径;

定义数组存放障碍物图片资源的路径;

  1.  
    package util;
  2.  
     
  3.  
    import java.awt.*;
  4.  
     
  5.  
    //初始化需要用到的参数
  6.  
    public class Constant {
  7.  
    //窗口的大小
  8.  
    //定义静态的组最终变量作为宽高
  9.  
    public static final int FRAM_WIDTH = 600;
  10.  
    public static final int FRAM_HEIGHT = 500;
  11.  
    //窗口的标题
  12.  
    //静态的最终变量作为窗口的标题
  13.  
    public static final String FRAM_TITLE = "飞翔的小鸟";
  14.  
     
  15.  
    //窗口初始化的位置
  16.  
    //静态最终变量
  17.  
    public static final int FRAM_X = 200;
  18.  
    public static final int FRAM_Y = 200;
  19.  
     
  20.  
    //图片的路径
  21.  
    public static final String BK_IMG_OATH = "newBird\\img\\bird_bk.png";
  22.  
     
  23.  
    //定义背景的颜色
  24.  
    public static final Color BK_COLOR = new Color(0X4B4CF);
  25.  
     
  26.  
    //存放三张小鸟图片的路径
  27.  
    public static final String[] BIRD_IMG = {
  28.  
    "newBird\\img\\bird_normal.png",
  29.  
    "newBIrd\\img\\bird_up.png",
  30.  
    "newBird\\img\\bird_down.png"
  31.  
    };
  32.  
    //定义障碍物图片资源(路径)
  33.  
    public static final String[] BARRIER_IMG_PATH = {
  34.  
    "newBird\\img\\barrier.png",
  35.  
    "newBird\\img\\barrier_up.png",
  36.  
    "newBird\\img\\barrier_down.png"
  37.  
    };
  38.  
    }
学新通

GameUtil:定义加载图片的工具

装载图片

  1.  
    package util;
  2.  
     
  3.  
     
  4.  
    import javax.imageio.ImageIO;
  5.  
    import java.awt.image.BufferedImage;
  6.  
    import java.io.FileInputStream;
  7.  
    import java.io.IOException;
  8.  
     
  9.  
    //加载图片工具类
  10.  
    public class GameUtil {
  11.  
    //装载图片
  12.  
    public static BufferedImage loadBufferedImage(String imgPath){
  13.  
    try{
  14.  
    /*这里是创建一个输入流,
  15.  
    用来读取指定路径下的文件,
  16.  
    imgPath是文件路径。在该方法中,
  17.  
    我们使用FileInputStream将图片文件读入内存中,
  18.  
    返回BufferedImage对象。
  19.  
    */
  20.  
    return ImageIO.read(new FileInputStream(imgPath));
  21.  
    }catch(IOException e){
  22.  
    e.printStackTrace();
  23.  
    }
  24.  
    return null;
  25.  
    }
  26.  
    }
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcaabf
系列文章
更多 icon
同类精品
更多 icon
继续加载