创建三个包,存放代码。把图片放进文件中
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 {//如果池中没有对象,只能newSystem.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;//实例化GameBarrierLayerprivate 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();}}}}/** 所有的我们需要绘制的内容都在此方法中进行调用绘制*/@Overridepublic 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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.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;}}
运行结果: