Skip to content

Commit

Permalink
feat: 添加悬浮型水管
Browse files Browse the repository at this point in the history
  • Loading branch information
kingyuluk committed Jul 11, 2020
1 parent d158fa5 commit 074595b
Show file tree
Hide file tree
Showing 11 changed files with 364 additions and 59 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.


## 1.1.0 (2020-07-11)


### Features

* 添加悬浮型水管 ([cc80ec9](https://github.com/kingyuluk/FlappyBird/commit/cc80ec9845194dc5326a8d70799b847b6821f751))
* 具备原版的游戏功能 ([264a7c3](https://github.com/kingyuluk/FlappyBird/commit/264a7c320c894851aa3e6c8c30ffcddf3ce1f78a))

## 1.0.0 (2020-07-10)


Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ com.bird.util 自定义的工具


# Version History
1.0.0 - July 11, 2020
1.0.0 - July 10, 2020
* 具备完整的游戏功能

1.1.0 - July 11, 2020
* 添加了悬浮型的水管

# Notes

文本编码格式为UTF-8,若注释出现乱码请修改编译器的文本编码格式
# Contact
* email: <[email protected]>
2 changes: 1 addition & 1 deletion src/com/bird/main/Bird.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class Bird {

// 在构造器中对资源初始化
public Bird() {
timing = new GameTime(); // 计时器
timing = GameTime.getInstance(); // 计时器

// 读取小鸟图片资源
birdImgs = new BufferedImage[STATE_COUNT][IMG_COUNT];
Expand Down
157 changes: 136 additions & 21 deletions src/com/bird/main/GameElementLayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
public class GameElementLayer {
private List<Pipe> pipes; // 水管的容器

//构造器
// 构造器
public GameElementLayer() {
pipes = new ArrayList<>();
}

//绘制方法
// 绘制方法
public void draw(Graphics g, Bird bird) {
// 遍历水管容器,如果可见则绘制,不可见则归还
for (int i = 0; i < pipes.size(); i++) {
Expand All @@ -46,7 +46,7 @@ public void draw(Graphics g, Bird bird) {
*/
public static final int VERTICAL_INTERVAL = Constant.FRAME_HEIGHT / 5;
public static final int HORIZONTAL_INTERVAL = Constant.FRAME_HEIGHT >> 2;
public static final int MIN_HEIGHT = (Constant.FRAME_HEIGHT) >> 3;
public static final int MIN_HEIGHT = Constant.FRAME_HEIGHT >> 3;
public static final int MAX_HEIGHT = ((Constant.FRAME_HEIGHT) >> 3) * 5;

private void pipeBornLogic(Bird bird) {
Expand All @@ -58,37 +58,152 @@ private void pipeBornLogic(Bird bird) {
// 若容器为空,则添加一对水管
int topHeight = GameUtil.getRandomNumber(MIN_HEIGHT, MAX_HEIGHT + 1); // 随机生成水管高度

Pipe top = PipePool.get();
Pipe top = PipePool.get("Pipe");
top.setAttribute(Constant.FRAME_WIDTH, -Constant.TOP_PIPE_LENGTHENING,
topHeight + Constant.TOP_PIPE_LENGTHENING, Pipe.TYPE_TOP_NORMAL, true);

Pipe bottom = PipePool.get();
Pipe bottom = PipePool.get("Pipe");
bottom.setAttribute(Constant.FRAME_WIDTH, topHeight + VERTICAL_INTERVAL,
Constant.FRAME_HEIGHT - topHeight - VERTICAL_INTERVAL, Pipe.TYPE_BOTTOM_NORMAL, true);

pipes.add(top);
pipes.add(bottom);
} else {
// 判断最后一对水管是否完全进入游戏窗口
// 判断最后一对水管是否完全进入游戏窗口,若进入则添加水管
Pipe lastPipe = pipes.get(pipes.size() - 1); // 获得容器中最后一个水管
if (lastPipe.isInFrame()) {
int topHeight = GameUtil.getRandomNumber(MIN_HEIGHT, MAX_HEIGHT + 1); // 随机生成水管高度
int x = lastPipe.getX() + HORIZONTAL_INTERVAL; //新水管的x坐标 = 最后一对水管的x坐标 + 水管的间隔
if (lastPipe.isInFrame()) { // 根据游戏分数难度递增
if (GameTime.getInstance().TimeToScore() < Constant.HOVER_MOVING_SCORE) {
try {
if (GameUtil.isInProbability(2, 5)) { // 40%的概率生成悬浮的普通水管
addHoverPipe(lastPipe);
} else {
addNormalPipe(lastPipe);
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
if (GameUtil.isInProbability(1, 4)) { // 1/4的概率生成普通水管
if(GameUtil.isInProbability(1, 2)) // 生成普通水管和悬浮水管的概率
addNormalPipe(lastPipe);
else
addHoverPipe(lastPipe);
} else {
if(GameUtil.isInProbability(1, 3)) // 生成移动水管和移动悬浮水管的概率
addMovingHoverPipe(lastPipe);
else
addMovingNormalPipe(lastPipe);
}
} catch (Exception e) {
e.printStackTrace();
}
}

Pipe top = PipePool.get();
top.setAttribute(x, -Constant.TOP_PIPE_LENGTHENING, topHeight + Constant.TOP_PIPE_LENGTHENING,
Pipe.TYPE_TOP_NORMAL, true);

Pipe bottom = PipePool.get();
bottom.setAttribute(x, topHeight + VERTICAL_INTERVAL,
Constant.FRAME_HEIGHT - topHeight - VERTICAL_INTERVAL, Pipe.TYPE_BOTTOM_NORMAL, true);

pipes.add(top);
pipes.add(bottom);
}
}
}

/**
* 添加普通水管
*
* @param lastPipe
*/
private void addNormalPipe(Pipe lastPipe) {
int topHeight = GameUtil.getRandomNumber(MIN_HEIGHT, MAX_HEIGHT + 1); // 随机生成水管高度
int x = lastPipe.getX() + HORIZONTAL_INTERVAL; // 新水管的x坐标 = 最后一对水管的x坐标 + 水管的间隔

// 概率生成移动的水管

Pipe top = PipePool.get("Pipe");
top.setAttribute(x, -Constant.TOP_PIPE_LENGTHENING, topHeight + Constant.TOP_PIPE_LENGTHENING,
Pipe.TYPE_TOP_NORMAL, true);

Pipe bottom = PipePool.get("Pipe");
bottom.setAttribute(x, topHeight + VERTICAL_INTERVAL, Constant.FRAME_HEIGHT - topHeight - VERTICAL_INTERVAL,
Pipe.TYPE_BOTTOM_NORMAL, true);

pipes.add(top);
pipes.add(bottom);
}

/**
* 添加悬浮水管
*
* @param lastPipe
*/
private void addHoverPipe(Pipe lastPipe) {

// 随机生成水管高度,屏幕高度的[1/4,1/6]
int topHoverHeight = GameUtil.getRandomNumber(Constant.FRAME_HEIGHT / 6, Constant.FRAME_HEIGHT / 4);
int x = lastPipe.getX() + HORIZONTAL_INTERVAL; // 新水管的x坐标 = 最后一对水管的x坐标 + 水管的间隔
int y = GameUtil.getRandomNumber(Constant.FRAME_HEIGHT / 12, Constant.FRAME_HEIGHT / 6); // 随机水管的y坐标,窗口的[1/6,1/12]

int type = Pipe.TYPE_HOVER_NORMAL;

// 生成上部的悬浮水管
Pipe topHover = PipePool.get("Pipe");
topHover.setAttribute(x, y, topHoverHeight, type, true);

// 生成下部的悬浮水管
int bottomHoverHeight = Constant.FRAME_HEIGHT - 2 * y - topHoverHeight - VERTICAL_INTERVAL;
Pipe bottomHover = PipePool.get("Pipe");
bottomHover.setAttribute(x, y + topHoverHeight + VERTICAL_INTERVAL, bottomHoverHeight, type, true);

pipes.add(topHover);
pipes.add(bottomHover);

}

/**
* 添加移动的悬浮水管
*
* @param lastPipe
*/
private void addMovingHoverPipe(Pipe lastPipe) {

// 随机生成水管高度,屏幕高度的[1/4,1/6]
int topHoverHeight = GameUtil.getRandomNumber(Constant.FRAME_HEIGHT / 6, Constant.FRAME_HEIGHT / 4);
int x = lastPipe.getX() + HORIZONTAL_INTERVAL; // 新水管的x坐标 = 最后一对水管的x坐标 + 水管的间隔
int y = GameUtil.getRandomNumber(Constant.FRAME_HEIGHT / 12, Constant.FRAME_HEIGHT / 6); // 随机水管的y坐标,窗口的[1/6,1/12]

int type = Pipe.TYPE_HOVER_HARD;

// 生成上部的悬浮水管
Pipe topHover = PipePool.get("MovingPipe");
topHover.setAttribute(x, y, topHoverHeight, type, true);

// 生成下部的悬浮水管
int bottomHoverHeight = Constant.FRAME_HEIGHT - 2 * y - topHoverHeight - VERTICAL_INTERVAL;
Pipe bottomHover = PipePool.get("MovingPipe");
bottomHover.setAttribute(x, y + topHoverHeight + VERTICAL_INTERVAL, bottomHoverHeight, type, true);

pipes.add(topHover);
pipes.add(bottomHover);

}

/**
* 添加移动的普通水管
*
* @param lastPipe
*/
private void addMovingNormalPipe(Pipe lastPipe) {
int topHeight = GameUtil.getRandomNumber(MIN_HEIGHT, MAX_HEIGHT + 1); // 随机生成水管高度
int x = lastPipe.getX() + HORIZONTAL_INTERVAL; // 新水管的x坐标 = 最后一对水管的x坐标 + 水管的间隔

Pipe top = PipePool.get("MovingPipe");
top.setAttribute(x, -Constant.TOP_PIPE_LENGTHENING, topHeight + Constant.TOP_PIPE_LENGTHENING,
Pipe.TYPE_TOP_HARD, true);

Pipe bottom = PipePool.get("MovingPipe");
bottom.setAttribute(x, topHeight + VERTICAL_INTERVAL, Constant.FRAME_HEIGHT - topHeight - VERTICAL_INTERVAL,
Pipe.TYPE_BOTTOM_HARD, true);

pipes.add(top);
pipes.add(bottom);
}

/**
* 判断元素和小鸟是否发生碰撞,若发生碰撞返回true,否则返回false
*
Expand All @@ -100,8 +215,8 @@ public boolean isCollideBird(Bird bird) {
if (bird.isDead()) {
return false;
}
//遍历水管容器

// 遍历水管容器
for (int i = 0; i < pipes.size(); i++) {
Pipe pipe = pipes.get(i);
// 判断碰撞矩形是否有交集
Expand Down
19 changes: 11 additions & 8 deletions src/com/bird/main/GameTime.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@
import com.bird.util.MusicUtil;

/**
* 游戏计时类
* 游戏计时类,单例类,方便调用
*
* @author Kingyu
*
*/
public class GameTime {

public static final int HOVER_BARRIER_TIME = 10; // 出现悬浮管道的时间
public static final int MOVING_BARRIER_TIME = 20; // 出现移动管道的时间

private static final GameTime GAME_TIME = new GameTime();

private int timeState; // 计时器的状态
public static final int STATE_READY = 0; // 计时就绪
public static final int STATE_START = 1; // 计时开始
Expand All @@ -30,7 +28,7 @@ public class GameTime {
private long score = 0; // 分数
private long bestScore; // 最高分数

public GameTime() {
private GameTime() {
timeState = STATE_READY;
bestScore = -1;

Expand All @@ -40,6 +38,10 @@ public GameTime() {
e.printStackTrace();
}
}

public static GameTime getInstance() {
return GAME_TIME;
}

// 装载最高纪录
private void loadBestTime() throws Exception {
Expand Down Expand Up @@ -117,8 +119,8 @@ public void endTiming() {
}
}

private static final int FIRST_SCORE_TIME = 6700; // 从游戏开始到通过第一根水管的所需时间
private static final int PER_SCORE_TIME = 2850; // 通过后续每一根水管的间隔的所需时间
private static final int FIRST_SCORE_TIME = 6600; // 从游戏开始到通过第一根水管的所需时间
private static final int PER_SCORE_TIME = 2880; // 通过后续每一根水管的间隔的所需时间

//将游戏时间转换为通过水管的数量
public long TimeToScore() {
Expand Down Expand Up @@ -149,6 +151,7 @@ public void reset() {
timeState = STATE_READY;
startTime = 0;
endTime = 0;
score = 0;
}

}
Loading

0 comments on commit 074595b

Please sign in to comment.