创建三个包,存放代码。把图片放进文件中
APP包(运行)
GameApp类
package APP;
import mian.GameFrame;
public class GameApp {
public static void main(String[] args) {
new GameFrame();
}
}
mian包(主内容)
Barrier 类(障碍物)
package mian;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import util.Constant;
import util.GameUtil;
/*
* 障碍物类
*/
public class Barrier {
private Rectangle rect;//小鸟矩形对象
//
private boolean mob=true;
private int speed=3;//障碍物移动速度
private static BufferedImage[] imgs;//障碍物需要的三个图片
//障碍物的状态
private boolean visible;
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]);
}
}
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_MOBLIE=6;
//获得障碍物的宽带和高度
public static final int BARRIRE_WIDTH=imgs[0].getWidth();
public static final int BARRIRE_HEIGHT=imgs[0].getHeight();
public static final int BARRIRE_HEAD_WIDTH=imgs[1].getWidth();
public static final int BARRIRE_HEAD_HEIGHT=imgs[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:
drawMormalTop(g);
break;
case TYPE_HOVER_NORMAL:
drawHoverNormal(g);
break;
case TYPE_MOBLIE:
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(imgs[0],x,y+i*BARRIRE_HEIGHT, null);
}
//绘制头
int y=height-BARRIRE_HEAD_HEIGHT;
g.drawImage(imgs[2],x-(BARRIRE_HEAD_WIDTH-BARRIRE_WIDTH)/2,y, null);
x-=speed;
if(x<-50) {
visible=false;
}
rect(g);
}
//绘制从下到上的障碍物
private void drawMormalTop(Graphics g) {
//求出所需要的障碍物的块数
int count=height/BARRIRE_HEIGHT+1;
//for循环绘制障碍物
for(int i=0;i<count;i++) {
g.drawImage(imgs[0],x,Constant.FRAM_HEIGHT-i*BARRIRE_HEIGHT, null);
}
//绘制头
int y=Constant.FRAM_HEIGHT-height;
g.drawImage(imgs[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(imgs[1],x,y,null);
//for循环绘制障碍物
for(int i=0;i<count;i++) {
g.drawImage(imgs[0],x,y+BARRIRE_HEAD_HEIGHT+i*BARRIRE_HEIGHT, null);
}
rect(g);
//绘制下头
int y11=y+height-BARRIRE_HEAD_HEIGHT;
g.drawImage(imgs[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(imgs[1],x,y,null);
//for循环绘制障碍物
for(int i=0;i<count;i++) {
g.drawImage(imgs[0],x,y+BARRIRE_HEAD_HEIGHT+i*BARRIRE_HEIGHT, null);
}
rect(g);
//绘制下头
int y11=y+height-BARRIRE_HEAD_HEIGHT;
g.drawImage(imgs[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;
}
}
}
/*
* 绘制障碍物矩形
*/
public void rect(Graphics g) {
int x1=this.x;
int y1=this.y;
int w1=imgs[0].getWidth();
// g.drawRect(x1, y1, w1,height);
setRectyangle(x1,y1,w1,height);
}
/*
* 障碍物矩形参数
*/
public void setRectyangle(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;
}
}
Barrierpool类(管理池中所有的对象的容器)
package mian;
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("容器归还了");
}
}
}
Bird(鸟)
package mian;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import static util.Constant.*;
import util.GameUtil;
/*
* 小鸟类
*/
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;
}
}
Cloud(云彩)
package mian;
import java.awt.Graphics;
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;
}
}
GameBackground(游戏背景)
package mian;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import util.Constant;
import util.GameUtil;
/*
* 游戏背景类
*/
public class GameBackground {
private BufferedImage bkimg;//背景需要的资源图片
//构造器初始化资源
public GameBackground() {
bkimg=GameUtil.loadBufferedImage(Constant.BK_CATH_OATH);
}
//绘制图片
public void draw(Graphics g) {
//填充背景颜色
g.setColor(Constant.BK_COLOR);
g.fillRect(0, 0, Constant.FRAM_WIDTH,Constant.FRAM_HEIGHT);
g.setColor(Color.black);
//得到图片的高宽和宽高
int height=bkimg.getHeight();
int width=bkimg.getWidth();
//循环的次数
int count=Constant.FRAM_WIDTH/width+1;
for(int i=0;i<count;i++) {
g.drawImage(bkimg,width*i,Constant.FRAM_HEIGHT-height, null);
}
}
}
GameBarrierLayer(游戏中障碍物层)
package mian;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
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) throws NumberFormatException, IOException {
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) throws NumberFormatException, IOException {
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("D:\\飞翔的小鸟.txt");
/*
* 用于得到文件中的数据
*/
public int getTxt() throws NumberFormatException, IOException {
BufferedReader in=new BufferedReader(new FileReader(file));
int read=Integer.parseInt(in.readLine());
in.close();
return read;
}
/*
* 用于储存数据
*/
public void setTxt(String str) throws IOException {
FileWriter fileWriter=new FileWriter(file);
fileWriter.write(str);
fileWriter.close();
}
/*
* 用来从池中获取对象,并把参数封装成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();
}
}
GameFrame
package mian;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import static util.Constant.*;
import util.Constant;
public class GameFrame extends Frame{
//实例化GrameBackground类
private GameBackground gameBackground;
//实例化Bird类
private Bird bird;
//实例化GameBarrierLayer
private GameBarrierLayer gameBarrierLayer;
//实例化GameFrontground类
private GameFrontground gameFrontground;
//存放图片的图片
private BufferedImage buffimg=new BufferedImage(FRAM_WIDTH,FRAM_HEIGHT,BufferedImage.TYPE_4BYTE_ABGR);
//构造方法中初始化一些参数
public GameFrame() {
setVisible(true);//窗口是否可见
setSize(FRAM_WIDTH,FRAM_HEIGHT);//窗体的大小
setTitle(FRAM_Ttile);//窗体的标题
setLocation(FRAM_x,FRAM_y);//窗体的初始位置
setResizable(false);//窗体的大小不可改变
//窗口的关闭事件
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);//结束程序
}
});
//初始化游戏对象
initGame();
new run().start();
//添加案件监听器
addKeyListener(new KeyAdapter (){
public void keyPressed(KeyEvent e) {
//super.keyPressed(e);
add(e);
}
public void keyReleased(KeyEvent e) {
//super.keyReleased(e);
minu(e);
}
});
}
//对游戏中的对象初始化
public void initGame() {
gameBackground=new GameBackground();
bird=new Bird();
gameFrontground=new GameFrontground();
gameBarrierLayer=new GameBarrierLayer();
}
class run extends Thread{
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);
try {
gameBarrierLayer.draw(graphics,bird);
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//一次性的将图片绘制到屏幕中
g.drawImage(buffimg,0,0,null);
}else {
String over="游戏结束";
g.setColor(Color.red);
g.setFont(new Font("微软雅黑",1,60));
g.drawString(over,300,250);
String reset="Spce 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();
}
}
GameTime(计时)
package mian;
/*
* 计时类
*/
public class GameTime {
private long begingTime;//开始
private long endTime;//结束
private long differ;//时间差
public GameTime() {
}
public void begin() {
begingTime=System.currentTimeMillis();
}
public long differ() {
endTime=System.currentTimeMillis();
return differ=(endTime-begingTime)/1000;
}
}
util(窗体)
Constant
package util;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
public class GameUtil {
public static BufferedImage loadBufferedImage(String imgpath) {
try {
return ImageIO.read(new FileInputStream(imgpath));
}catch(IOException e){
e.printStackTrace();
}
return null;
}
}
运行结果: