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等代碼中涉及到的知識幫助大家順利完成本次的小項目!!!
