1.前言
首先,我先说一下这个项目,这个项目题材的来自牛客网的开源项目
我在这里做一个我自己在开发此项目的心得体会和经验交流,并且带领大家了解从0去入手一个项目的完整思路
2.分析
①素材准备
在开发此项目之前,我们需要去先下载一些关于飞翔的小鸟素材图片
小鸟的飞翔图片
地面背景图片
柱子图片
以及开始结束图片
那么这里我为大家提供百度网盘链接,大家需要可自行下载
链接:https://pan.baidu.com/s/12ww0HQ6KluVP-fcC40iXXQ
提取码:zjd8
复制这段内容后打开百度网盘手机App,操作更方便哦
②代码构思
本项目主要针对JAVASE刚学完想巩固练习,却没有项目着手的同学,用的都是一些基础性的知识
运用到的知识点:
1.面向对象:封装继承多态
2.数组
3.常用类Math
4.swing组件:图形界面工具
5.鼠标监听
6.IO流
7.多线程
逻辑步骤分析:
1.先实现窗口的制作,并且将背景图放入窗口面板
2.设计地面类,实现游戏背景地面移动
3.设计柱子类,实现游戏背景柱子移动
4.设计小鸟类,在类中添加小鸟相关方法
初始化小鸟相关参数, 判断小鸟是否碰撞柱子与地面
5.把小鸟放在面板中
6.鼠标监听控制小鸟飞行的轨迹
7.添加计分和游戏结束游戏开始的画面
代码分类:
由上述的分析,我们可以大致分析计划创建4个类
1.小鸟类:设置小鸟参数,添加小鸟判断方法
2.柱子类:设置柱子参数,添加柱子移动方法
3.地面类:设置地面参数,添加地面移动方法
4.测试类:添加开始结束、鼠标监听等方法
3.代码实现及展示
①小鸟类:
1 package FlyBirdGame; 2 3 import javax.imageio.ImageIO; 4 import java.awt.image.BufferedImage; 5 import java.io.File; 6 7 class Bird { 8 //图片 9 BufferedImage image; 10 //位置 11 int x,y; 12 //宽,高 13 int width,height; 14 //大小 15 int size; 16 17 //重力加速度 18 double g; 19 //位移的间隔时间 20 double t; 21 //最初上抛速度 22 double v0; 23 //当前上抛速度 24 double speed; 25 //经过时间t后的位移 26 double s; 27 //小鸟的倾角 28 double alpha; 29 30 //一组图片,记录小鸟的动画帧 31 BufferedImage[] images; 32 //动画帧数组的下标 33 int index; 34 35 //初始化小鸟 36 public Bird() throws Exception{ 37 //初始化基本参数 38 image = ImageIO.read(new File("0.png")); 39 width = image.getWidth(); 40 height = image.getHeight(); 41 x=132; 42 y=280; 43 size =40; 44 45 //初始化位移参数 46 g=4; 47 v0=20; 48 t=0.25; 49 speed = v0; 50 s = 0; 51 alpha = 0; 52 53 //初始化动画帧参数 54 images = new BufferedImage[8]; 55 for(int i = 0;i<8;i++){ 56 images[i] = ImageIO.read(new File(i+".png")); 57 } 58 index = 0; 59 } 60 61 //飞行动作(变化一帧) 62 public void fly(){ 63 index++; 64 image = images[(index/12)%8]; 65 } 66 67 //移动一步 68 public void step(){ 69 double v0 =speed; 70 //计算上抛运动位移 71 s=v0*t + g*t*t/2; 72 //计算小鸟的坐标位置 73 y=y-(int)s; 74 //计算下次移动速度 75 double v = v0 -g*t; 76 speed = v; 77 //计算倾角 78 alpha = Math.atan(s/8); 79 } 80 81 //向上飞翔 82 public void flappy(){ 83 //重叠速度 84 speed =v0; 85 } 86 87 //检查小鸟是否碰撞到地面 88 public boolean hit(Ground ground ){ 89 boolean hit = y+size/2 > ground.y; 90 if(hit){ 91 y = ground.y - size/2; 92 alpha = -3.14159265358979323 / 2; 93 } 94 return hit; 95 } 96 97 //检查小鸟是否碰到柱子 98 public boolean hit(Column column){ 99 //先检测是否在柱子范围内 100 if(x>column.x - column.width /2 - size /2 101 && x<column.x + column.width/2 + size/2){ 102 //检查是否在柱子的缝隙种 103 if(y>column.y - column.gap/2 + size /2 104 && y<column.y + column.gap /2 -size/2){ 105 return false; 106 } 107 return true; 108 } 109 return false; 110 } 111 }
②地面类:
1 package FlyBirdGame; 2 3 import javax.imageio.ImageIO; 4 import java.awt.image.BufferedImage; 5 import java.io.File; 6 7 public class Ground { 8 //图片 9 BufferedImage image; 10 //位置 11 int x,y; 12 //宽高 13 int width,height; 14 15 //初始化地面 16 public Ground() throws Exception { 17 image = ImageIO.read(new File("ground.png")); 18 width = image.getWidth(); 19 height = image.getHeight(); 20 x=0; 21 y=500; 22 } 23 24 //向左移动一步 25 public void step(){ 26 x--; 27 if(x==-109){ 28 x = 0; 29 } 30 } 31 }
③柱子类:
1 package FlyBirdGame; 2 3 import javax.imageio.ImageIO; 4 import java.awt.image.BufferedImage; 5 import java.io.File; 6 import java.util.Random; 7 8 public class Column { 9 //图片 10 BufferedImage image; 11 //位置 12 int x,y; 13 //宽高 14 int width,height; 15 //柱子间缝隙 16 int gap; 17 //柱子间距离 18 int distance; 19 //随机数工具 20 Random random = new Random(); 21 22 /** 23 * 初始化第n个柱子 24 */ 25 public Column(int n) throws Exception{ 26 image = ImageIO.read(new File("column.png")); 27 width = image.getWidth(); 28 height = image.getHeight(); 29 gap = 144; 30 distance = 245; 31 x= 550 + (n-1) * distance; 32 y = random.nextInt(218)+132; 33 } 34 35 //向左移动一步 36 public void step(){ 37 x--; 38 if(x==-width/2){ 39 x = distance * 2 - width/2; 40 y = random.nextInt(218) + 132; 41 } 42 } 43 }
④测试类:
1 package FlyBirdGame; 2 3 import javax.imageio.ImageIO; 4 import javax.swing.*; 5 import java.awt.*; 6 import java.awt.image.BufferedImage; 7 import java.awt.event.MouseAdapter; 8 import java.awt.event.MouseEvent; 9 import java.awt.event.MouseListener; 10 import java.io.File; 11 12 public class BirdGame extends JPanel { 13 //背景图片 14 BufferedImage background; 15 //开始图片 16 BufferedImage startImage; 17 //结束图片 18 BufferedImage gameOverImage; 19 20 //地面 21 Ground ground; 22 //柱子 23 Column column1,column2; 24 //小鸟 25 Bird bird; 26 27 //游戏分数 28 int score; 29 30 //游戏状态 31 int state; 32 33 //状态常量 34 public static final int START = 0;//开始 35 public static final int RUNNING = 1;//运行 36 public static final int GAME_OVER = 2;//结束 37 38 /** 39 * 初始化游戏 40 */ 41 public BirdGame() throws Exception{ 42 //初始化 43 background = ImageIO.read(new File("bg.png")); 44 startImage = ImageIO.read(new File("start.png")); 45 gameOverImage = ImageIO.read(new File("gameover.png")); 46 47 //初始化地面,柱子,小鸟 48 ground = new Ground(); 49 column1 = new Column(1); 50 column2 = new Column(2); 51 bird = new Bird(); 52 53 //初始化分数 54 score = 0; 55 //初始化状态 56 state = START; 57 } 58 /** 59 * 绘制界面 60 */ 61 public void paint(Graphics g){ 62 //绘制背景 63 g.drawImage(background,0,0,null); 64 65 //绘制地面 66 g.drawImage(ground.image,ground.x,ground.y,null); 67 //绘制柱子 68 g.drawImage(column1.image,column1.x - column1.width/2,column1.y 69 -column1.height/2,null); 70 g.drawImage(column2.image,column2.x - column2.width/2,column2.y 71 -column2.height/2,null); 72 73 //绘制小鸟 74 Graphics2D g2 = (Graphics2D) g; 75 g2.rotate(-bird.alpha,bird.x,bird.y); 76 g2.drawImage(bird.image,bird.x-bird.width/2,bird.y-bird.height/2,null); 77 g2.rotate(bird.alpha,bird.x,bird.y); 78 79 //绘制分数 80 Font f = new Font(Font.SANS_SERIF,Font.BOLD,40); 81 g.setFont(f); 82 g.drawString(""+score,40,60); 83 g.setColor(Color.WHITE); 84 g.drawString(""+score,40-3,60-3); 85 86 //绘制开始和结束界面 87 switch (state) { 88 case START: 89 g.drawImage(startImage, 0, 0, null); 90 break; 91 case GAME_OVER: 92 g.drawImage(gameOverImage, 0, 0, null); 93 break; 94 } 95 } 96 // 开始游戏 97 public void action() throws Exception { 98 // 鼠标监听器 99 MouseListener l = new MouseAdapter() { 100 // 鼠标按下事件 101 public void mousePressed(MouseEvent e) { 102 try { 103 switch (state) { 104 case START: 105 // 在开始状态,按下鼠标则转为运行状态。 106 state = RUNNING; 107 break; 108 case RUNNING: 109 // 在运行状态,按下鼠标则小鸟向上飞行。 110 bird.flappy(); 111 break; 112 case GAME_OVER: 113 // 在结束状态,按下鼠标则重置数据,再次转为开始态。 114 column1 = new Column(1); 115 column2 = new Column(2); 116 bird = new Bird(); 117 score = 0; 118 state = START; 119 break; 120 } 121 } catch (Exception ex) { 122 ex.printStackTrace(); 123 } 124 } 125 }; 126 // 将监听器添加到当前的面板上 127 addMouseListener(l); 128 // 不断的移动与重绘 129 while (true) { 130 switch (state) { 131 case START: 132 // 小鸟做出飞行动作 133 bird.fly(); 134 // 地面向左移动一步 135 ground.step(); 136 break; 137 case RUNNING: 138 // 地面向左移动一步 139 ground.step(); 140 // 柱子向左移动一步 141 column1.step(); 142 column2.step(); 143 // 小鸟做出飞行动作 144 bird.fly(); 145 // 小鸟上下移动一步 146 bird.step(); 147 // 计算分数 148 if (bird.x == column1.x || bird.x == column2.x) { 149 score++; 150 } 151 // 检测是否发生碰撞 152 if (bird.hit(ground) || bird.hit(column1) || bird.hit(column2)) { 153 state = GAME_OVER; 154 } 155 break; 156 } 157 // 重新绘制界面 158 repaint(); 159 // 休眠 1000/60 毫秒 160 Thread.sleep(1000 / 60); 161 } 162 } 163 /** 164 * 启动方法 165 */ 166 public static void main(String[] args) throws Exception { 167 JFrame frame = new JFrame(); 168 BirdGame game = new BirdGame(); 169 frame.add(game); 170 frame.setSize(440, 670); 171 frame.setLocationRelativeTo(null); 172 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 173 frame.setVisible(true); 174 game.action(); 175 } 176 177 }
4.心得分享
对于一些刚入门java的小伙伴来说,可能里面用到的一些方法,不是很熟悉这里建议大家可以通过API查询可以学习了解一下swing、鼠标监听以及ImageIO等代码中涉及到的知识帮助大家顺利完成本次的小项目!!!