Java实现飞翔的鸟小游戏

news2024/11/16 17:44:33

Java实现飞翔的鸟小游戏

1.准备工作

创建一个新的Java项目命名为“飞翔的鸟”,并在src中创建一个包命名为“com.qiku.bird",在这个包内分别创建4个类命名为**“Bird”、“BirdGame”、“Column”、“Ground”,并向需要的图片**素材导入到包内。

2.代码内容

Bird类

package com.qiku.bird;
 
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
 
/*
 * 小鸟类
 * */
public class Bird {
    int x;// 坐标
    int y;
    int width; // 宽高
    int height;
    BufferedImage image; // 图片
    BufferedImage[] images; // 小鸟所有图片
 
    public Bird() {
        // 初始化数组 保存八张图片
        images = new BufferedImage[8];
        // 使用循环结构 将小鸟所有图片 存入数组
        for (int i = 0; i < images.length; i++) {
            try {
                images[i] = ImageIO.read(Bird.class.getResourceAsStream(i + ".png"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        image = BirdGame.bird_image;
        width = image.getWidth();
        height = image.getHeight();
        x = 120;
        y = 240;
    }
 
    // 小鸟飞翔的方法
    int index = 0;
 
    public void fly() {
        image = images[index % images.length];
        index++;
    }
 
    // h = v * t + g * t * t / 2
    int g = 6; //重力加速度
    double t = 0.15; // 下落时间
    double v = 0; // 初速度
    double h = 0; // 下落距离
 
    //小鸟下落一次
    public void down() {
        h = v * t + g * t * t / 2; // 具体下落的距离
        v = v + g * t; // 末速度 = 当前速度 + 重力加速度 * 时间
        y += (int) h;
    }
 
    // 小鸟向上飞
    public void up() {
        // 给一个 负方向的初速度
        v = -30;
    }
    /*
     * 小鸟撞地面
     * */
    public boolean hitGround(Ground ground) {
        boolean isHit = this.y + this.height >= ground.y;
        return isHit;
    }
 
    // 小鸟撞天花板
    public boolean hitCeiling() {
        boolean isHit = this.y <= 0;
        return isHit;
    }
 
    // 小鸟撞柱子
    public boolean hitColumn(Column c) {
        boolean b1 = this.x + this.width >= c.x;
        boolean b2 = this.x <= c.x + c.width;
        boolean b3 = this.y <= c.y + c.height / 2 - c.gap / 2;
        boolean b4 = this.y + this.height >= c.y + c.height / 2 + c.gap / 2;
        // 满足b1 b2表示水平方向 相撞 b1 b2 b3 同时满足 撞上柱子 b1 b2 b4 同时满足撞下柱子
        return b1 && b2 && (b3 || b4);
 
    }
 
}

BirdGame类

package com.qiku.bird;
import javax.imageio.ImageIO;
import javax.swing.*;
 
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
 
/**
 * 游戏启动类
 * 使用extends 关键字 继承JPanel 画板类 ==> 于是BirdGame 就具备了画板类的功能
 */
public class BirdGame extends JPanel {
    //    定义游戏状态
    public static final int START = 0;  // 开始
    public static final int RUNNING = 1;  // 运行
    public static final int GAME_OVER = 2;  // 结束
    // 游戏当前状态 默认0 开始状态
    int state = START;
    int score = 0; //玩家得分
 
    static BufferedImage bg = null; // 背景图片
    static BufferedImage start = null; //开始图片
    static BufferedImage ground_image = null; // 地面
    static BufferedImage bird_image = null; // 小鸟
    static BufferedImage column_image = null; // 柱子
    static BufferedImage gameOver_image = null; // game游戏
 
    // 静态代码块 一般用于加载静态资源(视频,音频,图片等)
    static {
        // 将本地的图片bg.png读取到程序中的bg
        try {
            bg = ImageIO.read(BirdGame.class.getResourceAsStream("bg.png"));
            start = ImageIO.read(BirdGame.class.getResourceAsStream("start.png"));
            ground_image = ImageIO.read(BirdGame.class.getResourceAsStream("ground.png"));
            column_image = ImageIO.read(BirdGame.class.getResourceAsStream("column.png"));
            bird_image = ImageIO.read(BirdGame.class.getResourceAsStream("0.png"));
            gameOver_image = ImageIO.read(BirdGame.class.getResourceAsStream("gameover.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    Ground ground;//声明地面
    Bird bird;
    Column column1;
    Column column2;
 
    // BirdGame 的构造方法
    public BirdGame() {
        bird = new Bird();
        ground = new Ground();
        column1 = new Column();
        column2 = new Column();
        // 柱子2的x坐标 = 柱子1的坐标基础上+244保持水平间距
        column2.x = column1.x + column1.distance;
 
    }
 
    /*
     * 用于在画板上绘制内容的方法
     * 想在画板上显示什么 在这个方法写就行了
     * @param g 画笔
     *  */
    @Override
 
    public void paint(Graphics g) {
        // g.fillRect(0,0,100,200); // 设置颜色落笔点 宽高
        g.drawImage(bg, 0, 0, null); // 画背景
        if (state == START) {
            g.drawImage(start, 0, 0, null);  // 开始图片
        }
        g.drawImage(column1.image, column1.x, column1.y, null); // 画柱子
        g.drawImage(column2.image, column2.x, column2.y, null); // 画柱子2
        g.drawImage(bird.image, bird.x, bird.y, null); //小鸟图片
        g.drawImage(ground.image, ground.x, ground.y, null);  // 地面图片
        if (state == GAME_OVER) {
            g.drawImage(gameOver_image, 0, 0, null); // 结束图片
 
        }
        // 画分数
        Font font = new Font("微软雅黑", Font.BOLD, 25); // 创建字体
        g.setFont(font);  // 给画笔设置字体
        g.setColor(Color.BLACK);  // 设置字体黑色颜色
        g.drawString("分数:  " + score, 30, 50);
        g.setColor(Color.WHITE);  // 设置字体白色颜色
        g.drawString("分数:  " + score, 28, 48);
    }
 
    // 判断小鸟与柱子是否相撞 游戏结束
    public boolean isGameOver() {
        boolean isHit = bird.hitGround(ground) || bird.hitCeiling() || bird.hitColumn(column1) || bird.hitColumn(column2);
        return isHit;
    }
 
 
    // 游戏流程控制的方法
    public void action() throws Exception {
        frame.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                System.out.println(e.getKeyCode());
                if(e.getKeyCode() == 32){
                    if (state == START) {  // 如果是开始状态 单击转换运行
                        state = RUNNING;
                    }
 
                    if (state == RUNNING) {
                        bird.up(); //小鸟上升
                    }
                    if (state == GAME_OVER) {
                        bird = new Bird();
                        column1 = new Column();
                        column2 = new Column();
                        column2.x = column1.x + column1.distance;
                        score = 0;
                        state = START;
                    }
                }
            }
        });
 
 
        // 给当前对象()添加鼠标单击事件
        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) { // 鼠标单击执行代码
                if (state == START) {  // 如果是开始状态 单击转换运行
                    state = RUNNING;
                }
 
                if (state == RUNNING) {
                    bird.up(); //小鸟上升
                }
                if (state == GAME_OVER) {
                    bird = new Bird();
                    column1 = new Column();
                    column2 = new Column();
                    column2.x = column1.x + column1.distance;
                    score = 0;
                    state = START;
                }
 
            }
        });
 
        // 死循环 {}的代码会一直反复执行
        while (true) {
            if (state == START) {
                ground.step(); // 地面移动
                bird.fly(); // 小鸟飞翔
            } else if (state == RUNNING) {
                ground.step(); // 地面移动
                column1.step(); // 柱子1移动
                column2.step(); // 柱子2移动
                bird.fly(); // 小鸟飞翔
                bird.down(); // 小鸟下落
                if (isGameOver() == true) {
                    state = GAME_OVER;
                }
                // 设置增加分数
                if (bird.x == column1.x + column1.width + 1 || bird.x == column2.x + column2.width + 1) {
                    score +=5;
                }
            }
 
            repaint(); //重画 即重新执行paint 方法
            Thread.sleep(10); //每隔10毫秒,让程序休眠一次
        }
    }
    static  JFrame frame = new JFrame();
    // main方法 - 程序的入口(即:有main方法 程序才能运行)
    public static void main(String[] args) throws Exception {
        BirdGame game = new BirdGame(); // 创建画板对象
        frame.setSize(432, 644);//设置宽高
        frame.setLocationRelativeTo(null); // 居中显示
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭窗口,同时使程序结束
        frame.setVisible(true); //设置可见性
        frame.add(game); // 将画板放到画框上
        frame.setTitle("飞翔的小鸟");// 设置标题
        frame.setResizable(false);// 设置不允许玩家拖动界面
 
        // 调用action
        game.action();
    }
 
}

Column类

package com.qiku.bird;
 
import java.awt.image.BufferedImage;
 
/*
 * 柱子类
 * */
public class Column {
    int x;// 坐标
    int y;
    int width; // 宽高
    int height;
    BufferedImage image; // 图片
    int gap; //上下柱子之间的间隙
    int distance; //水平方向柱子之间的距离
    int min = -(1200 / 2 - 144 / 2);
    int max = 644 - 146 - 144 / 2 - 1200 / 2;
 
    public Column() {
        gap = 150;
        distance = 244;
        image = BirdGame.column_image;
        width = image.getWidth();
        height = image.getHeight();
        x = BirdGame.bg.getWidth();
        y = (int) (Math.random() * (max - min) + min);
 
    }
 
    public void step() {
        x--;
        if (x <= -width) {
            x = BirdGame.bg.getWidth();
            y = (int) (Math.random() * (max - min) + min);
        }
    }
}
 

Ground类

package com.qiku.bird;
 
import java.awt.image.BufferedImage;
 
/*
* 地面类
* */
public class Ground {
    int x ;// 地面坐标
    int y ;
    int width ; // 地面的宽高
    int height;
    BufferedImage image; // 地面图片
 
    public Ground(){
        image = BirdGame.ground_image;
        x = 0;
        y = BirdGame.bg.getHeight() - image.getHeight();
 
        width = image.getWidth();
        height = image.getHeight();
    }
    /*
    * 地面走一步的方法
    * */
    public void step(){
        x--;
        if(x <= 432 - width){
            x=0;
        }
    }}

3.运行结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1270880.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

运行启动vue项目报报错node: --openssl-legacy-provider is not allowed in NODE_OPTIONS解决

报错的问题就是package.json中的Scripts下的dev 解决方法就是要不升级你的应用代码&#xff0c;支持 新版本的node.js 要不就是删除SET NODE_OPTIONS--openssl-legacy-provider &&代码&#xff0c;如下代码即可正常运行起来

还在愁没项目?来瞧瞧这些另类赚钱方式

客套话不多说&#xff0c;直接上案例&#xff0c;这些都是正儿八经的真实案例&#xff0c;相信大家通过这些人的案例自然能摸索整理出一套属于自己的项目&#xff01;摸索不出&#xff0c;也多多少少能受一些灵感上的启发。 小A是长期混B站的&#xff0c;大家称他为“B站搬运工…

echarts图表显示不全

图表显示是显示了&#xff0c;但是没有展示全部&#xff0c;一看控制台div的高度只有1px了&#xff0c;手动修改高度也只是拉伸图表&#xff0c;并没有按规定的尺寸展示 随之开始思考为什么呢 ? ? ? 因为 Echarts 的依赖是惰性的&#xff0c;需要手动设置resize&#xff0…

【Openstack Train安装】十三、创建实例

在先前的教程中&#xff0c;介绍了安装openstack及其相关组件的具体过程&#xff0c;本文介绍如何创建实例并完成访问。 在按照本教程操作之前&#xff0c;请确保完成以下配置&#xff1a; 【Openstack Train安装】一、虚拟机创建 【Openstack Train安装】二、NTP安装 【Op…

ubuntu0.22.04.1安装mysql8.0及root密码注意

先看一下你的安装包是什么版本 apt list |grep mysql基本都是默认的8.0版本&#xff0c;然后安装&#xff1a; apt-get install mysql-server-8.0安装以后 &#xff0c;mysql默认启动&#xff1b; 一般root 是没有密码的&#xff0c;在本地直接回车登录 我们看一下密码插件 …

Java系列-new Object的过程

从《深入理解Java虚拟机》里面的第七章看到了一些&#xff0c;先简单记录一下&#xff0c;好多不懂的。 类从被加载到虚拟机内存中开始&#xff0c;到卸载出内存为止&#xff0c;它的整个生命周期包括&#xff1a;加载、验证、准备、解析、初始化、使用和卸载7个阶段。其中验证…

37.从0到上线三天搭建个人网站(第一天)

点赞收藏加关注&#xff0c;你也能住大别墅&#xff01; 挑战三天搭建个人网站 从0到上线 一、项目的主要功能 1.作为自己在网上的一个工作室。 2.发帖 3.展示个人项目连接 4.介绍自己&#xff08;没准儿还能接点活儿&#xff09; 二、UI风格参考 三、技术选型 1.前端&a…

宋仕强论道之华强北自组织和激励模式(十四)

宋仕强论道之华强北自组织和激励模式&#xff08;十四&#xff09;: 为什么一个小小深圳市华强北我宋仕强就讲这么久呢&#xff0c;听说玄奘大和尚刚出道时在洛阳的白马寺讲经&#xff0c;一个“悟”字就讲了三个月。一个事物有他的复杂性和多样性&#xff0c;从自然科学和社会…

STM32CubeMX HAL F405 TIM1输出多路不同频率及占空比的方波(PWM)(输出比较模式)

TIM1_CH1 TIM1_CH1N TIM1_CH2 TIM1_CH2N TIM1_CH3 TIM1_CH3N TIM1_CH4 TIM1的通道1、2、3输出同频率&#xff08;20KHz&#xff09;的PWM波形(占空比50%) TIM1的通道1输出100Hz的PWM波形(占空比50%) #include "tim.h"/* USER CODE BEGIN 0 */ uint16_t f1 100;…

科聪停车移动机器人整体解决方案!

停车机器人是用于在停车场或车库等场所中进行车辆的自动停放和取车操作。随着智能交通和智能城市的发展&#xff0c;停车机器人在解决停车难、提高停车效率和减少停车空间浪费等方面具有广阔的应用前景。 科聪停车机器人解决方案&#xff1a; 本方案中核心部分采用的是科聪通用…

DC电源模块的基本工作原理和应用

BOSHIDA DC电源模块的基本工作原理和应用 DC电源模块是一种能够将交流电转化为直流电的电子装置。它的基本工作原理是利用变压器、整流桥、电容滤波、电压稳定器等电路组成&#xff0c;将输入的交流电转换为稳定的直流电输出。这种直流电源模块通常可以提供不同的电压和电流输…

一觉醒来!Keras 3.0史诗级更新,大一统深度学习三大后端框架【Tensorflow/PyTorch/Jax】

不知道大家入门上手机器学习项目是首先入坑的哪个深度学习框架&#xff0c;对于我来说&#xff0c;最先看到的听到的就是Tensorflow了&#xff0c;但是实际上手做项目开发的时候却发现了一个很重要的问题&#xff0c;不容易上手&#xff0c;基于原生的tf框架来直接开发模总是有…

MySQL之redo log

聊聊REDO LOG 为什么需要redolog&#xff1f; 那redolog主要是为了保证数据的持久化&#xff0c;我们知道innodb存储引擎中数据是以页为单位进行存储&#xff0c;每一个页中有很多行记录来存储数据&#xff0c;我们的数据最终是要持久化到硬盘中&#xff0c;那如果我们每进行…

优思学院|六西格玛质量管理如何提升顾客满意度?

顾客满意度是一种无价的商品&#xff0c;它必须被赢得。 近年来&#xff0c;人们对于顾客满意度与企业的财务业绩之间的关系越来越关注&#xff0c;顾客满意之所以会如此持久地引起人们的强烈关注&#xff0c;是因为人们认为顾客满意能为企业带来较强的市场竞争优势和更高的市…

【攻防世界-misc】[简单] 简单的base编码

1.下载并打开文件 2.由于题目说的是base编码&#xff0c;就用base在线工具解码&#xff0c;多次尝试后是base64编码&#xff0c;但由于这个文件内容太多了&#xff0c;所以需要多次&#xff08;18次&#xff09;解码才可以获得flag值。 CTF在线工具-在线base编码|在线base解码…

【网络奇缘】- 计算机网络|分层结构|深入学习ISO模型

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏: 一见倾心,再见倾城 --- 计算机网络~&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 回顾链接&#xff1a;http://t.csdnimg.cn/nRRzR 这篇文章是关于深入学习OSI模型七层结构&#xff0c; “书山…

java审计之java反序列化-CC链

介绍 序列化的本质是内存对象到数据流的一种转换&#xff0c;我们知道内存中的东西不具备持久性&#xff0c;但有些场景却需要将对象持久化保存或传输。 在Java工程中&#xff0c;序列化还广泛应用于JMX&#xff0c;RMI&#xff0c;网络传输&#xff08;协议包对象&#xff09…

猫头虎分享ubuntu20.04下VSCode无法输入中文解决方法

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

android framework分屏“官方”黑屏bug问题发现,你会分析吗?-千里马实战作业挑战

背景 hi&#xff0c;粉丝朋友们&#xff1a; 大家都知道马哥课程以实战为特色&#xff0c;这里的实战就是最贴近公司里面开发的实战项目。这些实战主要来自哪呢&#xff1f; 1、以前在公司的工作积累&#xff0c;自己在公司做过什么&#xff0c;这部分比较好毕竟都是搞过的 2…

【华为OD题库-049】评论转换输出-java

题目 在一个博客网站上&#xff0c;每篇博客都有评论。每一条评论都是一个非空英文字母字符串。评论具有树状结构&#xff0c;除了根评论外&#xff0c;每个评论都有一个父评论。 当评论保存时&#xff0c;使用以下格式: 首先是评论的内容; 然后是回复当前评论的数量。 最后是当…