使用java语言,在IDEA环境下,设计实现一个简单有趣的FlappyBird小游戏。在当今社会,人们的工作学习压力日益增大,生活节奏逐渐加快,多数人没有足够的时间去休闲娱乐,放松自己。FlappyBird小游戏是一款小型休闲类游戏,
它可以锻炼人们的反应能力,有益于开发智力。
本游戏要求,实现以下基本需求:
功能需求:
(1) 控制游戏:按住空格键可以操纵小鸟以一定的速度向上飞行,松开空格键则使小鸟自由下落;控制小鸟躲避不同类型的移动的障碍物,撞到障碍物或者触碰到游戏页面的最上端或者最下端都会导致小鸟死亡,游戏结束;控制小鸟飞行过程中,添加计时和计分功能,并且保存最佳的一次游戏记录。
(2) 重置游戏:当小鸟死亡时,弹出提示页面,按住空格键将重新开始游戏。
非功能需求:
(1) 游戏页面:游戏窗口化&固化保障游戏图形界面的友好性。
(2)游戏进入界面:实现提示页面,按住空格键开始游戏。
根据需求分析的结果,本游戏至少要分为以下三个模块:游戏启动模块、游戏主体模块、自定义工具模块,分别用于启动游戏、实现游戏主体功能、辅助实现游戏主体。
本游戏的整体功能模块图如2-1所示。
图1-1 FlappyBird小游戏功能结构图
该游戏程序由本人与另外两名同学三人共同完成;其中,本人完成的部分有:设计游戏窗口及展示面、设计游戏背景、绘制小鸟、绘制背景云层、设计三种类型的障碍物、实现障碍物随机出现和移动、游戏计时和计分、保存最佳记录、重置游戏。
在此处主要展示main模块的实现,是整个游戏程序的重要组成部分。具体细分为Barrier类、BarrierPool类、Bird类、Cloud类、GameBackGround类、GameBarrierLayer类、GameFrame类、GameFontGound类、GameReady类、GameTime类、MovingBarrier类,下面将主要展示main模块下几大主类实现的具体功能。
(1)Barrier类
该类实现对障碍物的设计,代码如下:
package com.bird.main;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import com.bird.util.Constant;
import com.bird.util.GameUtil;
public class Barrier {
// 障碍物需要用到的三张图
static BufferedImage[] imgs;
static {
final int COUNT = 3;
// 类加载的时候,将三张图片初始化
imgs = new BufferedImage[COUNT];
for (int i = 0; i < COUNT; i++) {
imgs[i]=GameUtil.loadBufferedImage(Constant.BARRIER_IMG_PATH[i]);
}
}
// 障碍物移动的速度
public static final int MIN_SPEED = 1;
public static int MAX_SPEED = 5;
int speed;
// 获得所有的障碍物元素的宽高
public static final int BARRIER_WIDTH = imgs[0].getWidth();
public static final int BARRIER_HEIGHT = imgs[0].getHeight();
public static final int BARRIER_HEAD_WIDTH = imgs[1].getWidth();
public static final int BARRIER_HEAD_HEIGHT = imgs[1].getHeight();
// 是相对于障碍物的x,y的坐标,不是相对于窗口
int x, y;
int width, height;
int type;
public static final int TYPE_TOP_NORMAL = 0;
public static final int TYPE_TOP_HARD = 1;
public static final int TYPE_BOTTOM_NORMAL = 2;
public static final int TYPE_BOTTOM_HARD = 3;
public static final int TYPE_HOVER_NORMAL = 4;
public static final int TYPE_HOVER_HARD = 5;
// 添加障碍物是否可见的状态
boolean visible;
Rectangle rect;
public Barrier() {
this.width = BARRIER_WIDTH;
this.speed = MIN_SPEED * 2;
rect = new Rectangle();
rect.width = this.width;
}
// 根据不同的类型绘制不同的障碍物
public void draw(Graphics g, Bird bird) {
switch (type) {
case TYPE_TOP_NORMAL:
drawTopNormal(g);
break;
case TYPE_BOTTOM_NORMAL:
drawBottomNormal(g);
break;
case TYPE_HOVER_NORMAL:
drawHoverNormal(g);
break;
}
// 鸟死亡之后,障碍物不再移动
if (bird.isDied())
return;
logic();
}
/**
* 绘制中间漂浮的障碍物
*
* @param g
*/
private void drawHoverNormal(Graphics g) {
// 先绘制上面的头
g.drawImage(imgs[1], x - (BARRIER_HEAD_WIDTH - BARRIER_WIDTH >> 1), y , null);
// 绘制中间细的部分
int count = (height - BARRIER_HEAD_HEIGHT * 2) / BARRIER_HEIGHT + 1;
for (int i = 0; i < count; i++) {
g.drawImage(imgs[0], x, y + i * BARRIER_HEIGHT + BARRIER_HEAD_HEIGHT, null);
}
// 绘制底部的头
int y = this.y + height - BARRIER_HEAD_HEIGHT;
g.drawImage(imgs[2], x - (BARRIER_HEAD_WIDTH - BARRIER_WIDTH >> 1), y, null);
}
/**
* 1.绘制从上往下的障碍物
*
* @param g
*/
private void drawTopNormal(Graphics g) {
// 确定上半部分障碍物拼接的个数
int count = (height - BARRIER_HEAD_HEIGHT) / BARRIER_HEIGHT;
for (int i = 0; i < count + 1; i++) {
g.drawImage(imgs[0], x, y + i * BARRIER_HEIGHT, null);
}
// 绘制障碍物的头
int y = this.y + height - BARRIER_HEAD_HEIGHT;
g.drawImage(imgs[2], x - (BARRIER_HEAD_WIDTH - BARRIER_WIDTH >> 1), y, null);
}
/**
* 2.绘制从下往上的障碍物
*
* @param g
*/
private void drawBottomNormal(Graphics g) {
// 确定上半部分障碍物拼接的个数
int count = (height - BARRIER_HEAD_HEIGHT) / BARRIER_HEIGHT + 1;
for (int i = 0; i < count; i++) {
g.drawImage(imgs[0], x, y + i * BARRIER_HEIGHT + BARRIER_HEAD_HEIGHT, null);
}
// 绘制障碍物的头
g.drawImage(imgs[1], x - (BARRIER_HEAD_WIDTH - BARRIER_WIDTH >> 1), y, null);
}
/**
* 障碍物的逻辑部分
*/
private void logic() {
x -= speed;// 坐标向左走
rect.x -= speed;
// 障碍物完全移出屏幕
if (x < -BARRIER_WIDTH) {
visible = false;
}
}
/**
* 判断当前障碍物是否完全出现在窗口中
*
* @return
*/
public boolean isInFrame() {
return x + BARRIER_WIDTH < Constant.FRAME_WIDTH;
}
public int getx() {
return x;
}
public void setx(int x) {
this.x = x;
}
public void sety(int y) {
this.y = y;
}
public void setType(int type) {
this.type = type;
}
public void setHeight(int height) {
this.height = height;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVisible() {
return visible;
}
public Rectangle getRect() {
return rect;
}
/**
* 设置障碍物的属性
*
* @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(x, y, height);
}
/**
* 设置障碍物矩形的属性
*
* @param x
* @param y
* @param height
*/
public void setRectangle(int x, int y, int height) {
rect.x = x;
rect.y = y;
rect.height = height;
}
}
(2)BarrierPool类
代码如下:
package com.bird.main;
import java.util.ArrayList;
import java.util.List;
/**
* 为了避免反复的创建和销毁对象 使用对象池来提前创建好一些对象 使用的时候从池中获得,使用完毕后归还
*
* @author mac
*
*/
public class BarrierPool {
// 用于管理池中的所有对象的容器
private static List<Barrier> pool = new ArrayList<Barrier>();
private static List<MovingBarrier> pool1 = new ArrayList<MovingBarrier>();
// 对象池中初始的对象的个数
public static final int INIT_BARRIER_COUNT = 16;
// 最大个数
public static final int MAX_BARRIER_COUNT = 20;
static {
// 初始化池中的对象
for (int i = 0; i < INIT_BARRIER_COUNT; i++) {
pool.add(new Barrier());
}
for (int i = 0; i < INIT_BARRIER_COUNT; i++) {
pool1.add(new MovingBarrier());
}
}
/**
* 从池中获取一个对象
*
* @return
*/
public static Barrier get(String className) {
if ("Barrier".equals(className)) {
int size = pool.size();
if (size > 0) {
// 移除并返回最后一个
return pool.remove(size - 1);
} else {
// 池被拿空,只能返回一个新的对象
return new Barrier();
}
} else {
int size = pool1.size();
if (size > 0) {
// 移除并返回最后一个
return pool1.remove(size - 1);
} else {
// 池被拿空,只能返回一个新的对象
return new MovingBarrier();
}
}
}
/**
* 将对象归还到池中
*
* @param barrier
*/
public static void giveBack(Barrier barrier) {
if (barrier.getClass() == Barrier.class) {
if (pool.size() < MAX_BARRIER_COUNT) {
pool.add(barrier);
} else {
}
} else {
if (pool1.size() < MAX_BARRIER_COUNT) {
pool1.add((MovingBarrier) barrier);
} else {
}
}
}
}
由于篇幅有限,以上只展示部分代码,需要源码下方链接自取
链接:https://pan.baidu.com/s/1ZTtRoVdB3SD3cu95c3pE0w
提取码:roco