Java实战小游戏《flapper Bird》完整版,含源码
Flapper Bird
目录
一、前言
二、素材准备
1.背景图片
2.背景音乐
三、建立工程
四、代码实现
1.小鸟类
2. 地面类
3. 柱子类
4. 音乐类
5. 游戏类
五、效果展示
六、注意事项
七、心得体会
一、前言
断断续续java学了一个月,想找个项目练练手,于是打算跟着大佬们一起写个《Flapper Bird》小游戏。以下只是我对自己研究该项目的一个小结,记录一下也希望对读者有一定的帮助。
原文链接:
JavaSE实战项目:飞翔的小鸟(完整版)_zjdzka的博客-CSDN博客_javase实战项目
Java小游戏中加背景音乐--有图有真相_一如既往的博客-CSDN博客_java给游戏添加背景音乐
与原文的区别在于:简单设置了游戏等级,添加了背景音乐(由于时间有限,仅任意找了一首歌转换格式导入),以及本人完成该项目的效果展示。
二、素材准备
1.背景图片
在开发此项目之前,需要先下载一些关于flapper bird的素材图片
①开始结束图片
②小鸟的飞翔图片
③地面背景图片
④柱子图片
网盘链接:百度网盘 请输入提取码
提取码:zjd8
2.背景音乐
给游戏添加一个背景音乐,因为时间有限,我只是任意找了一首歌转换格式后导入。此项目采用的是.wav格式音频(注意:不可直接更改音频文件后缀名!!!)
①背景音乐
音频格式转换网站:在线转换为音频-免费的在线音频转换器
三、建立工程
1. 创建一个项目工程: Flapper_Bird
2. 工程下新建一个包:ui
3. 包下新建五个类: Bird、Ground、Column、Music、Game
4. 在该工程下导入: ①图片素材②.wav格式背景音乐
四、代码实现
1.小鸟类
package ui;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;public class Bird {//图片BufferedImage image;//位置int x,y;//宽,高int width,height;//大小int size;//重力加速度double g;//位移的间隔时间double t;//最初上抛速度double v0;//当前上抛速度double speed;//经过时间t后的位移double s;//小鸟的倾角double alpha;//一组图片,记录小鸟的动画帧BufferedImage[] images;//动画帧数组的下标int index;//初始化小鸟public Bird() throws Exception{//初始化基本参数image = ImageIO.read(new File("0.png"));width = image.getWidth();height = image.getHeight();x=132;y=280;size =40;//初始化位移参数g=8;//4v0=35;//20t=0.2;//0.25speed = v0;s = 0;alpha = 0;//初始化动画帧参数images = new BufferedImage[8];for(int i = 0;i<8;i++){images[i] = ImageIO.read(new File(i+".png"));}index = 0;}//飞行动作(变化一帧)public void fly(){index++;image = images[(index/12)%8];//image = images[(index/12)%8];}//移动一步public void step(){double v0 =speed;//计算上抛运动位移s=v0*t/1.5 + g*t*t/2;// s=v0*t + g*t*t/2;//计算小鸟的坐标位置y=y-(int)s;//计算下次移动速度double v = v0 -g*t;speed = v;//计算倾角alpha = Math.atan(s/15);//alpha = Math.atan(s/8);}//向上飞翔public void flappy(){//重叠速度speed =v0;}//检查小鸟是否碰撞到地面public boolean hit(Ground ground ){boolean hit = y+size/2 > ground.y;if(hit){y = ground.y - size/2;alpha = -3.14159265358979323 / 2;}return hit;}//检查小鸟是否碰到柱子public boolean hit(Column column){//先检测是否在柱子范围内if(x>column.x - column.width /2 - size /2&& x<column.x + column.width/2 + size/2){//检查是否在柱子的缝隙种if(y>column.y - column.gap/2 + size /2&& y<column.y + column.gap /2 -size/2){return false;}return true;}return false;}
}
2. 地面类
package ui;import java.awt.image.BufferedImage;import javax.imageio.ImageIO;
import java.io.File;public class Ground {//图片BufferedImage image;//位置int x,y;//宽高int width,height;//初始化地面public Ground() throws Exception {image = ImageIO.read(new File("ground.png"));width = image.getWidth();height = image.getHeight();x=0;y=500;}//向左移动一步public void step(){x--;if(x==-100){x = 0;}}
}
3. 柱子类
package ui;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Random;public class Column {//图片BufferedImage image;//位置int x,y;//宽高int width,height;//柱子间缝隙int gap;//柱子间距离int distance;//随机数工具Random random = new Random();/*** 初始化第n个柱子*/public Column(int n) throws Exception{image = ImageIO.read(new File("column.png"));width = image.getWidth();height = image.getHeight();gap = 144;distance = 245;x= 550 + (n-1) * distance;y = random.nextInt(218)+132;}/** 向左移动一步*/public void step(){x--;if(x==-width/2){x = distance * 2 - width/2;y = random.nextInt(218) + 132;}}
}
4. 音乐类
package ui;import java.io.File;
import java.io.IOException;import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;public class Music extends Thread {private String fileName;private final int EXTERNAL_BUFFER_SIZE = 524288;public Music(String wavFile) {this.fileName = wavFile;}@SuppressWarnings("unused")public void run() {File soundFile = new File(fileName); // 播放音乐的文件名if (!soundFile.exists()) {System.err.println("Wave file not found:" + fileName);return;}while (true) { // 设置循环播放AudioInputStream audioInputStream = null; // 创建音频输入流对象try {audioInputStream = AudioSystem.getAudioInputStream(soundFile); // 创建音频对象} catch (UnsupportedAudioFileException e1) {e1.printStackTrace();return;} catch (IOException e1) {e1.printStackTrace();return;}AudioFormat format = audioInputStream.getFormat(); // 音频格式SourceDataLine auline = null; // 源数据线DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);try {auline = (SourceDataLine) AudioSystem.getLine(info);auline.open(format);} catch (LineUnavailableException e) {e.printStackTrace();return;} catch (Exception e) {e.printStackTrace();return;}if (auline.isControlSupported(FloatControl.Type.PAN)) {FloatControl pan = (FloatControl) auline.getControl(FloatControl.Type.PAN);}auline.start();int nBytesRead = 0;byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];try {while (nBytesRead != -1) {nBytesRead = audioInputStream.read(abData, 0, abData.length);if (nBytesRead >= 0)auline.write(abData, 0, nBytesRead);}} catch (IOException e) {e.printStackTrace();return;} finally {auline.drain();
// auline.close();}}}
}
5. 游戏类
package ui;import javax.imageio.ImageIO;
import javax.swing.*;import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;public class Game extends JPanel {private static final long serialVersionUID = 1L;//背景图片BufferedImage background;//开始图片BufferedImage startImage;//结束图片BufferedImage gameOverImage;//地面Ground ground;//柱子Column column1,column2;//小鸟Bird bird;//游戏分数int score;//游戏等级int degree;//游戏状态int state;//状态常量public static final int START = 0;//开始public static final int RUNNING = 1;//运行public static final int GAME_OVER = 2;//结束/*** 初始化游戏*/public Game() throws Exception{//初始化background = ImageIO.read(new File("bg.png"));startImage = ImageIO.read(new File("start.png"));gameOverImage = ImageIO.read(new File("gameover.png"));//初始化地面,柱子,小鸟ground = new Ground();column1 = new Column(1);column2 = new Column(2);bird = new Bird();//初始化分数score = 0;//初始化等级degree = 0;//初始化状态state = START;}/*** 绘制界面*/public void paint(Graphics g){//绘制背景g.drawImage(background,0,0,null);//绘制地面g.drawImage(ground.image,ground.x,ground.y,null);//绘制柱子g.drawImage(column1.image,column1.x - column1.width/2,column1.y-column1.height/2,null);g.drawImage(column2.image,column2.x - column2.width/2,column2.y-column2.height/2,null);//绘制小鸟Graphics2D g2 = (Graphics2D) g;g2.rotate(-bird.alpha,bird.x,bird.y);g2.drawImage(bird.image,bird.x - bird.width/2,bird.y-bird.height/2,null);g2.rotate(bird.alpha,bird.x,bird.y);//绘制分数Font f = new Font(Font.SANS_SERIF,Font.BOLD,40);g.setFont(f);g.drawString(""+score,40,60);g.setColor(Color.WHITE);g.drawString(""+score,40-3,60-3);//绘制等级Font d = new Font(Font.SANS_SERIF,Font.BOLD,40);g.setFont(d);for(int i=0;i<degree;i++){g.drawString("*",250+i*20,60);g.setColor(Color.BLUE);g.drawString("*",250+i*20-1,60-1);}//绘制开始和结束界面switch (state) {case START:g.drawImage(startImage, 0, 0, null);break;case GAME_OVER:g.drawImage(gameOverImage, 0, 0, null);break;}}// 开始游戏public void action() throws Exception {// 鼠标监听器MouseListener l = new MouseAdapter() {// 鼠标按下事件public void mousePressed(MouseEvent e) {try {switch (state) {case START:// 在开始状态,按下鼠标则转为运行状态。state = RUNNING;break;case RUNNING:// 在运行状态,按下鼠标则小鸟向上飞行。bird.flappy();break;case GAME_OVER:// 在结束状态,按下鼠标则重置数据,再次转为开始态。column1 = new Column(1);column2 = new Column(2);bird = new Bird();score = 0;degree = 0;state = START;break;}} catch (Exception ex) {ex.printStackTrace();}}};// 将监听器添加到当前的面板上addMouseListener(l);// 不断的移动与重绘while (true) {double grade = 1.0;switch (state) {case START:// 小鸟做出飞行动作bird.fly();// 地面向左移动一步ground.step();break;case RUNNING:if(score > 2){grade = (double)(score *1.0) / 2;degree = (int)grade;}while(grade > 0){// 地面向左移动一步ground.step();// 柱子向左移动一步column1.step();column2.step();grade--;} // 小鸟做出飞行动作bird.fly();// 小鸟上下移动一步bird.step();// 计算分数if (bird.x == (column1.x + column1.width/2) || bird.x == (column2.x + column2.width/2)) {score++;}// 检测是否发生碰撞if (bird.hit(ground) || bird.hit(column1) || bird.hit(column2)) {state = GAME_OVER;}break;}// 重新绘制界面repaint();// 休眠 1000/60 毫秒Thread.sleep(1000 / 60);}}/*** 启动方法*/public static void main(String[] args) throws Exception {//背景音乐启动Music audioPlayWave = new Music("intuition.wav");// 开音乐 音樂名audioPlayWave.start();@SuppressWarnings("unused")int musicOpenLab = 1;JFrame frame = new JFrame();Game game = new Game();frame.add(game);frame.setSize(440, 670);frame.setLocationRelativeTo(null);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);game.action();}}
五、效果展示
1. 开始运行(背景音乐随之播放)
2. 开始游戏 3. 游戏结束
六、注意事项
1. 代码中添加的图片与音频必须与导入的路径名一致
2. 报错:Wave file not found:intuition.wav
未导入.wav音频
3. 报错:javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file at javax.sound.sampled.AudioSystem.getAudioInputStream (AudioSystem.java:1189) at ui.Music.run(Music.java:33)
导入音频格式有误,不可直接更改音频文件后缀名得到.wav格式音频!
七、心得体会
java小白首次体验了一下小游戏的开发,受益匪浅。在添加图片和音乐上也费了些时间,开始是完全不知道图片和音乐应该加在哪里,接着是音乐格式一直有误,总之实属不易。新手上路,欢迎各位读者留言指导!
Java实战小游戏《flapper Bird》完整版,含源码相关推荐
- 【Java实现小游戏】飞翔的小鸟(源码)
游戏玩法:通过鼠标点击使小鸟上下移动穿过柱子并完成得分,小鸟碰到柱子或掉落到地面上都会结束游戏. (游戏内图片) 下面是实现这个游戏的代码: Brid类: package bird;import or ...
- C++小游戏笔记——射击小行星(附源码)
C++小游戏笔记--射击小行星(附源码) 游戏展示图 一.飞船 1.飞船的绘制 2.飞船的角度 二.小行星 1.小行星的绘制 2."凹凸不平"效果的形成 3.小行星的分裂 三.子弹 ...
- 微信小游戏《飞机打方块》源码分享
微信小游戏<飞机打方块>源码分享 游戏使用CocosCreator v2.4.2开发 源码:https://gitee.com/propertygame/cocos-creator3.x- ...
- FC小游戏合集网页版HTML源码
FC小游戏合集网页版HTML源码,上传到服务器即可访问,包含游戏文件在里面,操作键网页上有列出. 源码下载:FC小游戏合集网页版HTML源码-小程序文档类资源-CSDN下载
- cocos creator 2.4.5消除小游戏新玩法消星星源码H5+安卓+IOS三端源码
cocos creator 2.4.5消除小游戏新玩法消星星源码H5+安卓+IOS三端源码,开发脚本为typeScript方便扩展和阅读,支持cocos creator2.X版本,完整的源码可直接运营 ...
- QT界面免费版开源图片转文字工具程序完整版附源码
QT界面免费版开源图片转文字工具程序完整版附源码 需求源码的朋友请留言 操作步骤如下:
- 【新手上路】Java必备小游戏——Flappy Bird(飞翔的小鸟)
<飞翔的小鸟>是一款曾经比较火热的小游戏,本文可以带你你从零开始,一步一步的开发出这款小游戏.如果你只是刚入门java的新手,不用担心,只要你简单掌握了该游戏所需要的javase基础知识, ...
- C语言小游戏之扫雷完整版
C语言小游戏之扫雷 一.游戏介绍 二.游戏步骤及实现的功能 1.初始化雷盘 2.打印雷盘 3.随机布置雷 4.玩家排雷 5.防止玩家第一次被炸死 6.统计所选位置周围八个位置中雷的个数 7.递归拓展已 ...
- Java开发的船体程序 超级玛丽小游戏 411 功能非常齐全 完整源码
今天为大家继续分享泡泡堂小游戏的开发与制作 410,目前系统已经完成了初步功能,后续会进一步完善.整个系统界面漂亮,有完整得源码,希望大家可以喜欢.喜欢的帮忙点赞和关注.一起编程.一起进步!! 开发环 ...
最新文章
- 【代码保留】表删除/重命名(含中文与空格)
- 使用数字示波器DS6104测量交流信号的幅值和相位
- linux 新开窗口到最前,怎么设置一个窗口总是在电脑桌面的最前
- Android webservice的用法详细讲解
- P3157-[CQOI2011]动态逆序对【CDQ分治,树状数组】
- hessian学习笔记
- linux基础应用和常用技巧
- Zernike函数拟合曲面--MATLAB实现
- python-类的装饰器
- (55)Verilog HDL双沿采样设计
- xenserver 突破VID 2T限制
- XenServer 6.5实战:Creating a Storage Repository (CIFS)
- 基于QT的超市信息管理系统
- openbmc开发29:开关机管理
- Ubuntu下deb文件安装方法图文详解
- css preserve-3d 使用
- arm嵌入式led灯闪烁实验报告_嵌入式ARM键盘控制LED灯实验报告
- 项目管理知识体系指南 (四)
- android bootload漏洞,一加6手机的Bootloader漏洞可让攻击者控制设备
- 蓝桥杯试题 基础练习 数列特征python
热门文章
- qt客户端显示服务器发送的图片,qt客户端显示服务器发送的图片
- 豪斯医生改名换姓上演《我的“钱”半生》?
- 《深入理解Java虚拟机》知识点目录
- 2011年网页设计发展趋势
- 1824. Minimum Sideway Jumps 贪心和DP方法
- Ubuntu 安装截图软件
- 之于图片主色调提取算法
- 老有所依,得上点技术
- 深度学习主机环境配置: Ubuntu16.04+Nvidia GTX 1080i+CUDA8.0+CUDDN6
- LightOJ 1079 Just another Robbery