一、创建文件、包、类、插入图片文件
二、app包
1、Gameapp类(运行游戏)
package app;
import main.GameFrame;
public class Gameapp {
public static void main(String[] args) {//游戏的入口
new GameFrame();
}
}
三、main包
1、Barrier(障碍物类)
package main;
import util.Constant;
import util.GameUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 障碍物类
*/
public class Barrier {
//矩形参数
private Rectangle rect;
private boolean mob = true;
//障碍物移动速度
private int speed = 3;
//障碍物需要的三个图片
private static BufferedImage[] img;
//障碍物的状态
private boolean visible;
static {
final int COUNT = 3;
//类加载的时候将三个图片初始化
img = new BufferedImage[COUNT];
for (int i = 0; i < COUNT; i++) {
img[i] = GameUtil.loadBufferedImage(Constant.BARRIER_IMG_PATH[i]);
}
}
//位置
private int x, y;
//宽度和高度
private int width, height;
//障碍物的类型
private int type;
public static final int TYPE_TOP_NORMAL = 0;
public static final int TYPE_BOTTOM_NORMAL = 2;
public static final int TYPE_HOVER_NORMAL = 4;
public static final int TYPE_MOBILE = 6;
//获得障碍物的宽度和高度
public static final int BARRIRE_WIDTH = img[0].getWidth();
public static final int BARRIRE_HEIGHT = img[0].getHeight();
public static final int BARRIRE_HEAD_WIDTH = img[1].getWidth();
public static final int BARRIRE_HEAD_HEIGHT = img[1].getHeight();
public Barrier() {
rect = new Rectangle();
}
public Barrier(int x, int y, int height, int type) {
this.x = x;
this.y = y;
this.height = height;
this.type = type;
this.width = BARRIRE_WIDTH;
}
//根据不同的类型绘制障碍物
public void draw(Graphics g) {
switch (type) {
case TYPE_TOP_NORMAL:
drawTopMormal(g);
break;
case TYPE_BOTTOM_NORMAL:
drawNomalTop(g);
break;
case TYPE_HOVER_NORMAL:
drawHoverNormal(g);
break;
case TYPE_MOBILE:
drawMobile(g);
break;
}
}
//绘制从上向下的障碍物
private void drawTopMormal(Graphics g) {
//求出所需要的障碍物的块数
int count = (height - BARRIRE_HEAD_HEIGHT) / BARRIRE_HEIGHT + 1;
//for循坏绘制障碍物
for (int i = 0; i < count; i++) {
g.drawImage(img[0], x, y + i * BARRIRE_HEIGHT, null);
}
//绘制头
int y = height - BARRIRE_HEAD_HEIGHT;
g.drawImage(img[2], x - (BARRIRE_HEAD_WIDTH - BARRIRE_WIDTH) / 2, y, null);
x -= speed;
if (x < 50) {
visible = false;
}
rect(g);
}
//绘制从下向上的障碍物
private void drawNomalTop(Graphics g) {
//求出所需要的障碍物的块数
int count = height / BARRIRE_HEIGHT + 1;
//for循环绘制障碍物
for (int i = 0; i < count; i++) {
g.drawImage(img[0], x, Constant.FRAM_HEIGNT - i * BARRIRE_HEIGHT, null);
}
//绘制头
int y = Constant.FRAM_HEIGNT - height;
g.drawImage(img[1], x - (BARRIRE_HEAD_WIDTH - BARRIRE_WIDTH) / 2, y, null);
x -= speed;
if (x < -50) {
visible = false;
}
rect(g);
}
//绘制中间的障碍物
private void drawHoverNormal(Graphics g) {
//求出所需要的障碍物的块数
int count = (height-BARRIRE_HEAD_HEIGHT)/BARRIRE_HEIGHT;
//绘制上头
g.drawImage(img[1],x,y,null);
//for循环绘制障碍物
for (int i = 0; i < count; i++) {
g.drawImage(img[0], x, y+BARRIRE_HEAD_HEIGHT+i*BARRIRE_HEIGHT, null);
}
rect(g);
//绘制下头
int y11 = y+height-BARRIRE_HEAD_HEIGHT;
g.drawImage(img[2],x,y11,null);
x -= speed;
if (x < -50) {
visible = false;
}
}
//绘制移动的障碍物
private void drawMobile(Graphics g) {
//求出所需要的障碍物的块数
int count = (height-BARRIRE_HEAD_HEIGHT)/BARRIRE_HEIGHT;
//绘制上头
g.drawImage(img[1],x,y,null);
//for循环绘制障碍物
for (int i = 0; i < count; i++) {
g.drawImage(img[0], x, y+BARRIRE_HEAD_HEIGHT+i*BARRIRE_HEIGHT, null);
}
rect(g);
//绘制下头
int y11 = y+height-BARRIRE_HEAD_HEIGHT;
g.drawImage(img[2],x,y11,null);
x -= speed;
if (x < -50) {
visible = false;
}
if (mob) {
y+=5;
if (y >= 250) {
mob=false;
}
}else if (!mob){
y-=5;
if (y <= 100) {
mob=true;
}
}
}
/**
* 绘制障碍物碰撞矩形
*
* @return
*/
public void rect(Graphics g) {
int x1 = this.x;
int y1 = this.y;
int w1 = img[0].getWidth();
// g.setColor(Color.blue);
// g.drawRect(x1, y1, w1, height);
setRecyangle(x1, y1, w1, height);
}
/**
* 障碍物的碰撞矩形参数
*
* @return
*/
public void setRecyangle(int x, int y, int width, int height) {
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
}
//判断什么时候绘制下一组障碍物
public boolean isInFrame() {
return 600 - x > 150;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public Rectangle getRect() {
return rect;
}
}
2、Barrierpool(管理障碍物数量)
package main;
import java.util.ArrayList;
import java.util.List;
/**
* 为了避免反复的创建和销毁对象,使用对象池来提前创建好一些对象。
* 使用的时候从池中获得,使用完毕后,归还
*/
public class Barrierpool {
//用于管理池中所有对象的容器
private static List<Barrier> pool = new ArrayList<>();
//池中初始的对象个数
public static final int initCount = 16;
//对象池中最大个数
public static final int maxCOunt = 20;
static {
//初始化池中的对象
for (int i = 0; i < initCount; i++) {
pool.add(new Barrier());
}
}
/**
* 从池中获取一个对象
*/
public static Barrier getPool(){
int size = pool.size();
//如果池中有对象才可以拿
if (size > 0) {
//移除并返回对象
System.out.println("拿走一个");
return pool.remove(size-1);
}else {
//池中没有对象了 只能new
System.out.println("新的对象");
return new Barrier();
}
}
/**
* 将对象归还容器中
*/
public static void setPool(Barrier barrier){
if (pool.size() < maxCOunt) {
pool.add(barrier);
System.out.println("容器归还了");
}
}
}
3、Bird(小鸟类)
package main;
import static util.Constant.*;
import util.GameUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
/**
* 小鸟类
*/
public class Bird {
//小鸟矩形对象
private Rectangle rect;
//小鸟加速度
private int acceleration;
//小鸟的生命
public boolean life = true;
//存放小鸟图片
private BufferedImage[] images;
public static final int BIRD_IMG_COUNT = 3;
//鸟的状态
private int state;
public static final int STATE_NORMAR = 0;//平着飞
public static final int STATE_UP = 1;//向上飞
public static final int STATE_DOWN = 2;//向下飞
//小鸟的位置
private int x=200,y=200;
//小鸟移动方向 上下
private boolean up=false,down=false;
//小鸟移动速度
private int speed=4;
//构造方法中对资源初始化
public Bird() {
images = new BufferedImage[BIRD_IMG_COUNT];
for (int i = 0; i < BIRD_IMG_COUNT; i++) {
images[i] = GameUtil.loadBufferedImage(BIRD_IMG[i]);
}
int w = images[0].getWidth();
int h = images[0].getHeight();
rect = new Rectangle(w,h);
}
//绘制小鸟
public void draw(Graphics g) {
flyLogic();
g.drawImage(images [state], x, y, null);
//绘制小鸟的矩形
g.drawRect(x,y,(int)rect.getWidth(), rect.height);
rect.x=this.x;
rect.y=this.y;
}
//控制小鸟移动方向
public void flyLogic(){
if (up){
acceleration--;
y+=acceleration;
if (acceleration < -10) {
acceleration=-10;
}
if (y<20){
y=20;
acceleration=0;
}
}
if (!up){
acceleration++;
y+=acceleration;
if (acceleration > 10) {
acceleration=10;
}
if (y>475){
y=475;
acceleration=0;
}
}
}
public void fly(int fly){
switch (fly){
case 1:
state=1;
up=true;
break;
case 5:
state=2;
up=false;
break;
}
}
public Rectangle getRect() {
return rect;
}
/**
* 重新绘制小鸟的位置
*/
public void restartDraw(){
life=true;
x=200;
y=200;
}
}
4、Cloud(云彩类)
package main;
import java.awt.*;
import java.awt.image.BufferedImage;
/**
* 云彩类
*/
public class Cloud {
//云彩图片
private BufferedImage img;
//云彩速度
private int speed;
//云彩的位置
private int x,y;
public Cloud(){}
public Cloud(BufferedImage img, int speed, int x, int y) {
this.img = img;
this.speed = speed;
this.x = x;
this.y = y;
}
public void draw(Graphics g){
x-=speed;
g.drawImage(img,x,y,null);
}
/**
* 用于判断云彩是否飞出屏幕以外
*/
public boolean isOutFrame(){
if (x < -100) {
return true;
}
return false;
}
}
5、GameBackGround(游戏背景类)
package main;
import static util.Constant.*;
import util.Constant;
import util.GameUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
/**
* 游戏背景类
*/
public class GameBackGround {
//背景需要的资源图片
private BufferedImage bkimg;
//构造器初始化资源
public GameBackGround(){
bkimg = GameUtil.loadBufferedImage(Constant.BK_IMG_OATH);
}
//绘制图片
public void draw(Graphics g){
//填充背景色
g.setColor(BK_COLOR);
g.fillRect(0,0,FRAM_WIDTH,FRAM_HEIGNT);
g.setColor(Color.black);
//得到图片的高度和宽度
int height = bkimg.getHeight();
int weight = bkimg.getWidth();
//循环的次数
int count = Constant.FRAM_WIDTH/weight+1;
for (int i = 0; i < count; i++) {
g.drawImage(bkimg,weight*i,Constant.FRAM_HEIGNT-height,null);
}
}
}
6、GameBarrierLayer(游戏中障碍物层)
在第87行中需要在电脑盘中创建一个txt文件,用来储存游戏数据,并在该文件中随意输入一位数字
package main;
import util.Constant;
import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 游戏中障碍物层
*/
public class GameBarrierLayer {
private GameTime gameTime;
private int txt;
private Random random = new Random();
private List<Barrier> barriers;
public GameBarrierLayer() {
barriers = new ArrayList<>();
gameTime = new GameTime();
}
//绘制障碍物
public void draw(Graphics g, Bird bird) {
for (int i = 0; i < barriers.size(); i++) {
Barrier barrier = barriers.get(i);
if (barrier.isVisible()) {
barrier.draw(g);
} else {
Barrier remove = barriers.remove(i);
Barrierpool.setPool(remove);
i--;
}
}
collideBird(bird);
logic(g);
}
public void logic(Graphics g) {
if (barriers.size() == 0) {
ran();
gameTime.begin();
insert(600, 0, numberTop, 0);
insert(600, 500 - numberDown, numberDown, 2);
} else {
long differ = gameTime.differ();
g.setColor(Color.white);
g.setFont(new Font("微软雅黑", 1, 20));
g.drawString("坚持了:" + differ + "秒", 30, 50);
//显示最高成绩
txt = getTxt();
if (differ <= txt){
g.drawString("最高成绩:" + txt , 200, 50);
}else {
setTxt(String.valueOf(differ));
g.drawString("最高成绩:" + getTxt() , 200, 50);
}
//判断最后一个障碍物是否完全进入屏幕内
Barrier last = barriers.get(barriers.size() - 1);
if (last.isInFrame()) {
ran();
if (number < 50){
insert(600,32,440,4);
}else if (number>450){
insert(600,125,200,6);
}else {
insert(600, 0, numberTop, 0);
insert(600, 500 - numberDown, numberDown, 2);
}
}
}
}
//用于储存游戏数据
File file = new File("E:\\小鸟.txt");
/**
* 从文件获取数据
* @return
*/
public int getTxt() {
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int read = 0;
try {
read = Integer.parseInt(in.readLine());
} catch (IOException e) {
e.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return read;
}
/**
* 写入数据到文件
* @param str
*/
public void setTxt(String str) {
FileWriter out = null;
try {
out = new FileWriter(file);
} catch (IOException e) {
e.printStackTrace();
}
try {
out.write(str);
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 用于从池中获取对象,并吧参数封装成barrier 存入barriers数组中
*/
public void insert(int x, int y, int num, int type) {
Barrier top = Barrierpool.getPool();
top.setX(x);
top.setY(y);
top.setHeight(num);
top.setType(type);
top.setVisible(true);
barriers.add(top);
}
//上方障碍物高度
private int numberTop;
//下方障碍物高度
private int numberDown;
private int number;
//产生两个100-500之间的随机高度
public void ran() {
numberTop = random.nextInt(400) + 100;
numberDown = random.nextInt(400) + 100;
number = random.nextInt(500);
//如果管道重合,则重新随机
if (numberTop + numberDown > 450) {
ran();
}
}
/**
* 判断障碍物和小鸟发生碰撞
*/
public boolean collideBird(Bird bird) {
for (int i = 0; i < barriers.size(); i++) {
Barrier barrier = barriers.get(i);
//判断矩形是否相交
if (barrier.getRect().intersects(bird.getRect())) {
System.out.println("装上啦");
bird.life = false;
}
}
return false;
}
/**
* 用于清空障碍物的池子
*/
public void restant(){
barriers.clear();
}
}
7、 GameFrame(游戏的主窗口类)
package main;
import static util.Constant.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
/**
* 游戏的主窗口类,所有的关于游戏中绘制的内容都在此类中完成。
*/
public class GameFrame extends Frame {
//实例化gamebackGround类
private GameBackGround gameBackGround;
//实例化Bird类
private Bird bird;
//实例化GameBarrierLayer类
private GameBarrierLayer gameBarrierLayer;
//实例化GameFrontGround类
private GameFrontGround gameFrontGround;
//存放图片的图片
private BufferedImage buffimg = new BufferedImage(FRAM_WIDTH,FRAM_HEIGNT,BufferedImage.TYPE_4BYTE_ABGR);
//构造方法中初始化一些参数
public GameFrame(){
//窗口是否可见
setVisible(true);
//窗口的大小
setSize(FRAM_WIDTH,FRAM_HEIGNT);
//窗口的标题
setTitle(FRAM_TITLE);
//窗口的初始化位置
setLocation(FRAM_X,FRAM_Y);
//窗口的大小不可改变
setResizable(false);
//窗口的关闭事件
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);//结束程序
}
});
//初始化游戏对象
initGamg();
new run().start();
//添加按键监听
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
add(e);
}
@Override
public void keyReleased(KeyEvent e) {
minu(e);
}
});
}
//对游戏中的对象初始化
public void initGamg(){
gameBackGround = new GameBackGround();
bird = new Bird();
gameFrontGround = new GameFrontGround();
gameBarrierLayer = new GameBarrierLayer();
}
class run extends Thread{
@Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(33);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 所有的我们需要绘制的内容都在此方法中进行调用绘制
*/
@Override
public void update(Graphics g) {
if(bird.life){
//得到图片的画笔
Graphics graphics = buffimg.getGraphics();
gameBackGround.draw(graphics);
bird.draw(graphics);
gameFrontGround.draw(graphics);
gameBarrierLayer.draw(graphics,bird);
//一次性的将图片绘制到屏幕中
g.drawImage(buffimg,0,0,null);
}else {
String over = "游戏结束";
g.setColor(Color.red);
g.setFont(new Font("微软雅黑",1,60));
g.drawString(over,180,250);
String reset = "Space Reset Game";
g.drawString(reset,25,350);
}
}
//按键
public void add(KeyEvent e){
switch (e.getKeyCode()){
case KeyEvent.VK_UP:
bird.fly(1);
break;
case KeyEvent.VK_SPACE:
if (bird.life == false) {
restart();
}
break;
}
}
//抬键
public void minu(KeyEvent e){
switch (e.getKeyCode()){
case KeyEvent.VK_UP:
bird.fly(5);
break;
}
}
/**
* 重置游戏
*/
public void restart(){
gameBarrierLayer.restant();
bird.restartDraw();
}
}
8、GameFrontGround(游戏的前景类)
package main;
import util.Constant;
import util.GameUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 游戏的前景类
*/
public class GameFrontGround {
//云彩的个数
private static final int CLOUND_COUNT = 2;
//存放云彩的容器
private List<Cloud> clouds;
//云彩的飞行速度
private static final int CLOUNG_SPEED = 1;
//使用到图片资源
private BufferedImage[] img;
//用于产生随机数
private Random random;
// 构造器初始化数据
public GameFrontGround() {
clouds = new ArrayList<>();
img = new BufferedImage[CLOUND_COUNT];
//容器中添加云彩的图片
for (int i = 0; i < CLOUND_COUNT; i++) {
img[i] = GameUtil.loadBufferedImage("飞翔的小鸟/img/cloud0" + i + ".png");
}
random = new Random();
}
//绘制云彩
public void draw(Graphics g) {
logic();
for (int i = 0; i < clouds.size(); i++) {
clouds.get(i).draw(g);
}
}
/**
* 用于云彩的个数控制
*/
private void logic() {
if ((int) (500 * Math.random()) < 5) {
Cloud cloud = new Cloud(img[random.nextInt(CLOUND_COUNT)], CLOUNG_SPEED, 600, random.nextInt(150));
clouds.add(cloud);
}
for (int i = 0; i < clouds.size(); i++) {
Cloud cloud = clouds.get(i);
if (cloud.isOutFrame()){
clouds.remove(i);
i--;
System.out.println("移除了"+cloud);
}
}
}
}
9、GameTime(游戏计时器)
package main;
/**
* 游戏计时器
*/
public class GameTime {
//开始
private long beginTime;
//结束
private long endTime;
//时间差
private long differ;
public GameTime(){}
public void begin(){
beginTime = System.currentTimeMillis();
}
public long differ(){
endTime = System.currentTimeMillis();
return differ=(endTime-beginTime)/1000;
}
}
四、util包
1、Constant(设置窗口资源)
package util;
import java.awt.*;
/**
* @author
* @create
*/
public class Constant {
//窗口的大小
public static final int FRAM_WIDTH= 600;
public static final int FRAM_HEIGNT= 500;
//窗口标题
public static final String FRAM_TITLE= "飞翔的小鸟";
//窗口的初始化位置
public static final int FRAM_X= 200;
public static final int FRAM_Y= 200;
//背景图片
public static final String BK_IMG_OATH = "飞翔的小鸟/img/bird_bk.png";
//背景色
public static final Color BK_COLOR = new Color(0x4BC4CF);
//小鸟图片资源
public static final String[] BIRD_IMG={
"飞翔的小鸟/img/bird_normal.png","飞翔的小鸟/img/bird_up.png","飞翔的小鸟/img/bird_down.png"
};
//障碍物图片资源
public static final String[] BARRIER_IMG_PATH ={
"飞翔的小鸟/img/barrier.png","飞翔的小鸟/img/barrier_up.png","飞翔的小鸟/img/Barrier_down.png"};
}
2、GameUtil(游戏工具类)
package util;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 游戏工具类
*/
public class GameUtil {
/**
*该方法传入一个图片路径 读取图片
*/
public static BufferedImage loadBufferedImage(String ImgPath){
try {
return ImageIO.read(new FileInputStream(ImgPath));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}