Commit 5e5ba4bf authored by kingyu's avatar kingyu Committed by kingyuluk
Browse files

feat: 添加悬浮型水管

parent d7b64a56
...@@ -2,6 +2,15 @@ ...@@ -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. 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) ## 1.0.0 (2020-07-10)
......
...@@ -17,8 +17,14 @@ com.bird.util 自定义的工具 ...@@ -17,8 +17,14 @@ com.bird.util 自定义的工具
# Version History # Version History
1.0.0 - July 11, 2020 1.0.0 - July 10, 2020
* 具备完整的游戏功能 * 具备完整的游戏功能
1.1.0 - July 11, 2020
* 添加了悬浮型的水管
# Notes
文本编码格式为UTF-8,若注释出现乱码请修改编译器的文本编码格式
# Contact # Contact
* email: <kingyuluk@hotmail.com> * email: <kingyuluk@hotmail.com>
...@@ -44,7 +44,7 @@ public class Bird { ...@@ -44,7 +44,7 @@ public class Bird {
// 在构造器中对资源初始化 // 在构造器中对资源初始化
public Bird() { public Bird() {
timing = new GameTime(); // 计时器 timing = GameTime.getInstance(); // 计时器
// 读取小鸟图片资源 // 读取小鸟图片资源
birdImgs = new BufferedImage[STATE_COUNT][IMG_COUNT]; birdImgs = new BufferedImage[STATE_COUNT][IMG_COUNT];
......
...@@ -17,12 +17,12 @@ import com.bird.util.GameUtil; ...@@ -17,12 +17,12 @@ import com.bird.util.GameUtil;
public class GameElementLayer { public class GameElementLayer {
private List<Pipe> pipes; // 水管的容器 private List<Pipe> pipes; // 水管的容器
//构造器 // 构造器
public GameElementLayer() { public GameElementLayer() {
pipes = new ArrayList<>(); pipes = new ArrayList<>();
} }
//绘制方法 // 绘制方法
public void draw(Graphics g, Bird bird) { public void draw(Graphics g, Bird bird) {
// 遍历水管容器,如果可见则绘制,不可见则归还 // 遍历水管容器,如果可见则绘制,不可见则归还
for (int i = 0; i < pipes.size(); i++) { for (int i = 0; i < pipes.size(); i++) {
...@@ -46,7 +46,7 @@ public class GameElementLayer { ...@@ -46,7 +46,7 @@ public class GameElementLayer {
*/ */
public static final int VERTICAL_INTERVAL = Constant.FRAME_HEIGHT / 5; public static final int VERTICAL_INTERVAL = Constant.FRAME_HEIGHT / 5;
public static final int HORIZONTAL_INTERVAL = Constant.FRAME_HEIGHT >> 2; 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; public static final int MAX_HEIGHT = ((Constant.FRAME_HEIGHT) >> 3) * 5;
private void pipeBornLogic(Bird bird) { private void pipeBornLogic(Bird bird) {
...@@ -58,37 +58,152 @@ public class GameElementLayer { ...@@ -58,37 +58,152 @@ public class GameElementLayer {
// 若容器为空,则添加一对水管 // 若容器为空,则添加一对水管
int topHeight = GameUtil.getRandomNumber(MIN_HEIGHT, MAX_HEIGHT + 1); // 随机生成水管高度 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, top.setAttribute(Constant.FRAME_WIDTH, -Constant.TOP_PIPE_LENGTHENING,
topHeight + Constant.TOP_PIPE_LENGTHENING, Pipe.TYPE_TOP_NORMAL, true); 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, bottom.setAttribute(Constant.FRAME_WIDTH, topHeight + VERTICAL_INTERVAL,
Constant.FRAME_HEIGHT - topHeight - VERTICAL_INTERVAL, Pipe.TYPE_BOTTOM_NORMAL, true); Constant.FRAME_HEIGHT - topHeight - VERTICAL_INTERVAL, Pipe.TYPE_BOTTOM_NORMAL, true);
pipes.add(top); pipes.add(top);
pipes.add(bottom); pipes.add(bottom);
} else { } else {
// 判断最后一对水管是否完全进入游戏窗口 // 判断最后一对水管是否完全进入游戏窗口,若进入则添加水管
Pipe lastPipe = pipes.get(pipes.size() - 1); // 获得容器中最后一个水管 Pipe lastPipe = pipes.get(pipes.size() - 1); // 获得容器中最后一个水管
if (lastPipe.isInFrame()) { if (lastPipe.isInFrame()) { // 根据游戏分数难度递增
int topHeight = GameUtil.getRandomNumber(MIN_HEIGHT, MAX_HEIGHT + 1); // 随机生成水管高度 if (GameTime.getInstance().TimeToScore() < Constant.HOVER_MOVING_SCORE) {
int x = lastPipe.getX() + HORIZONTAL_INTERVAL; //新水管的x坐标 = 最后一对水管的x坐标 + 水管的间隔 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 * 判断元素和小鸟是否发生碰撞,若发生碰撞返回true,否则返回false
* *
...@@ -100,8 +215,8 @@ public class GameElementLayer { ...@@ -100,8 +215,8 @@ public class GameElementLayer {
if (bird.isDead()) { if (bird.isDead()) {
return false; return false;
} }
//遍历水管容器 // 遍历水管容器
for (int i = 0; i < pipes.size(); i++) { for (int i = 0; i < pipes.size(); i++) {
Pipe pipe = pipes.get(i); Pipe pipe = pipes.get(i);
// 判断碰撞矩形是否有交集 // 判断碰撞矩形是否有交集
......
...@@ -10,16 +10,14 @@ import com.bird.util.Constant; ...@@ -10,16 +10,14 @@ import com.bird.util.Constant;
import com.bird.util.MusicUtil; import com.bird.util.MusicUtil;
/** /**
* 游戏计时类 * 游戏计时类,单例类,方便调用
* *
* @author Kingyu * @author Kingyu
* *
*/ */
public class GameTime { public class GameTime {
private static final GameTime GAME_TIME = new GameTime();
public static final int HOVER_BARRIER_TIME = 10; // 出现悬浮管道的时间
public static final int MOVING_BARRIER_TIME = 20; // 出现移动管道的时间
private int timeState; // 计时器的状态 private int timeState; // 计时器的状态
public static final int STATE_READY = 0; // 计时就绪 public static final int STATE_READY = 0; // 计时就绪
public static final int STATE_START = 1; // 计时开始 public static final int STATE_START = 1; // 计时开始
...@@ -30,7 +28,7 @@ public class GameTime { ...@@ -30,7 +28,7 @@ public class GameTime {
private long score = 0; // 分数 private long score = 0; // 分数
private long bestScore; // 最高分数 private long bestScore; // 最高分数
public GameTime() { private GameTime() {
timeState = STATE_READY; timeState = STATE_READY;
bestScore = -1; bestScore = -1;
...@@ -40,6 +38,10 @@ public class GameTime { ...@@ -40,6 +38,10 @@ public class GameTime {
e.printStackTrace(); e.printStackTrace();
} }
} }
public static GameTime getInstance() {
return GAME_TIME;
}
// 装载最高纪录 // 装载最高纪录
private void loadBestTime() throws Exception { private void loadBestTime() throws Exception {
...@@ -117,8 +119,8 @@ public class GameTime { ...@@ -117,8 +119,8 @@ public class GameTime {
} }
} }
private static final int FIRST_SCORE_TIME = 6700; // 从游戏开始到通过第一根水管的所需时间 private static final int FIRST_SCORE_TIME = 6600; // 从游戏开始到通过第一根水管的所需时间
private static final int PER_SCORE_TIME = 2850; // 通过后续每一根水管的间隔的所需时间 private static final int PER_SCORE_TIME = 2880; // 通过后续每一根水管的间隔的所需时间
//将游戏时间转换为通过水管的数量 //将游戏时间转换为通过水管的数量
public long TimeToScore() { public long TimeToScore() {
...@@ -149,6 +151,7 @@ public class GameTime { ...@@ -149,6 +151,7 @@ public class GameTime {
timeState = STATE_READY; timeState = STATE_READY;
startTime = 0; startTime = 0;
endTime = 0; endTime = 0;
score = 0;
} }
} }
package com.bird.main;
import java.awt.Color;
import java.awt.Graphics;
import com.bird.util.Constant;
/**
* 移动水管类,继承Pipe类
*
* @author Kingyu
*
*/
public class MovingPipe extends Pipe {
private int dealtY; // 移动水管的坐标
public static final int MAX_DEALY = 50; // 最大移动距离
private int dir;
public static final int DIR_UP = 0;
public static final int DIR_DOWN = 1;
// 构造器
public MovingPipe() {
super();
}
/**
* 设置水管参数
*
* @param x
* @param y
* @param height
* @param type
* @param visible
*/
public void setAttribute(int x, int y, int height, int type, boolean visible) {
this.x = x;
this.y = y;
this.height = height;
this.type = type;
this.visible = visible;
setRectangle(this.x, this.y, this.height);
dealtY = 0;
dir = DIR_DOWN;
if (type == TYPE_TOP_HARD) {
dir = DIR_UP;
}
}
// 绘制方法
public void draw(Graphics g, Bird bird) {
switch (type) {
case TYPE_HOVER_HARD:
drawHoverHard(g);
break;
case TYPE_TOP_HARD:
drawTopHard(g);
break;
case TYPE_BOTTOM_HARD:
drawBottomHard(g);
break;
}
// 鸟死后水管停止移动
if (bird.isDead()) {
return;
}
pipeLogic();
// 绘制碰撞矩形
g.setColor(Color.black);
g.drawRect((int) pipeRect.getX(), (int) pipeRect.getY(), (int) pipeRect.getWidth(), (int) pipeRect.getHeight());
}
// 绘制移动的悬浮水管
private void drawHoverHard(Graphics g) {
// 拼接的个数
int count = (height - 2 * PIPE_HEAD_HEIGHT) / PIPE_HEIGHT + 1;
// 绘制水管的上顶部
g.drawImage(imgs[2], x - ((PIPE_HEAD_WIDTH - width) >> 1), y + dealtY, null);
// 绘制水管的主体
for (int i = 0; i < count; i++) {
g.drawImage(imgs[0], x, y + dealtY + i * PIPE_HEIGHT + PIPE_HEAD_HEIGHT, null);
}
// 绘制水管的下底部
int y = this.y + height - PIPE_HEAD_HEIGHT;
g.drawImage(imgs[1], x - ((PIPE_HEAD_WIDTH - width) >> 1), y + dealtY, null);
}
// 绘制从上往下的普通水管
private void drawTopHard(Graphics g) {
// 拼接的个数
int count = (height - PIPE_HEAD_HEIGHT) / PIPE_HEIGHT + 1; // 取整+1
// 绘制水管的主体
for (int i = 0; i < count; i++) {
g.drawImage(imgs[0], x, y + dealtY + i * PIPE_HEIGHT, null);
}
// 绘制水管的顶部
g.drawImage(imgs[1], x - ((PIPE_HEAD_WIDTH - width) >> 1),
height - Constant.TOP_PIPE_LENGTHENING - PIPE_HEAD_HEIGHT + dealtY, null);
}
// 绘制从下往上的普通水管
private void drawBottomHard(Graphics g) {
// 拼接的个数
int count = (height - PIPE_HEAD_HEIGHT) / PIPE_HEIGHT + 1;
// 绘制水管的主体
for (int i = 0; i < count; i++) {
g.drawImage(imgs[0], x, Constant.FRAME_HEIGHT - PIPE_HEIGHT - i * PIPE_HEIGHT + dealtY, null);
}
// 绘制水管的顶部
g.drawImage(imgs[2], x - ((PIPE_HEAD_WIDTH - width) >> 1), Constant.FRAME_HEIGHT - height + dealtY, null);
}
/**
* 可动水管的运动逻辑
*/
private void pipeLogic() {
x -= speed;
pipeRect.x -= speed;
if (x < -1 * PIPE_HEAD_WIDTH) {// 水管完全离开了窗口
visible = false;
}
//水管上下移动
if (dir == DIR_DOWN) {
dealtY++;
if (dealtY > MAX_DEALY) {
dir = DIR_UP;
}
} else {
dealtY--;
if (dealtY <= 0) {
dir = DIR_DOWN;
}
}
pipeRect.y = this.y + dealtY;
}
}
...@@ -14,7 +14,7 @@ import com.bird.util.GameUtil; ...@@ -14,7 +14,7 @@ import com.bird.util.GameUtil;
* *
*/ */
public class Pipe { public class Pipe {
private static BufferedImage[] imgs; // 水管的图片,static保证图片只加载一次 static BufferedImage[] imgs; // 水管的图片,static保证图片只加载一次
static {// 静态代码块,类加载的时候,初始化图片 static {// 静态代码块,类加载的时候,初始化图片
final int PIPE_IMAGE_COUNT = 3; final int PIPE_IMAGE_COUNT = 3;
imgs = new BufferedImage[PIPE_IMAGE_COUNT]; imgs = new BufferedImage[PIPE_IMAGE_COUNT];
...@@ -29,12 +29,12 @@ public class Pipe { ...@@ -29,12 +29,12 @@ public class Pipe {
public static final int PIPE_HEAD_WIDTH = imgs[1].getWidth(); public static final int PIPE_HEAD_WIDTH = imgs[1].getWidth();
public static final int PIPE_HEAD_HEIGHT = imgs[1].getHeight(); public static final int PIPE_HEAD_HEIGHT = imgs[1].getHeight();
private int x, y; // 水管的坐标,相对于元素层 int x, y; // 水管的坐标,相对于元素层
private int width, height; // 水管的宽,高 int width, height; // 水管的宽,高
private boolean visible; // 水管可见状态,true为可见,false表示可归还至对象池 boolean visible; // 水管可见状态,true为可见,false表示可归还至对象池
// 水管的类型 // 水管的类型
private int type; int type;
public static final int TYPE_TOP_NORMAL = 0; public static final int TYPE_TOP_NORMAL = 0;
public static final int TYPE_TOP_HARD = 1; public static final int TYPE_TOP_HARD = 1;
public static final int TYPE_BOTTOM_NORMAL = 2; public static final int TYPE_BOTTOM_NORMAL = 2;
...@@ -45,9 +45,9 @@ public class Pipe { ...@@ -45,9 +45,9 @@ public class Pipe {
// 水管的速度 // 水管的速度
public static final int MIN_SPEED = 1; public static final int MIN_SPEED = 1;
public static final int MAX_SPEED = 2; public static final int MAX_SPEED = 2;
private int speed; int speed;
private Rectangle pipeRect; // 水管的碰撞矩形 Rectangle pipeRect; // 水管的碰撞矩形
// 构造器 // 构造器
public Pipe() { public Pipe() {
...@@ -106,10 +106,13 @@ public class Pipe { ...@@ -106,10 +106,13 @@ public class Pipe {
case TYPE_HOVER_NORMAL: case TYPE_HOVER_NORMAL:
drawHoverNormal(g); drawHoverNormal(g);
break; break;
} }
// //绘制碰撞矩形 // //绘制碰撞矩形
// g.setColor(Color.black); // g.setColor(Color.black);
// g.drawRect((int) pipeRect.getX(), (int) pipeRect.getY(), (int) pipeRect.getWidth(), (int) pipeRect.getHeight()); // g.drawRect((int) pipeRect.getX(), (int) pipeRect.getY(), (int) pipeRect.getWidth(), (int) pipeRect.getHeight());
//鸟死后水管停止移动
if (bird.isDead()) { if (bird.isDead()) {
return; return;
} }
...@@ -156,9 +159,9 @@ public class Pipe { ...@@ -156,9 +159,9 @@ public class Pipe {
int y = this.y + height - PIPE_HEAD_HEIGHT; int y = this.y + height - PIPE_HEAD_HEIGHT;
g.drawImage(imgs[1], x - ((PIPE_HEAD_WIDTH - width) >> 1), y, null); g.drawImage(imgs[1], x - ((PIPE_HEAD_WIDTH - width) >> 1), y, null);
} }
/** /**
* 水管的运动逻辑 * 普通水管的运动逻辑
*/ */
private void pipeLogic() { private void pipeLogic() {
x -= speed; x -= speed;
...@@ -166,7 +169,6 @@ public class Pipe { ...@@ -166,7 +169,6 @@ public class Pipe {
if (x < -1 * PIPE_HEAD_WIDTH) {// 水管完全离开了窗口 if (x < -1 * PIPE_HEAD_WIDTH) {// 水管完全离开了窗口
visible = false; visible = false;
} }
} }
/** /**
......
...@@ -12,16 +12,21 @@ import com.bird.util.Constant; ...@@ -12,16 +12,21 @@ import com.bird.util.Constant;
* *
*/ */
public class PipePool { public class PipePool {
private static List<Pipe> pool = new ArrayList<>(); // 用于管理池中所有对象的容器 private static List<Pipe> pool = new ArrayList<Pipe>(); // 池中对象的容器
private static List<MovingPipe> movingPool = new ArrayList<MovingPipe>(); // 池中对象的容器
public static final int INIT_PIPE_COUNT = (Constant.FRAME_WIDTH public static final int INIT_PIPE_COUNT = (Constant.FRAME_WIDTH
/ (Pipe.PIPE_HEAD_WIDTH + GameElementLayer.HORIZONTAL_INTERVAL) + 2) * 2; // 根据窗口宽度算得对象池中对象的初始个数 / (Pipe.PIPE_HEAD_WIDTH + GameElementLayer.HORIZONTAL_INTERVAL) + 2) * 2; // 根据窗口宽度算得对象池中对象的初始个数
public static final int MAX_PIPE_COUNT = 50; // 对象池中对象的最大个数,自行定义 public static final int MAX_PIPE_COUNT = 30; // 对象池中对象的最大个数,自行定义
//初始化水管容器 // 初始化水管容器
static { static {
for (int i = 0; i < INIT_PIPE_COUNT; i++) { for (int i = 0; i < INIT_PIPE_COUNT; i++) {
pool.add(new Pipe()); pool.add(new Pipe());
} }
for (int i = 0; i < INIT_PIPE_COUNT; i++) {
movingPool.add(new MovingPipe());
}
} }
/** /**
...@@ -29,12 +34,21 @@ public class PipePool { ...@@ -29,12 +34,21 @@ public class PipePool {
* *
* @return * @return
*/ */
public static Pipe get() { public static Pipe get(String className) {
int size = pool.size(); if ("Pipe".equals(className)) {
if (size > 0) { int size = pool.size();
return pool.remove(size - 1); // 移除并返回最后一个 if (size > 0) {
return pool.remove(size - 1); // 移除并返回最后一个
} else {
return new Pipe(); // 空对象池,返回一个新对象
}
} else { } else {
return new Pipe(); // 空对象池,返回一个新对象 int size = movingPool.size();
if (size > 0) {
return movingPool.remove(size - 1); // 移除并返回最后一个
} else {
return new MovingPipe(); // 空对象池,返回一个新对象
}
} }
} }
...@@ -44,8 +58,15 @@ public class PipePool { ...@@ -44,8 +58,15 @@ public class PipePool {
* @param pipe * @param pipe
*/ */
public static void giveBack(Pipe pipe) { public static void giveBack(Pipe pipe) {
if (pool.size() < MAX_PIPE_COUNT) { //判断类的类型
pool.add(pipe); if(pipe.getClass() == Pipe.class) {
} if (pool.size() < MAX_PIPE_COUNT) {
pool.add(pipe);
}
}else {
if (movingPool.size() < MAX_PIPE_COUNT) {
movingPool.add((MovingPipe)pipe);
}
}
} }
} }
...@@ -23,6 +23,8 @@ public class Constant { ...@@ -23,6 +23,8 @@ public class Constant {
// 图像资源路径 // 图像资源路径
public static final String BG_IMG_PATH = "sources/img/background.png"; // 背景图片 public static final String BG_IMG_PATH = "sources/img/background.png"; // 背景图片
public static final int HOVER_MOVING_SCORE = 4; //出现移动管道的分数
// 小鸟图片 // 小鸟图片
public static final String[][] BIRDS_IMG_PATH = { public static final String[][] BIRDS_IMG_PATH = {
......
package com.bird.util; package com.bird.util;
import java.awt.Font; import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import sun.font.FontDesignMetrics;
/** /**
* 工具类,游戏中用到的工具都在此类 * 工具类,游戏中用到的工具都在此类
* *
...@@ -71,12 +70,17 @@ public class GameUtil { ...@@ -71,12 +70,17 @@ public class GameUtil {
* 获得指定字符串在指定字体的宽高 * 获得指定字符串在指定字体的宽高
*/ */
public static int getStringWidth(Font font, String str) { public static int getStringWidth(Font font, String str) {
FontMetrics fm = FontDesignMetrics.getMetrics(font); AffineTransform affinetransform = new AffineTransform();
return fm.stringWidth(str); FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
int textHeight = (int)(font.getStringBounds(str, frc).getWidth());
return textHeight;
} }
public static int getStringHeight(Font font, String str) { public static int getStringHeight(Font font, String str) {
FontMetrics fm = FontDesignMetrics.getMetrics(font); AffineTransform affinetransform = new AffineTransform();
return fm.getHeight(); FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
int textHeight = (int)(font.getStringBounds(str, frc).getHeight());
return textHeight;
} }
} }
...@@ -18,6 +18,7 @@ public class MusicUtil { ...@@ -18,6 +18,7 @@ public class MusicUtil {
private static AudioClip score; private static AudioClip score;
// 装载音乐资源 // 装载音乐资源
@SuppressWarnings("deprecation")
public static void load() { public static void load() {
try { try {
fly = Applet.newAudioClip(new File("sources/wav/fly.wav").toURL()); fly = Applet.newAudioClip(new File("sources/wav/fly.wav").toURL());
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment