Java飞翔的小鸟

一、项目分析

创建一个窗口和画板,把画板放到窗口上,在画板上绘画图片
(2)让小鸟在画面中动起来,可以上下飞
(3)让地面和管道动起来
(4)碰撞检测
(5)绘出开始的界面和游戏结束的界面

二、项目展示
 1.开始状态

2.运行状态

 3.结束状态

三、实现代码

1.游戏启动类

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();
    }
 
}

 2.地面类

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.小鸟类
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);
 
    }
 
}
4.柱子类
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 = 144;
        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);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nginx 优化与防盗链

目录 配置Nginx隐藏版本号 Nginx隐藏版本号的方法 修改配置文件法 修改源码法 修改用户与组 设置缓存时间 日志切割 连接超时 更改进程数 配置网页压缩 配置防盗链 fpm参数优化 总结&#xff1a;nginx优化 配置Nginx隐藏版本号 可以使用 Fiddler 工具抓取数据包&…

【Citespace】从Citespace开始的引文可视化分析

CiteSpace 译“引文空间”&#xff0c;是一款着眼于分析科学分析中蕴含的潜在知识&#xff0c;是在科学计量学、数据可视化背景下逐渐发展起来的引文可视化分析软件。由于是通过可视化的手段来呈现科学知识的结构、规律和分布情况&#xff0c;因此也将通过此类方法分析得到的可…

巧用ChatGPT高效搞定Excel数据分析【文末送书-04】

文章目录 一.巧用ChatGPT高效搞定Excel数据分析1. ChatGPT简介2. 安装所需工具2.1 Python2.2 OpenAI GPT库 3. 与ChatGPT交互进行数据分析4. 利用ChatGPT进行筛选和排序5. ChatGPT的局限性和注意事项6. ChatGPT与数据可视化7. ChatGPT与进阶数据分析任务 二. 结论&文末福利…

Windows安装Maven

一、Maven 是什么&#xff1f; Maven 是一个项目管理和整合工具。Maven 为开发者提供了一套完整的构建生命周期框架。开发团队几乎不用花多少时间就能够自动完成工程的基础构建配置&#xff0c;因为 Maven 使用了一个标准的目录结构和一个默认的构建生命周期。 在有多个开发团…

软件开发安全指南

2.1.应用系统架构安全设计要求 2.2.应用系统软件功能安全设计要求 2.3.应用系统存储安全设计要求 2.4.应用系统通讯安全设计要求 2.5.应用系统数据库安全设计要求 2.6.应用系统数据安全设计要求 软件开发全资料获取&#xff1a;点我获取

用Java实现根据数据库中的数量,生成年月份+序号递增

在日常开发中&#xff0c;经常会遇到根据年月日和第几号文件生成对应的编号&#xff0c;今天给大家提供一个简单的工具类 public static final Long CODE1L;/*** param select 数据库中数据总数* return*/public static String SubjectNo(Long select){// 在总数的基础上1&…

c2-C语言--指针

1.用一级指针遍历一维数组 结论 buf[i]<>*(buf i) <> *(p i)<> p[i] #include <stdio.h>int main(){int buf[5] {10,20 ,30 ,40,50}; //buf[0] --- int // buf --&buf[0] ----int *int *p buf;//&buf[0] --- &*(buf0)printf(&quo…

统一存储、全闪阵列、分布式NAS,企业级存储概述

Infortrend普安科技即将迎来公司成立30周年华诞。Infortrend普安科技从无到有&#xff0c;由小做强&#xff0c;为全球用户提供高性能、高可靠、高扩展、环保节能的存储解决方案&#xff0c;在存储领域造就了一段品牌佳话。从1993年成立伊始&#xff0c;Infortrend一直致力于企…

云服务器哪家便宜?亚马逊云科技按需选实例够便宜

随着云计算的迅猛发展&#xff0c;越来越多的企业和个人开始关注云服务器的选择。在众多云服务提供商中&#xff0c;亚马逊云科技&#xff08;Amazon Web Services&#xff0c;AWS&#xff09;凭借其强大的基础设施和丰富的服务&#xff0c;备受业界青睐。本文聚焦一个备受关注…

【lesson3】数据库表的操作

文章目录 创建修改修改表名增加表类型修改表的某一类型的类型修改表某一类型的类型名 删除删除表的某一列删除表 查看查看表信息查看表内容 创建 建表指令&#xff1a; 查看是否建表成功&#xff1a; 查看表的具体信息&#xff1a; 修改 修改表名 法一&#xff1a;修改…

基础宠物商店管理系统(Java)大一程序设计

一.开发环境 Windows 11 -- JDK 21 -- IDEA 2021.3.3 二.需求 三.代码部分 //创建一个宠物类&#xff0c;被另外两类继承public class Pet {private String name;private int age;private String gender;private double cost0;//买进价格private double sellprice0;//卖出价…

hdlbits系列verilog解答(mt2015_q4a)-52

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 本次我们实现一个简单的组合逻辑输出。 z (x^y) & x 模块声明&#xff1a; module top_module (input x, input y, output z); 二、verilog源码 module top_module (input x, input y, output z);assig…

CRM系统是怎样帮助团队处理业务的?

客户关系管理的核心思想是将企业的客户作为最重要的资源&#xff0c;提供优质的客户服务&#xff0c;满足客户的需求&#xff0c;保证实现客户的终生价值&#xff0c;这也是众多企业使用CRM系统的原因。那么&#xff0c;CRM如何帮助中小企业解决业务与团队之间的问题&#xff1…

如何通过IDM进行统一权限

IDM身份管理平台在当今企业信息化建设中扮演着至关重要的角色&#xff0c;它不仅仅关乎用户身份的管理&#xff0c;更牵涉到对企业内部各种资源的合理分配和访问控制。其中&#xff0c;统一权限是 IDM 的一个核心概念&#xff0c;它通过集中管理用户的身份和访问权限&#xff0…

【Spring】Spring统一功能处理

Spring统一功能处理 拦截器拦截器什么是拦截器拦截器的基本使用定义拦截器注册配置拦截器 拦截器详解拦截器的拦截路径配置拦截器实现原理初始化处理请求 适配器模式 统一数据返回格式统一数据返回格式快速入门 统一异常处理 拦截器 场景: 我们要对一个网站实现强制登陆的功能…

mysql:通过INFORMATION_SCHEMA数据库查询表的元信息

使用SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA database_name AND TABLE_NAME table_name;查询某个表的元信息。其中database_name替换为数据库名称&#xff0c;table_name替换为表的名称。 例如&#xff0c;下面语句&#xff0c;查询development数据库中…

二、如何保证架构的质量、架构前期准备、技术填补与崩溃预防、系统重构

1、如何保证架构的质量 -- 稳定性和健壮性 2、正确的选择是良好的开端 -- 架构前期准备 ① 架构师分类&#xff1a;系统架构师、应用架构师、业务架构师 3、技术填补与崩溃预防 4、系统重构

时间序列预测实战(二十四)PyTorch实现RNN进行多元和单元预测(附代码+数据集+完整解析)

一、本文介绍 本篇文章给大家带来的是利用我个人编写的架构进行RNN时间序列卷积进行时间序列建模&#xff08;专门为了时间序列领域新人编写的架构&#xff0c;简单且不同于市面上大家用GPT写的代码&#xff09;&#xff0c;包括结果可视化、支持单元预测、多元预测、模型拟合…

【Python必做100题】之第四题(判断素数)

素数&#xff1a;约数只有1和本身的数叫素数 代码如下&#xff1a; a int(input("请随机输入一个数字&#xff1a;")) #键盘随机输入一个数字进行判断 flag False for i in range(2,a):if a % i 0: #在(2&#xff0c;a-1)之间但凡有一个可以整除就不是素数break…

MyBatis进阶之分页和延迟加载

文章目录 分页1. RowBounds 分页2. PageHelper 分页3. PageInfo 对象属性描述 延迟加载立即加载激进式延迟加载真-延迟加载 分页 Mybatis 中实现分页功能有 3 种途径&#xff1a; RowBounds 分页&#xff08;不建议使用&#xff09;Example 分页&#xff08;简单情况可用)Pag…