JAVA实现flappy bird游戏

图片素材

实现代码

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.io.IOException;public class BackGroundView extends JPanel {BufferedImage bgImage; //背景图片BufferedImage groundImg;//地面图片BufferedImage imgStart;//开始游戏图片BufferedImage imgEnd;//GameOVer图片public int bg_width;//背景图片宽度public int bg_height;//背景图片高度public int ground_width;//地面图片宽度public int ground_height;//地面图片高度public int ground_x,ground_y;//地面绘制起始坐标public int speed = 0;//管道和地面移动的速度public int state = 0;//游戏状态,0表示未开始,1表示正在玩,2表示GameOverpublic static final int MOVE_SPEED1 = 50;// 地面及柱子移动初始速度,当积分累加,速度会递增public static final int jframeWidth = 432;//窗口宽度(bg.png宽度)public static final int jframeHeight = 644;//窗口高度(bg.png高度)public static final String PATH_PIC = "\\pictures\\";public static final String PATH_BG = PATH_PIC + "bg.png";//背景图片路径public static final String PATH_GROUND = PATH_PIC + "ground.png";public static final String PATH_IMGSTART = PATH_PIC + "start.png";public static final String PATH_IMGEND = PATH_PIC + "gameover.png";public static final int FONT_SIZE = 30;//得分字体大小public static final int SCORE_X = 20;public static final int SCORE_Y = 40;public int score;public JFrame jframeMain;public GameBoard gameBoard;public Bird bird;public Pipe pipe1,pipe2;public BackGroundView(){initFrame();//初始化窗口}public void initFrame(){jframeMain = new JFrame("Flappy Bird");jframeMain.setSize(jframeWidth, jframeHeight);jframeMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jframeMain.setLocationRelativeTo(null);//居中显示jframeMain.setResizable(false);//窗口Size固定gameBoard = new GameBoard();//初始化内部类GameBoardjframeMain.add(gameBoard);Thread moveAll = new Thread(gameBoard);moveAll.start();}//游戏面板class GameBoard extends JPanel implements Runnable{public GameBoard(){initGame();//初始化游戏}public void initGame(){//原则:先加载后绘制try{//1、加载背景图片bgImage = ImageIO.read(this.getClass().getResource(PATH_BG));//根据当前路径加载图片进内存//获取图片宽度与高度bg_width = bgImage.getWidth();bg_height = bgImage.getHeight();System.out.println("bg_width:" + bg_width + ",bg_height:" + bg_height);//2、加载地面图片,注意大的图片要先加载,否则会遮住之前加载的groundImg = ImageIO.read(this.getClass().getResource(PATH_GROUND));ground_width = groundImg.getWidth();ground_height = groundImg.getHeight();ground_x = 0;ground_y = bg_height - ground_height;System.out.println("ground_width:" + ground_width + ",ground_height:" + ground_height);System.out.println("ground_x:" + ground_x + ",ground_y:" + ground_y);//3、加载开始和结束图片imgStart = ImageIO.read(this.getClass().getResource(PATH_IMGSTART));imgEnd = ImageIO.read(this.getClass().getResource(PATH_IMGEND));//4、加载小鸟图片,并在绘制中绘制小鸟,在run中让小鸟飞动bird = new Bird();//5、加载管道图片,一个窗口中最多显示两个管道pipe1 = new Pipe(bg_width, bg_height, ground_height);pipe1.x = bg_width;//第一根管道位置pipe2 = new Pipe(bg_width, bg_height, ground_height);pipe2.x = bg_width + Pipe.PIPE_DISTANCE;//第二跟管道位置}catch (IOException e){ }//3、让地面移动speed = MOVE_SPEED1;//速度初始化}@Overridepublic void run() {action();//处理键盘事件//移动while(true){try{if (state == 0) {groundMove();//地面移动,初始化窗口未开始游戏地面和小鸟就要动bird.fly();//小鸟飞动}else if (state == 1){groundMove();//地面移动,初始化窗口未开始游戏地面和小鸟就要动bird.fly();//小鸟飞动bird.down();//仅游戏开始时下降pipe1.move();//让两根管子动起来pipe2.move();//小鸟撞到地面,天空,柱子都GameOverif (bird.hitPipe(pipe1) || bird.hitPipe(pipe2) || bird.hitGround(bg_height, ground_height) || bird.hitSky()){state = 2;}else {if (bird.addScore(pipe1) || bird.addScore(pipe2)){//每次通过一个得分加10分,速度也增加score += 10;speed += 2;}}}else if (state == 2){}Thread.sleep(1000 / speed);//speed越大线程休眠时间越少,执行次数越多,速度就越快this.repaint();//刷新,会自动重新调用paint()方法}catch (InterruptedException e){ }}}public void groundMove(){ground_x--;//地面左移,可以实现小鸟右移if (ground_x == bg_width - ground_width + 9){//9为修正值,自己调的,保证移动更流畅ground_x = 0;}}public void action(){//设置监听事件this.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {super.mouseClicked(e);switch(state){case 0://游戏未开始点击,就切换为开始游戏state = 1;bird.x = Bird.BIRD_FLY_X;bird.y = Bird.BIRD_FLY_Y;break;case 1://游戏开始bird.up();//游戏中点击就是上升break;case 2://切换到未开始状态,得分清零,小鸟与管道位置重置state = 0;score = 0;bird.x = Bird.BIRD_X;bird.y = Bird.BIRD_Y;pipe1.x = bg_width;pipe2.x = bg_width + Pipe.PIPE_DISTANCE;break;default:break;}}});}@Overridepublic void paint(Graphics g) {super.paint(g);//System.out.println("paint方法被调用时间:" + getCurrentTime());g.drawImage(bgImage,0,0,null);//绘制背景if (state == 0){//游戏未开始g.drawImage(imgStart,0,0,null);g.drawImage(bird.img, bird.x, bird.y, null);}else if (state == 1){//游戏开始g.drawImage(bird.img, bird.x, bird.y, null);//点击开始后,初始坐标也同时变g.drawImage(pipe1.img, pipe1.x, pipe1.y, null);g.drawImage(pipe2.img, pipe2.x, pipe2.y, null);}else if (state == 2){//游戏结束g.drawImage(imgEnd,0,0,null);}g.drawImage(groundImg , ground_x, ground_y, null);//绘制地面//绘制分数Graphics2D gg = (Graphics2D) g;Font scoreFont = new Font("微软雅黑", Font.BOLD, FONT_SIZE);//得分字体//下面两句是抗锯齿模式,消除文字锯齿,字体更清晰顺滑gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);gg.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);gg.setFont(scoreFont);gg.setColor(Color.WHITE);gg.drawString("" + score, SCORE_X, SCORE_Y);}//当前时间public String getCurrentTime() {Date day = new Date();SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");return df.format(day);}}public void showView(){jframeMain.setVisible(true);}
}
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;//小鸟类
public class Bird {public static final int BIRD_PIC_COUNT = 8;//小鸟图片个数,8张图片轮播形成飞行时的样子public static final int BIRD_X = 190;//初始化小鸟坐标(游戏未开始小鸟位置)public static final int BIRD_Y = 220;public static final int BIRD_FLY_X = 120;//开始游戏后小鸟初始坐标public static final int BIRD_FLY_Y = 240;public static final int BIRD_UP_SPEED = 6;public static int index = 0;//当前小鸟图片序号public int x,y;//小鸟坐标public int width;//小鸟宽度public int height;//小鸟高度public double g = 9.8;//重力加速度public double t = 0.05;//自然下降时间public double v,h;//下降速度与下降距离BufferedImage img;BufferedImage[] imgs = new BufferedImage[BIRD_PIC_COUNT];public Bird(){try{for (int i = 0; i < 8; i++) {imgs[i] = ImageIO.read(this.getClass().getResource(BackGroundView.PATH_PIC + i + ".png"));}img = imgs[0];//获取小鸟宽高width = img.getWidth();height = img.getHeight();//初始化小鸟位置x = BIRD_X;y = BIRD_Y;}catch (IOException e){ }}// 小鸟飞翔的图片切换public void fly() {index++;// 小鸟图形切换的频率,index/x,x越大,翅膀切换频率越慢,index到48完成一次轮播img = imgs[index / 6 % BIRD_PIC_COUNT];//除以6是调整速度if (index == 6 * BIRD_PIC_COUNT) {index = 0;}}//上升public void up(){v = BIRD_UP_SPEED;//上升,鼠标点击小鸟上升20}//下降public void down() {v = v - g*t;// Vt=Vo-gth = v - g*t*t/2;// h=Vot-gt²/2y = y - (int)h;}// 碰撞检测// 是否碰撞地面public boolean hitGround(int bg_height, int ground_height) {if (y + height >= (bg_height - ground_height)) {return true;}return false;}// 碰撞到舞台顶部public boolean hitSky() {if (y <= 0) {return true;}return false;}// 碰到柱子时的检测public boolean hitPipe(Pipe p) {// x方向小鸟和柱子碰撞的条件if ((x + width) >= p.x && x <= p.x + p.width) {if (y <= p.y + (p.height - Pipe.PIPE_GAP) / 2|| y >= p.y + (p.height + Pipe.PIPE_GAP) / 2 - height) {return true;}}return false;}// 增加积分,通过管道后调用该方法public boolean addScore(Pipe p) {if (x == p.x + p.width) {return true;}return false;}
}
public class Main {public static void main(String[] args) {new BackGroundView().showView();}
}
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;public class Pipe {public static int PIPE_GAP = 144;//中间可通过的缺口大小public static int PIPE_DISTANCE = 244;//管道之间的间距BufferedImage img;//管道图片public int x,y;//坐标public int width,height;//柱子宽高private int max, min;//保证管道完全能显示在屏幕上,所以要设置max与minRandom random = new Random();//管道随机出现public int bg_width;public Pipe(int bg_width, int bg_height, int ground_height){this.bg_width = bg_width;try{img = ImageIO.read(this.getClass().getResource(BackGroundView.PATH_PIC + "pipe.png"));width = img.getWidth();height = img.getHeight();System.out.println("Pipe_width = " + width + ",Pipe_height = " + height);//width=74,height=1200x = bg_width;//管道在不在初始背景出现,在背景"右边"max = (height - PIPE_GAP) / 2;//图片有上下两管道,这个max表示一个管道的高度min = (height - PIPE_GAP) / 2 - (bg_height - PIPE_GAP - ground_height);//管道出现的最小长度y = -(min + random.nextInt(max - min));//管道随机出现的坐标}catch (IOException e){ }}//游戏开始,柱子就要向左移动public void move(){x--;//若柱子走出最左边窗口,管道就重新初始化if (x == -width){x = bg_width;y = -(min + random.nextInt(max - min));//管道随机出现的坐标}}}

 游戏界面与实现效果

 

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

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

相关文章

飞翔的小鸟游戏

GameApp类 package App;import main.GameFrame;public class GameApp {public static void main(String[] args) {//游戏的入口new GameFrame();} } main Barrier 类 package main;import util.Constant; import util.GameUtil;import java.awt.*; import java.awt.image.Buf…

gitea仓库镜像同步至gitlab

1、参考文档&#xff1a;仓库镜像 | Gitea Documentation 2、错误一&#xff1a;账号密码错误问题 解决方法&#xff1a; 出现以上错误为第三步用户名&#xff08;Oauth2应用名称&#xff09;或者密码&#xff08;Gitlab个人访问令牌&#xff09;错误。 1&#xff09;如下图1…

【UE4虛幻】UTexture2D纹理裁剪函数

参数说明&#xff1a; 源2D纹理图片&#xff1a;UTexture2D* SourceTexture 裁剪区域的左上角&#xff1a;const FVector2D TopLeft 裁剪区域的右下角&#xff1a;const FVector2D BottomRight 返回值是裁剪之后的纹理图片 UTexture2D* APointProjection::CropPicture(UTextur…

洗地机哪个牌子好用?洗地机选购攻略

传统的清洁方式都是扫把拖把的结合&#xff0c;既繁琐也劳累&#xff0c;每次清洁完后还得累的腰酸背痛的&#xff0c;像厨房这种地方甚至会不容易清洁干净&#xff0c;总感觉地板灰蒙蒙的。洗地机的诞生就很好的解决了这些问题&#xff0c;不用一遍遍的重复扫地拖地擦地&#…

1410. HTML 实体解析器 --力扣 --JAVA

题目 「HTML 实体解析器」 是一种特殊的解析器&#xff0c;它将 HTML 代码作为输入&#xff0c;并用字符本身替换掉所有这些特殊的字符实体。 HTML 里这些特殊字符和它们对应的字符实体包括&#xff1a; 双引号&#xff1a;字符实体为 &quot; &#xff0c;对应的字符是 &qu…

JOSEF约瑟 过电流继电器 JL15-300/11 触点形式一开一闭 板前接线

系列型号 JL15-1.5/11电流继电器JL15-2.5/11电流继电器 JL15-5/11电流继电器JL15-10/11电流继电器 JL15-15/11电流继电器JL15-20/11电流继电器 JL15-30/11电流继电器JL15-40/11电流继电器 JL15-60/11电流继电器JL15-80/11电流继电器 JL15-100/11电流继电器JL15-150/11电流继电…

linux的系统

10.4 I2C 系统的重要结构体 参考资料&#xff1a; ⚫ Linux 驱动程序:&#xff08;某版本的 Linux&#xff0c;比如 Linux-4.9.88&#xff09;/drivers/i2c ⚫ I2CTools: https://mirrors.edge.kernel.org/pub/software/utils/i2c-tools/ 284 / 577 10.4.1 重要结构体 使用一句…

母婴团队半年破亿秘诀揭秘,合规经营成就辉煌

这支母婴产品销售团队在短短半年内实现了过亿的销售额&#xff0c;这是一个令人瞩目的成就。他们既不依赖线下门店&#xff0c;也不是传统的电商平台&#xff0c;那么他们是如何做到这一点的呢&#xff1f; 这个团队从16年10月开始经营母婴产品&#xff0c;如今已经过去了6年时…

生成式AI:SEO的末日?

由于在搜索结果中引入生成式AI (GAI)&#xff0c;以 SEO 为主导的内容的未来成为最近的热门话题&#xff0c;这是有充分理由的。 对于出版商和网站所有者&#xff08;从现在开始我们将他们称为内容创建者&#xff09;的影响可能是毁灭性的。 如下图所示&#xff0c;谷歌新的搜…

成为AI产品经理——模型构建过程(上)

目录 一、背景 1.对内 2.对外 二、模型构建过程 1.模型设计 2.特征工程 ① 数据清洗 ② 特征提取 数值型数据 标签/描述类数据特征 非结构化数据&#xff08;处理文本特征&#xff09; 网络关系型数据 ③ 特征选择 ④ 训练集/测试集 一、背景 虽然产品经理不…

Linux应用开发基础知识——I2C应用编程(十二)

前言&#xff1a; I2C&#xff08;Inter-Integrated Circuit BUS&#xff09;是集成电路总线&#xff0c;是目前应用最广泛的总线之一&#xff0c;最初由PHILIPS&#xff08;现为NXP&#xff09;设计。它使用多主从架构&#xff0c;主要用于连接低速周边设备。I2C总线在硬件物理…

WorkPlus即时通讯,打通上下游产业链,构建企业生态圈

如今&#xff0c;随着信息技术的迅速发展&#xff0c;智慧水务、智慧医疗、智慧城市、智慧教育、智慧政务等领域正蓬勃发展。在这个智慧时代&#xff0c;企业需要一个具备开放性和扩展性的平台级产品&#xff0c;以满足多样化的业务需求。WorkPlus作为一款全新的移动底座产品&a…

String 真的不可变吗?

为什么 String 类不可变 final修饰符&#xff1a; String类被声明为final&#xff0c;这意味着它不能被继承。因此&#xff0c;无法创建String的子类来修改其行为。私有字符数组&#xff08;char[]&#xff09;&#xff1a; String类内部使用私有的字符数组来存储字符串的内容…

Excel文件比较不再繁琐,xlCompare助您快速找出差异

概要 在现代职场中&#xff0c;Excel 已成为工作中不可或缺的利器。 在日常操作中&#xff0c;我们会遇到需要对两个或多个 Excel 文件进行比较的情况&#xff0c;此时&#xff0c;一款高效的 Excel 文件比较工具就显得尤为重要。 本文将为您介绍一款功能强大、优势明显的 Exc…

创新建筑形式:气膜体育馆助力校园体育设施革新

体育场馆在校园中扮演着重要的角色&#xff0c;是学生们进行体育锻炼、比赛和各类体育活动的场所。传统的室内体育馆建设往往需要大量资金和漫长的建设周期&#xff0c;但随着气膜体育馆的崭露头角&#xff0c;校园体育设施的面貌正迎来一场革新。 快速搭建&#xff0c;灵活性极…

电机应用开发-直流有刷电机电流环控制实现

目录 直流有刷电机电流环控制实现 硬件设计 直流电机电流环控制-位置式PID实现 编程要点 配置ADC可读取电流值 配置基本定时器6产生定时中断读取当前电路中驱动电机的电流值并执行PID运算 配置定时器1输出PWM控制电机 ADC数据处理 编写位置式PID算法 直流电机电流环控…

3、领导跟你谈话,讲到你的团队里面的好友,公司会进行观察裁员,你会去传话么?

作为一个团队成员&#xff0c;我会认真听取领导的意见&#xff0c;并尊重公司的决定。然而&#xff0c;作为一个好友&#xff0c;我也会考虑他们的利益&#xff0c;我会与他们沟通&#xff0c;提醒他们注意自己的表现和工作&#xff0c;努力提高业绩和工作质量&#xff0c;以确…

5个免费在线工具推荐

NSDT 三维场景建模工具GLTF/GLB在线编辑器Three.js AI自动纹理化开发包YOLO 虚幻合成数据生成器3D模型在线转换 1、NSDT 三维场景建模 访问地址&#xff1a;NSDT 编辑器 2、GLTF/GLB在线编辑器 访问地址&#xff1a;GLTF 编辑器 3、Three.js AI自动纹理化开发包 图一为原始模…

Linux下安装两个版本python

1 python下载&#xff1a; 官网地址&#xff1a;Download Python | Python.org 第一&#xff1a;点击下载如下图&#xff1a; 第二&#xff1a;找到对应的python版本源码包&#xff1a; 点击右键复制下载地址&#xff0c;如下图 例如我的是&#xff1a;https://www.python.org/…

【鸿蒙应用ArkTS开发系列】- 云开发入门实战二 实现省市地区联动地址选择器组件(上)

目录 概述 云数据库开发 一、创建云数据库的对象类型。 二、预置数据&#xff08;为对象类型添加数据条目&#xff09;。 三、部署云数据库 云函数实现业务逻辑 一、创建云函数 二、云函数目录讲解 三、创建resources目录 四、获取云端凭据 五、导出之前创建的元数据…