ps:雖然是看着教程寫出來的,但是這是第一次實現一個項目還是挺開心的,還是自己以前玩過的遊戲
飛翔的小鳥相信大家也都玩過,就是不停點擊屏幕既要保證小鳥不落地,也要保證小鳥要穿過柱子
先來看一下效果圖吧:
接下來就是重點了:我們需要把遊戲中用到的場景先要實現出來
1.定義小鳥類
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
/**
* 小鳥
*/
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(getClass().getResource("/resources/0.png"));
width=image.getWidth();
height=image.getHeight();
x=132;
y=280;
size=40;
//初始化位移參數
g=4;
v0=20;
t=0.25;
speed=v0;
s=0;
alpha=0;
//初始化動畫幀參數
images=new BufferedImage[8];
for(int i=0;i<8;i++) {
images[i]=ImageIO.read(getClass().getResource("/resources/"+i+".png"));
}
index=0;
}
//飛行動作
public void fly() {
index++;
image=images[(index/12)%8];
}
//移動一步
public void step() {
double v0=speed;
//計算上拋運動位移
s=v0*t+g*t*t/2;
//計算鳥的座標位置
y=y-(int)s;
//計算下次移動速度
double v=v0-g*t;
speed=v;
//計算傾角(反正切函數)
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.定義地面類
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
/**
*地面
*/
public class Ground {
//圖片
BufferedImage image;
//位置
int x,y;
//寬高
int width,height;
//初始化地面
public Ground() throws Exception{
image=ImageIO.read(getClass().getResource("/resources/ground.png"));
width=image.getWidth();
height=image.getHeight();
x=0;
y=500;
}
//向左移動一步
public void step() {
x--;
if(x==-109) {
x=0;
}
}
}
3.定義柱子類
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
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(getClass().getResource("/resources/column.png"));
width=image.getWidth();
height=image.getHeight();
gap=144;
distance=245;
x=550+(n-1)*distance;
y=random.nextInt(218)+123;
}
//向左移動一步
public void step() {
x--;
if(x==-width/2) {
y=distance*2-width/2;
y=random.nextInt(218)+132;
x=550;
}
}
}
4.進行遊戲初始化和開始遊戲
package game;
/**
* 遊戲界面
*/
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
public class BirdGame extends JPanel {
// 背景圖片
BufferedImage background;
// 開始圖片
BufferedImage startImage;
// 結束圖片
BufferedImage gameOverImage;
// 地面
Ground ground;
// 柱子
Column column1, column2;
// 小鳥
Bird bird;
// 遊戲分數
int score;
// 遊戲狀態
int state;
// 狀態常量
public static final int START = 0;// 開始
public static final int RUNNING = 1;// 運行
public static final int GAME_OVER = 2;// 結束
/**
* 初始化遊戲
*/
public BirdGame() throws Exception {
// 初始化背景圖片
background = ImageIO.read(getClass().getResource("/resources/bg.png"));
// 初始化開始、結束圖片
startImage = ImageIO.read(getClass().getResource("/resources/start.png"));
gameOverImage = ImageIO.read(getClass().getResource("/resources/gameover.png"));
// 初始化地面、柱子、小鳥
ground = new Ground();
column1 = new Column(1);
column2 = new Column(2);
bird = new Bird();
// 初始化分數
score = 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);
g.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);
// 繪製開始與結束界面
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;
state = START;
break;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
// 將***添加到當前的面板上
addMouseListener(l);
// 不斷的移動與重繪
while (true) {
switch (state) {
case START:
// 小鳥做出飛行動作
bird.fly();
// 地面向左移動一步
ground.step();
break;
case RUNNING:
// 地面向左移動一步
ground.step();
// 柱子向左移動一步
column1.step();
column2.step();
// 小鳥做出飛行動作
bird.fly();
// 小鳥上下移動一步
bird.step();
// 計算分數
if (bird.x == column1.x || bird.x == column2.x) {
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 {
JFrame frame = new JFrame();
BirdGame game = new BirdGame();
frame.add(game);
frame.setSize(440, 670);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
game.action();
}
}
遊戲中的圖片資源:
百度雲盤鏈接
提取碼:bhab