java小游戏------Flappy Bird(飞翔的小鸟含源码)
链接:https://pan.baidu.com/s/1cZkqGN0gfGPjJM-FDxVUtg。链接:https://pan.baidu.com/s/1YcS3AtbHaY_G8JUOQg58Rg。如上图所示:我们需要绘制背景,小鸟,障碍物,当然也包括游戏开始界面以及死亡界面。(3)绘制障碍物(长柱和别的鸟),并使障碍物移动。(1)创建一个窗口绘制背景,绘制开始页面。(2)游戏界面展示的相关
前言:本小游戏可作为java入门阶段收尾创作。
需:掌握面向对象的使用,了解多线程和异常处理等知识。
如上图所示:我们需要绘制背景,小鸟,障碍物,当然也包括游戏开始界面以及死亡界面。
一:思路解析:
(1)创建一个窗口绘制背景,绘制开始页面
(2)绘制一只小鸟能上下移动
(3)绘制障碍物(长柱和别的鸟),并使障碍物移动
(4)碰撞测试
(5)计时器
(5)弹出死亡页面
二:代码的类
(1)游戏入口包 app
GameApp
(2)游戏界面展示的相关类包 main
GameFrame
GameBackGround
GameReady
Bird
Barrier
BarrierPool
GameBarrierLayer
Barrier1
GameBarrier1Layer
GameOver
GameTime
(3)工具类包 util
Constant
Gameutil
Musicutil
代码如下:
(1)App包
GameApp类(游戏启动以及背景音乐的添加)
package com.brid.app游戏的入口;
import com.brid.main游戏界面的展示相关的类.GameFrame;
import com.brid.util工具类.Musicutil;
public class GameApp {
public static void main(String[] args) {
new GameFrame();
Musicutil music=new Musicutil("D:\\java\\小游戏\\src\\music/bei.wav");
music.start();
@SuppressWarnings("unused")
int musicOpenLab =1;
}
}
(2)main包
GameFrame
package com.brid.main游戏界面的展示相关的类;
import com.brid.util工具类.Constant;
import com.brid.util工具类.Musicutil;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import static com.brid.util工具类.Constant.*;
//游戏的主窗口类
public class GameFrame extends Frame implements Runnable {
private int state;
// 游戏进行 状态 有 不用的 状态
private static int gameState;
public static final int STATE_READY = 0;
public static final int STATE_PLAYING = 1;
public static final int STATE_OVER =2;
//背景对象
private GameBackGround backGround;
//游戏前景对象
private GameBarrier1Layer frontGrond;
//游戏中的碰撞
private GameBarrierLayer barrierLayer;
//金币对象
private Barrier1 jinbi;
//小鸟对象
private Bird bird;
///游戏开始对象
private GameReady gameready;
//死亡
private GameOver gameover;
//音效
private Musicutil musicutil;
//所有在屏幕上绘制的内容,都是通过系统线程绘制的
//线程系统完成的工作:屏幕内容绘制,窗口的事件的监听和处理
//目前项目中存在两个线程任务。一个系统线程,一个是自己创建启动的线程(repaint())
//单独定义一张图片,然后将需要的内容绘制到图片上 一次性的将图片绘制窗口中
public BufferedImage bugImg=new
BufferedImage(FRAME_WIDTH,FRAME_HEIGHT,BufferedImage.TYPE_4BYTE_ABGR);
//窗口初始化
public GameFrame() {
initFrame();
//设置窗口可见
setVisible(true);
//初始化游戏对象
initGame();
}
//窗口初始化
private void initFrame() {
setSize(Constant.FRAME_WIDTH, Constant.FRAME_HEIGHT);
setTitle(Constant.Game_TITLE);
//窗口初始位置
setLocation(Constant.FRAME_X, Constant.FRAME_Y);
//窗口大小不可变
setResizable(false);
//关闭事件
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
//结束程序
System.exit(0);
}
});
//添加按键监听 接听事件的按键
addKeyListener(new MyKeyListener());}
//定义用于接受按键事件的对象的内部类
class MyKeyListener implements KeyListener {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
//处理按键按下事件
public void keyPressed(KeyEvent e) {
// 捕获 系统 传入的 按键虚拟值
int keyCode = e.getKeyCode();
switch (gameState){
case STATE_READY :
if (keyCode == KeyEvent.VK_P){
setGameState(STATE_PLAYING);
}
break;
case STATE_PLAYING :
if (keyCode == KeyEvent.VK_SPACE){
bird.fly();
}
break;
case STATE_OVER :
if (keyCode == KeyEvent.VK_R){
resetGame();
setGameState(STATE_READY);
}
break;
}
}
//处理按键松开事件
@Override
public void keyReleased(KeyEvent e) {
//捕获的系统传入的按键的虚拟键值
int keyCode = e.getKeyCode();
//开始游戏
switch (gameState){
case STATE_READY :
// music.player(); // 调用 音乐
break;
case STATE_PLAYING :
if (keyCode == KeyEvent.VK_SPACE){
bird.down();
}
break;
case STATE_OVER:
if (keyCode == KeyEvent.VK_R){
resetGame();
setGameState(STATE_READY);
}
break;
}
}
}
//重新开始游戏
private void resetGame(){
setGameState(STATE_OVER);
barrierLayer.reset();
bird.reset();
frontGrond.reset();
}
//对游戏中的对象进行初始化
private void initGame() {
gameready=new GameReady();
backGround = new GameBackGround();
frontGrond=new GameBarrier1Layer();
barrierLayer=new GameBarrierLayer();
// musicutil.load();
bird = new Bird();
gameover=new GameOver();
//启动线程
Thread thread=new Thread(this);
thread.start();
}
//父类方法 由JVM调用update 画笔
public void update(Graphics g) {
//得到图片画笔
Graphics bufG=bugImg.getGraphics();
if (gameState==STATE_READY){
gameready.draw(bufG);
}
if (gameState==STATE_PLAYING) {
backGround.draw(bufG);
//碰撞层
barrierLayer.draw(bufG, bird);
//遮挡层
frontGrond.draw(bufG, bird);
bird.draw(bufG);
}
if (gameState==STATE_OVER)
{
gameover.draw(bufG);
resetGame();
}
//一次性将图片绘制到屏幕上
g.drawImage(bugImg,0,0,null);
}
@Override
//多线程
public void run() {
while (true) {
//通过调用repaint JVM执行update 进行绘制
repaint();
try {
Thread.sleep(GAME_INTERVAL);//刷新频率
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//设置游戏进程的状态
public static void setGameState(int gameState) {
GameFrame.gameState = gameState;
}
}
GameBackGround
package com.brid.main游戏界面的展示相关的类;
import com.brid.util工具类.Gameutil;
import com.brid.util工具类.Constant;
import java.awt.*;
import java.awt.image.BufferedImage;
//游戏背景
public class GameBackGround {
//背景需要的资源
private BufferedImage bkImg;
//在构造方法中对资源进行初始化
public GameBackGround(){
bkImg= Gameutil.looadBufferedImage(Constant.BK_ING_PATH);
}
//自定义一个绘画方法
public void draw(Graphics g){
//先绘制背景色
g.setColor(Constant.BK_COLOR);
g.fillRect(0,0, Constant.FRAME_WIDTH, Constant.FRAME_HEIGHT);
//得到图片大小
int imgW=bkImg.getWidth();
int imgH=bkImg.getHeight();
int count = Constant.FRAME_WIDTH/imgW+1;
for (int i=0;i<count;i++){
g.drawImage(bkImg,imgW*i, Constant.FRAME_HEIGHT-imgH,null);
}
}
}
GameReady
图:
package com.brid.main游戏界面的展示相关的类;
/*
绘制 游戏的 开始界面
*/
import com.brid.util工具类.Gameutil;
import com.brid.util工具类.Constant;
import java.awt.*;
import java.awt.image.BufferedImage;
public class GameReady {
private final BufferedImage ready;
private BufferedImage titleImg;
private BufferedImage noticeImg;
private BufferedImage start;
public GameReady(){
titleImg= Gameutil.looadBufferedImage(Constant.TITLE_IMG_PATH);
noticeImg= Gameutil.looadBufferedImage(Constant.NOTICE_IMG_PATH);
ready=Gameutil.looadBufferedImage(Constant.START_IMG_PATH);
start=Gameutil.looadBufferedImage(Constant.start_IMG_PATH);
}
public void draw(Graphics g){
//背景色
g.setColor(Constant.BK_COLOR);
g.fillRect(0,0, Constant.FRAME_WIDTH, Constant.FRAME_HEIGHT);
int x = Constant.FRAME_WIDTH - titleImg.getWidth() >>1 ; // 开始 牌的 x坐标
int y = Constant.FRAME_HEIGHT / 3; // 开始 牌的 y坐标
g.drawImage(titleImg,x,y,null); // fly_bird 的 牌子
x= Constant.FRAME_WIDTH-noticeImg.getWidth() >>1 ;
y= Constant.FRAME_HEIGHT /3 <<1;
g.drawImage(noticeImg,x,y,null); // bird
x= Constant.FRAME_WIDTH-ready.getWidth()>>1 ;
y= Constant.FRAME_HEIGHT /2 ;
g.drawImage(ready,x,y,null);
x= Constant.FRAME_WIDTH-start.getWidth()>>1 ;
y= Constant.FRAME_HEIGHT /2+199 ;
g.drawImage(start,x,y,null);
}
}
Bird
package com.brid.main游戏界面的展示相关的类;
import com.brid.util工具类.Gameutil;
import com.brid.util工具类.Constant;
import java.awt.*;
import java.awt.image.BufferedImage;
import static com.brid.util工具类.Constant.FRAME_HEIGHT;
public class Bird {
//图片的张数
public static final int tu_shu=4;
//鸟的图片资源数组对象
private BufferedImage[]imgs;
//结束图片
private BufferedImage over;
//定义鸟的状态的变量
private int state;
public static final int STATE_0=0;
public static final int STATE_up=1;
public static final int STATE_down=2;
public static final int STATE_dieing=3;//坠落
public static final int STATE_died=4;//掉地上
//矩形小鸟
private Rectangle rect;
//小鸟坐标
private int x,y;
//小鸟在y轴上的属性
private int biany;
//向上最大速度
public static final int max_up_biany=10;
public static final int max_down_biany=15;
//计时
private GameTime gametime;
//对资源初始化
public Bird(){
imgs=new BufferedImage[tu_shu];
for (int i=0;i<tu_shu;i++){
imgs[i]= Gameutil.looadBufferedImage(Constant.BIRDS[i]);
}
//小鸟的初始化坐标
x= Constant.FRAME_WIDTH>>1;
y= FRAME_HEIGHT>>1;
int w=imgs[0].getWidth();
int h=imgs[0].getHeight();
int x=this.x-w;
int y=this.y-h;
//矩形大小
rect=new Rectangle(x+2,y+2,w-8,h-8);
gametime=GameTime.getInstance();
}
//绘制小鸟
public void draw(Graphics g) {
flyLogic();
//使用的图片资源索引
// int indx=state>STATE_dieing?STATE_dieing:state;
int halfImgW = imgs[state > STATE_dieing ? STATE_dieing : state].getWidth();
int halfImgH = imgs[state > STATE_dieing ? STATE_dieing : state].getHeight();
//让小鸟图片中心点的坐标和x,y的值一致
g.drawImage(imgs[state > STATE_dieing ? STATE_dieing : state], x - halfImgW, y - halfImgH, null);
//绘制小鸟的碰撞区域
g.setColor(Color.BLACK);
g.drawRect((int) rect.getX(), (int) rect.getY(), (int) rect.getWidth(), (int) rect.getHeight());
//计时
g.setFont(Constant.TIME_FONT);
g.setColor(Color.GREEN);
g.drawString(Long.toString(gametime.getSecondTime()),Constant.FRAME_WIDTH/2, FRAME_HEIGHT/8);
}
//小鸟飞行y轴变化
private void flyLogic(){
switch (state) {
case STATE_0:
break;
case STATE_up:
biany++;
if (biany > max_up_biany) {
biany = max_up_biany;
}
y -= biany;
rect.y -= biany;
//撞到上面
if (y < (imgs[state].getHeight(null) >> 1) + Constant.TOP_HEIGHT) {
die();
}
break;
case STATE_down:
biany ++;
if (biany > max_down_biany) {
biany = max_down_biany;
}
y += biany;
rect.y += biany;
//撞到下面
if (y > FRAME_HEIGHT - (imgs[state].getHeight(null) >> 1 - 1 / 2) * 2) {
die();
}
break;
case STATE_dieing:
biany++;
if (biany > max_down_biany) {
biany = max_down_biany;
}
y += biany;
if (y > Constant.FRAME_HEIGHT - (imgs[state].getHeight() >> 1)) {
y = Constant.FRAME_HEIGHT - (imgs[state].getHeight() >> 1);
died();
} break;
case STATE_died:
break;
}
}
//向上飞
public void fly(){
if (state==STATE_dieing||state==STATE_died||state==STATE_up)
return;
//状态只被改变一次
state=STATE_up;
biany=1;
if (gametime.isReady()){
gametime.startTiming();
}
}
//向下
public void down() {
if (state==STATE_dieing||state==STATE_died||state==STATE_down)
return;
state=STATE_down;
biany=1;
}
public Rectangle getRect() {
return rect;
}
public void die(){
state=STATE_dieing;
gametime.endTiming();
over=Gameutil.looadBufferedImage(Constant.OVER_IMG_PATH1);
}
//重置小鸟状态
public void reset(){
state=STATE_0;
biany=0;
x= Constant.FRAME_WIDTH>>1;
y= Constant.FRAME_HEIGHT>>1;
rect.y=this.y-imgs[0].getHeight();
gametime.reset();
}
public void died(){
// if ((y<FRAME_HEIGHT - (imgs[state].getHeight(null) >> 1)))
state=STATE_died;
GameFrame.setGameState(GameFrame.STATE_OVER);
// reset();
}
public boolean isdied(){
return state==STATE_died;
}
}
Barrier
package com.brid.main游戏界面的展示相关的类;
import com.brid.util工具类.Gameutil;
import com.brid.util工具类.Constant;
import java.awt.*;
import java.awt.image.BufferedImage;
//障碍物
public class Barrier {
//障碍物图片
private static BufferedImage[]imgs;
static {//图片个数
final int COUNT=3;
//类加载的时候,将图片初始化
imgs=new BufferedImage[COUNT];
for (int i=0;i<COUNT;i++){
imgs[i]= Gameutil.looadBufferedImage(Constant.ZHANGAI_IMG_PATH[i]);
}
}
//障碍物的移动速度
public static final int MIN_speed = 3;
// public Object setAttribute;
private 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_HEIGTH=imgs[1].getHeight();
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 =1;
public static final int TYPE_HOVER_NORMAL =2;
//添加障碍物是否可见 ture可见
public boolean visible;
private Rectangle rect;
public Barrier() {
this.width=BARRIER_WIDTH;
this.speed=MIN_speed;
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:drawHoverNrmal(g);
// break;
}
//绘制障碍物的矩形
// g.setColor(Color.RED);
//g.drawRect((int)rect.getX(),(int)rect.getY(),(int)rect.getWidth(),(int)rect.getHeight());
//鸟死亡之后障碍物不移动
if (bird.isdied())
return;
logic();
}
//从上到下绘制障碍物
private void drawTopNormal(Graphics g){
int count=(height-BARRIER_HEAD_HEIGTH)/BARRIER_HEIGHT;
for (int i=0;i<=count;i++){
g.drawImage(imgs[0],x,y+i*BARRIER_HEIGHT,null);
}
//绘制障碍物的头
int y=this.y+height-BARRIER_HEAD_HEIGTH;
g.drawImage(imgs[2],x-(BARRIER_HEAD_WIDTH-BARRIER_WIDTH>>1),y,null);
}
//从下往上绘制
private void drawBottomNormal(Graphics g){
int count=(height-BARRIER_HEAD_HEIGTH)/BARRIER_HEIGHT+1;
for (int i=0;i<count;i++){
g.drawImage(imgs[0],x,y+i*BARRIER_HEIGHT+BARRIER_HEAD_HEIGTH,null);
}
//绘制障碍物的头
g.drawImage(imgs[1],x-(BARRIER_HEAD_WIDTH-BARRIER_WIDTH>>1),y,null);
}
//悬浮障碍
// private void drawHoverNrmal(Graphics g){
// //绘制上面的头
// g.drawImage(imgs[1],x-(BARRIER_HEAD_WIDTH-BARRIER_WIDTH>>1),y+25,null);
// //绘制中间部分
// int count =(height-BARRIER_HEAD_HEIGTH*2)/BARRIER_HEIGHT-1;
// for (int i=0;i<count;i++){
// g.drawImage(imgs[0],x,y+i*BARRIER_HEIGHT+BARRIER_HEAD_WIDTH,null);
// }
// //绘制下面的头
// int y=this.y+height-BARRIER_HEAD_HEIGTH;
// g.drawImage(imgs[2],x-(BARRIER_HEAD_WIDTH-BARRIER_WIDTH>>1),y,null);
// }
/*
障碍物的逻辑部分
*/
public void logic(){
x-=speed;
rect.x-=speed;
//障碍物移除屏幕
if (x<-BARRIER_WIDTH){
visible=false;
}
}
/*
判断当前障碍物是否完全出现在窗口中
*/
public boolean isInFarm(){
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 setHeight(int height) {
// this.height = height;
// }
//
// public void setType(int type) {
// this.type = type;
// }
// public void setVisible(boolean visible) {
// this.visible = visible;
// }
public boolean isVisible() {
return visible;
}
public Rectangle getRect(){
return rect;
}
/*
设置障碍物的矩形属性
*/
public void setAttribute(int x, int y, int height, boolean visible, int type) {
this.x=x;
this.y=y;
this.height=height;
this.type=type;
this.visible=visible;
setRectangle(x,y,height);
}
public void setRectangle(int x,int y,int height){
rect.x=x;
rect.y=y;
rect.height=height;
}
}
BarrierPool
package com.brid.main游戏界面的展示相关的类;
import java.util.ArrayList;
import java.util.List;
/*
为了避免反复创建和销毁对象,使用对象池来提前创建好一些对象
*/
public class BarrierPool {
private static List<Barrier> pool = new ArrayList<Barrier>();
//对象池中初始的对象的个数
public static final int INTT_BARRIER_shuliang = 16;
//最大个数
public static final int MAX_BARRIER_shuliang = 20;
static {
//初始化池中对象
for (int i = 0; i < INTT_BARRIER_shuliang; i++) {
pool.add(new Barrier());
}
}//从池中拿一对象
public static Barrier get() {
int size=pool.size();
if (size>0){
//移除并返回最后一个
return pool.remove(size-1);
}else {
//池空,只能返回新对象
return new Barrier();
}
}
/*
将对象归还
*/
public static void giveBack(Barrier barrier){
if (pool.size()<MAX_BARRIER_shuliang){
pool.add(barrier);
}else {
}
}
}
GameBarrierLayer
package com.brid.main游戏界面的展示相关的类;
import com.brid.util工具类.Gameutil;
import com.brid.util工具类.Constant;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
//游戏中的障碍物层的类
public class GameBarrierLayer {
//障碍的位置和高度
private static final int TYPE1_zongjiange= Constant.FRAME_HEIGHT>>2;
private static final int TYPE1_hengjiange= Constant.FRAME_HEIGHT>>2;
private static final int TYPE1_MIN_HEIGHT= Constant.FRAME_HEIGHT>>3;
private static final int TYPE1_MAX_HEIGHT=(Constant.FRAME_HEIGHT>>3)*5;
private List<Barrier> barriers;
private Object Gameready;
public GameBarrierLayer() {
barriers = new ArrayList<>();
}
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,bird);
}else {
Barrier remove=barriers.remove(i);
BarrierPool.giveBack(remove);
i--;
}
}
//碰撞
collidBird(bird);
logic(bird);
}
/*
添加障碍物的逻辑
*/
private void logic(Bird bird) {
//鸟死后不在添加障碍物
if (bird.isdied()){
return ;
}
if (barriers.size()==0){
//游戏刚开始,添加一对
int topHeight= Gameutil.getRandomNumber(TYPE1_MIN_HEIGHT,TYPE1_MAX_HEIGHT+1);
int type=Barrier.TYPE_TOP_NORMAL;
Barrier top= BarrierPool.get();
top.setAttribute(Constant.FRAME_WIDTH,0,topHeight,true,type);
type=Barrier.TYPE_BOTTOM_NORMAL;
Barrier bottom= BarrierPool.get();
bottom.setAttribute(Constant.FRAME_WIDTH,topHeight+TYPE1_zongjiange,topHeight+TYPE1_zongjiange,true,type);
barriers.add(top);
barriers.add(bottom);
}else {
//判断最后一个障碍物是否完全进入窗口中
Barrier last= barriers.get(barriers.size()-1);
if (last.isInFarm()){
int topHeight= Gameutil.getRandomNumber(TYPE1_MIN_HEIGHT,TYPE1_MAX_HEIGHT+1);
int type=Barrier.TYPE_TOP_NORMAL;
int x=last.getX()+TYPE1_hengjiange;
Barrier top= BarrierPool.get();
top.setAttribute(x,0,topHeight,true,type);
type=Barrier.TYPE_BOTTOM_NORMAL;
Barrier bottom= BarrierPool.get();
bottom.setAttribute(x,topHeight+TYPE1_zongjiange, Constant.FRAME_HEIGHT-topHeight-TYPE1_zongjiange,true,type);
barriers.add(top);
barriers.add(bottom);
}
}
}
/*
判断所有障碍物和小鸟是否发生碰撞
*/
public boolean collidBird(Bird bird){
//鸟死后停止碰撞
if (bird.isdied()){
return false;
}
for (int i=0;i<barriers.size();i++){
Barrier barrier=barriers.get(i);
//两个矩形是否接触
if (barrier.getRect().intersects(bird.getRect())){
// System.out.println("障碍物 "+barrier.getRect());
// System.out.println("傻逼鸟"+bird.getRect());
bird.die();
// bird.died();
return true;
}
}
return false;
}
//重置障碍物
public void reset() {
barriers.clear();//容器的自带功能
}
}
Barrier1
package com.brid.main游戏界面的展示相关的类;
//金币
import java.awt.*;
import java.awt.image.BufferedImage;
import static com.brid.util工具类.Constant.FRAME_WIDTH;
public class Barrier1<rect> {
//图片
private BufferedImage img;
//速度
private int speed;
//方向
private int dir;
public static final int DIR_left=0;
public static final int DIR_right=1;
//坐标
private int x,y;
private int w,h;
private Rectangle rect;
public Barrier1(){}
public Barrier1(BufferedImage img, int dir, int x, int y){
super();
this.img=img;
this.speed=3;
this.dir=dir;
this.x+=speed;
this.y=y;
//如何得到一个1.0到2.0的double值
// suofang =1+ Math.random();
//确定金币缩放的大小
// suofangImageW=(int)(suofang*img.getWidth());
// suofangImageH=(int)(suofang*img.getHeight());
//矩形大小
w=img.getWidth();
h=img.getHeight();
rect=new Rectangle(x+250,y,w,h);
}
public void draw(Graphics g){
int speed=this.speed;
/* if (dir==DIR_none){
}*/
x=(dir==DIR_left)?x-speed:x+speed;
g.drawImage(img,x,y,w,h,null);
//金币矩形
// g.setColor(Color.GREEN);
// g.drawRect(x,y,w,h);
/* //向右走
g.drawImage(img,x,y,null);
g.drawImage(img,x,y,null);*/
logic();
}
//判断金币出屏幕,出去返回true 否则返回false
public boolean isoutFrame(){
boolean result=false;
if (dir==DIR_left){
if (x<=img.getWidth(null)){
return true;
}
}else if(dir==DIR_right){
if (x> FRAME_WIDTH){
return true;
}
}
return result;
}
//修改dir方向
public void setDir(int dir){
this.dir=dir;
}
public Rectangle getRect() {
return rect;
}
public void logic(){
if (dir==DIR_right){
x+=speed;
rect.x+=3;
}
else if (dir==DIR_left){
x-=speed;
rect.x-=3;
}
// if (x<-suofangImageW){
// visible=false;
//}
}
}
GameBarrier1Layer
package com.brid.main游戏界面的展示相关的类;
import com.brid.util工具类.Gameutil;
import com.brid.util工具类.Constant;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import static com.brid.util工具类.Gameutil.getRandomNumber;
//游戏中遮挡 前景类
public class GameBarrier1Layer {
public static final int zhouqi = 100;
//金币资源数目
public static final int jinbi_shu = 3;
//屏幕中最多的金币数
public static final int max_jinbi_shu = 2;
//用来管理前景中的金币容器
private List<Barrier1> jinbis;//new ArrayList<>();
//使用到的图片资源
private BufferedImage[] jinbiImgs;
//速度和方向
private int jinbiDir;
//用于控制金币的逻辑运算周期
private long time;
// private Bird bird;
// private Graphics g;
public GameBarrier1Layer() {
jinbis = new ArrayList<>();
jinbiImgs = new BufferedImage[jinbi_shu];
for (int i = 0; i < jinbi_shu; i++) {
jinbiImgs[i] = Gameutil.looadBufferedImage(Constant.JINBI_IMG_PATH[i]);
}
//OTDO
jinbiDir = Barrier1.DIR_right;
}
//前景的绘制
public void draw(Graphics g,Bird bird) {
for (int i = 0; i < jinbis.size(); i++) {
jinbis.get(i).draw(g);
}
chiBird(bird);
logic(bird);
}
//金币碰撞
public boolean chiBird(Bird bird){
if (bird.isdied()){
return false;
}
for (int i=0;i<jinbis.size();i++){
Barrier1 jinbi=jinbis.get(i);
//两个矩形是否接触
// System.out.println("狗鸟"+bird.getRect());
// System.out.println("金币"+jinbi.getRect());
if (jinbi.getRect().intersects(bird.getRect())){
// System.out.println("狗鸟"+bird.getRect());
// System.out.println("金币"+jinbi.getRect());
// System.out.println("被创死了");
bird.die();
return true;
}
}
return false;
}
//金币个数,速度,方向,等的控制
private void logic(Bird bird) {
//金币的逻辑 每隔100ms运算一次
if (System.currentTimeMillis() - time > zhouqi) {
time = System.currentTimeMillis();
//做一次逻辑运算
if (bird.isdied()){
// System.out.println("qqq");
return;
}
//如果 屏幕中的金币的数量小于最大数量,可以考虑加一个
if (jinbis.size() < max_jinbi_shu) {
//百分之一的概率添加
if (Gameutil.isInPercent(Constant.jinbi_gailv)) {
int index = getRandomNumber(0, jinbi_shu);
//根据金币方向的改变 调整出生位置
int x;
if (jinbiDir== Barrier1.DIR_right){
x = -jinbiImgs[index].getWidth(null);
}else {
x= Constant.FRAME_WIDTH;
}
int y = Gameutil.getRandomNumber(Constant.TOP_HEIGHT, Constant.FRAME_HEIGHT-112);
Barrier1 jinbi = new Barrier1(jinbiImgs[index], jinbiDir, x, y);
jinbis.add(jinbi);
}
}
//金币出屏幕的处理
for (int i = 0; i < jinbis.size(); i++) {
//获得容器中每一个金币
Barrier1 jinbi = jinbis.get(i);
//移除金币
if (jinbi.isoutFrame()) {
jinbis.remove(i);
i--;
}
}
if (Gameutil.isInAnyProbability(1, 100)) {
//新的金币方向
int newDir= Gameutil.getRandomNumber(Barrier1.DIR_left, Barrier1.DIR_right+1);
if (newDir!=jinbiDir){
//将新的随机运动方向赋值
jinbiDir=newDir;
for (int i = 0; i < jinbis.size(); i++) {
//获得容器中每一个金币
Barrier1 jinbi = jinbis.get(i);
jinbi.setDir(newDir);
}
}
}
}
}
//金币重置
public void reset() {
jinbis.clear();//容器的自带功能
}
}
GameOver
图:
package com.brid.main游戏界面的展示相关的类;
import com.brid.util工具类.Gameutil;
import com.brid.util工具类.Constant;
import java.awt.*;
import java.awt.image.BufferedImage;
public class GameOver {
private BufferedImage over1;
private BufferedImage over2;
private BufferedImage over3;
public GameOver(){
over1= Gameutil.looadBufferedImage(Constant.OVER_IMG_PATH1);
over2= Gameutil.looadBufferedImage(Constant.OVER_IMG_PATH2);
over3=Gameutil.looadBufferedImage(Constant.OVER_IMG_PATH3);
}
public void draw(Graphics g){
int x = Constant.FRAME_WIDTH - over1.getWidth() >>1 ; // 开始 牌的 x坐标
int y = Constant.FRAME_HEIGHT/4; // 开始 牌的 y坐标
g.drawImage(over1,x,y,null); // fly_bird 的 牌子
x = Constant.FRAME_WIDTH - over2.getWidth() >>1 ; // 开始 牌的 x坐标
y = Constant.FRAME_HEIGHT / 2; // 开始 牌的 y坐标
g.drawImage(over2,x,y,null);
x = Constant.FRAME_WIDTH - over3.getWidth() >>1 ; // 开始 牌的 x坐标
y = Constant.FRAME_HEIGHT /2+133; // 开始 牌的 y坐标
g.drawImage(over3,x,y,null);
}
}
GameTime
package com.brid.main游戏界面的展示相关的类;
/*
设置 游戏上方 出现的 计时器
*/
public class GameTime {
private static final GameTime GAME_TIME = new GameTime();
// 游戏时间状态
private int timeState;
// 未开始计时
public static final int STATE_READY =0;
// 开始计时
public static final int STATE_RUN = 1;
// 结束计时
public static final int STATE_OVER = 2;
// 计时开始和结束
private long startTime,endTime;
//
private GameTime(){
timeState = STATE_READY;
}
// 这个等于返回一个对象
public static GameTime getInstance(){
return GAME_TIME;
}
// 准备开始计时
public boolean isReady(){
return timeState==STATE_READY;
}
// 开始计时
public void startTiming(){
startTime=System.currentTimeMillis();// 获取 当前系统时间
timeState=STATE_RUN;
}
// 结束计时
public void endTiming(){
endTime=System.currentTimeMillis(); // 获取 当前系统时间
timeState=STATE_OVER;
}
/*
游戏用毫秒来计时
*/
public long getTime(){
if (timeState==STATE_RUN){
return System.currentTimeMillis()-startTime;// 游戏 运行时 的时间
}
return endTime-startTime; // 游戏 结束时 的时间
}
// 将游戏用的毫秒转化为秒来计时
public long getSecondTime(){
// System.out.println(getTime()/1000);
return getTime()/1000;
}
// 重新开始后,重置时间
public void reset() {
timeState=STATE_READY;
startTime=0;
endTime=0;
}
}
(3)util包
Constant
package com.brid.util工具类;
import java.awt.*;
import java.awt.image.BufferedImage;
public class Constant {
//游戏窗口大小
public static final int FRAME_WIDTH=1008;
public static final int FRAME_HEIGHT=600;
//名称
public static final String Game_TITLE="飞翔的小鸟";
//窗口初始化
public static final int FRAME_X=250;
public static final int FRAME_Y=100;
//图片资源路径
public static final String BK_ING_PATH="src/picture/5.png";
public static final String[] BIRDS=
{"src/picture/bird_0.png","src/picture/bird_up.png","src/picture/bird_down.png","src/picture/bird_die.png"};
public static final String[]JINBI_IMG_PATH=
{"src/picture/jin.png","src/picture/yin.png","src/picture/tong.png" };
public static final String[]ZHANGAI_IMG_PATH=
{"src/picture/zhong.png","src/picture/shang.png","src/picture/xia.png"};
//游戏刷新间隔
public static final int GAME_INTERVAL=33;
//游戏背景色
public static final Color BK_COLOR=new Color(0x4CB4CF);
//标题栏的高度
public static final int TOP_HEIGHT=20;
//
public static final int jinbi_gailv=10;
//游戏开始界面
public static final String TITLE_IMG_PATH="src/picture/title.png";
public static final String NOTICE_IMG_PATH="src/picture/bird_0.png";
public static final String START_IMG_PATH="src/picture/6.png";
public static final String start_IMG_PATH="src/picture/start.png";
//死亡界面
public static final String OVER_IMG_PATH1="src/picture/bird_2b.png";
public static final String OVER_IMG_PATH2="src/picture/chuangdie.png";
public static final String OVER_IMG_PATH3="src/picture/start2.png";
}
Gameutil
package com.brid.util工具类;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
public class Gameutil {
private Gameutil(){}
public static BufferedImage looadBufferedImage(String imgPath) {
try{
return ImageIO.read(new FileInputStream(imgPath));
}catch (IOException e){
e.printStackTrace();
}
return null;
}
/**求本次调用该方法时,对于概率性的事件是否发生的方法
*
* @paramnum取值范围【1-100】代表事件发生的百分比1代表1%
* @return如果该事件发生了返回ture,否则返回false
*/
public static boolean isInPercent(final int num){
return getRandomNumber(1,101)<=num;
}
//任意概率的事件是否发生的方法 发生返回true
public static boolean isInAnyProbability(int fenzi,int fenmu){
//处理的特殊情况
if (fenzi<=0||fenmu<=0){
//抛出异常
try {
throw new Exception("传入非法参数");
} catch (Exception e) {
e.printStackTrace();
}
//return false;
}
//一定发生的事件
if (fenzi>=fenmu){
return true;
}
return getRandomNumber(1,fenmu+1)<=fenzi;
}
/**
* 求指定区间的随机数的方法
* min 区间最小值,包含。
* max 区间最大值,不包含。
*/
public static int getRandomNumber(int min,int max){
return (int)(Math.random()*(max-min)+min);
}
}
Musicutil
package com.brid.util工具类;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Musicutil extends Thread {
private String fileName;
private final int EXTERNAL_BUFFER_SIZE = 524288;
public Musicutil(String wavFile) {
this.fileName = wavFile;
}
@SuppressWarnings("unused")
public void run() {
File soundFile = new File(fileName); // 播放音乐的文件名
if (!soundFile.exists()) {
System.err.println("Wave file not found:" + fileName);
return;
}
while (true) { // 设置循环播放
AudioInputStream audioInputStream = null; // 创建音频输入流对象
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile); // 创建音频对象
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat(); // 音频格式
SourceDataLine auline = null; // 源数据线
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline.getControl(FloatControl.Type.PAN);
}
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
// auline.close();
}
}
}
}
图片资源:
链接:https://pan.baidu.com/s/1cZkqGN0gfGPjJM-FDxVUtg
提取码:7777
背景音乐:
链接:https://pan.baidu.com/s/1YcS3AtbHaY_G8JUOQg58Rg
提取码:9999
华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。
更多推荐
所有评论(0)