飞翔小鸟思路及代码

昨天跳着看视频把飞翔小鸟做出来了,下面分享一下我的思路。

先放成品图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

和上一篇飞机大战的思路相似:

1.先把窗体做出把背景图放在面板中
2.把游戏背景中地面移动实现
3.把柱子在面板中实现进场及移动
4.把小鸟放在面板中
5.鼠标监听控制小鸟飞行轨迹
6.写判断小鸟与柱子碰撞和与地面碰撞的方法
7.添加计分和游戏结束游戏开始的画面

上面步骤最难的是写判断碰撞的方法…
——————————————————————————————————————————

首先是窗体类:
public class GameFrame extends JFrame{
	public static void main(String[] args) {
		
		GameFrame frame=new GameFrame();
		GamePanel panel =new GamePanel();
		//显示窗体
		frame.setVisible(true);
		//向窗体内添加一块画板
		frame.add(panel);	
	}
	
	public GameFrame() {
		setTitle("飞翔小鸟");// 设置标题
		setSize(432, 644);//窗体尺寸
		setLocationRelativeTo(null);// 相对于屏幕左上角居中
		setResizable(false);// 设置不允许玩家拖动界面
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//设置Logo图标 img/0.png
	  setIconImage(ImageUtil.getImage("/img/0.png"));
	}
}

这是一个获取图片字节流的工具类:
public class ImageUtil {
	public static BufferedImage getImage(String path) {
		try {
			BufferedImage image = ImageIO.read(ImageUtil.class.getResource(path));
			return image;
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return null;

	}
}
地面类:
public class Ground {
	/*
	 * 定义地方的x,y坐标和宽高
	 */
	int x;
	int y;
	int w;
	int h;
	BufferedImage img;
		//地面的构造器用来构建地面对象
		public Ground() {
			img=ImageUtil.getImage("/img/ground.png");
			h=img.getHeight();
			w=img.getWidth();
			x=0;
			y=644-h;
		}
		
		public void Move() {
			//让地面能够一直往左边移动
			if(x<=-(w-432)) {
				x=25; //初始化x为25 刷新时没有明显的断层
			}else {
			x--;
			}
		}
}

这个是柱子类:
public class Column {
	/*
	 * 定义地方的x,y坐标和宽高
	 */
	int x;
	int y;
	int w;
	int h;
	Random ran = new Random();
	BufferedImage img;
	// 安全间隙
	int gap;

	// 构造器初始化构造柱子对象(i表示第几根柱子)
	public Column(int i) {
		img = ImageUtil.getImage("/img/column.png");
		h = img.getHeight() / 2;
		w = img.getWidth() / 2;
		x = 320 + (i - 1) * 245;
		y = -ran.nextInt(h + 146 - 644 + 1);
		// 初始化安全间隙
		gap = 75;
	}

	// 柱子移动
	public void Move() {
		if (x <= -w) {
			x = 432 + w;
			y = -ran.nextInt(h + 146 - 644 + 1);
		} else {
			x--;

		}
	}

}

这个是小鸟类(判断碰撞方法写在这里):
public class Bird {
	/*
	 * 定义地方的x,y坐标和宽高
	 */
	int x;
	int y;
	int w;
	int h;
	// 初速度
	double v0;
	// 时间间隔(往上移动的时间)
	double t;
	// 距离
	double s;
	// 重力
	double g;
	Random ran = new Random();
	BufferedImage img;

	List<BufferedImage> list;

	public Bird() {
		img = ImageUtil.getImage("/img/0.png");
		w = img.getWidth() / 2;
		h = img.getHeight() / 2;
		x = 100;
		y = 200;

		// 初始化初速度
		v0 = 2;
		// 时间
		t = 0.15;
		// 距离
		s = 0;
		// 重力
		g = 8;

		// 初始化装图片的容器
		list = new ArrayList<BufferedImage>();
		// 向容器中添加图片
		for (int i = 0; i < 8; i++) {
			list.add(ImageUtil.getImage("/img/" + i + ".png"));
		}
	}

	int index = 0;

	// 小鸟飞行时图片的切换效果
	public void fly() {
		if (index < 8) {
			img = list.get(index);
			index++;
		} else {
			index = 0;
		}
	}

	// 小鸟移动方法
	public void move() {
		// 计算小鸟上抛的距离
		s = v0 * t;
		// 得到小鸟上抛到最高点时的y坐标
		y = (int) (y - s);
		// 计算出小鸟到达最高点时的速度
		double v2 = v0 - g * t;
		// 最高点的速度就是小鸟下落时的初速度
		v0 = v2;
	}

	public void moveUp() {
		v0 = 15;
	}

	// 判断是否碰撞到天花板和地面
	public boolean hit() {
		if (y <= 0 || y >= 644 - 146 - h) {

			return true;
		}
		return false;
	}

	// 判断是否碰撞柱子
	public boolean hit(Column column) {
		if (x >= column.x - w && x <= column.x + column.w) {
			if (y > column.h / 2 + column.y - column.gap / 2 && y < column.h / 2 + column.y + column.gap / 2 - h) {
				return false;// 安全通过
			}
			return true;// 撞到了
		}
		return false;// 没撞到

	}

}

最后是画板类:
public class GamePanel extends JPanel {
	BufferedImage bg;//背景图
	/*
	 * 声明地面和柱子的对象
	 */
	Ground ground;
	Column column1;
	Column column2;
	Bird bird;//声明小鸟对象
	/*
	 * 接收三个碰撞条件的变量
	 */
	boolean bool1 ;
	boolean bool2;
	boolean bool3;
	// 游戏准备状态
	boolean start;//是否start
	boolean GameOver;//是否Gameover
	int socre;//分数

	public GamePanel() {
		bg = ImageUtil.getImage("/img/bg.png");
		ground = new Ground();
		column1 = new Column(1);
		column2 = new Column(2);
		bird = new Bird();

		// 监听鼠标
		MouseAdapter md = new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				// TODO 自动生成的方法存根
				super.mouseClicked(e);
				/*
				 * 当游戏为未开始时,点击鼠标为开始,执行start中的线程任务
				 */
				if (start == false) {
					start = true;
					start();
				} else if(GameOver){//当游戏结束时,点击鼠标为未开始,Gameover为否,并初始化画板中的各个对象
					start=false;
					GameOver=false;
					ground = new Ground();
					//初始化柱子对象
					column1 = new Column(1);//x = 300
					//初始化第二根柱子
					column2 = new Column(2);//x = 545
					//初始化鸟对象
					bird = new Bird();
					System.out.println("你的得分为 : "+socre);
					socre=0;
					repaint();
				}else{//游戏进行时,点击鼠标执行moveUp()方法
					bird.moveUp();
				}
			}

		};
		addMouseListener(md);
		addMouseMotionListener(md);
	}

	// 游戏开始的方法
	public void start() {
		MyThread mt = new MyThread();
		// 将线程所有执行的任务装入到线程对象中
		Thread t = new Thread(mt);
		// 将线程纳入线程调度
		t.start();// 告诉CPU可以给我这个线程分配时间片段了
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		g.drawImage(bg, 0, 0, null);// 添加背景
		g.drawImage(column1.img, column1.x, column1.y, column1.w, column1.h, null);// 添加第一根柱子
		g.drawImage(column2.img, column2.x, column2.y, column2.w, column2.h, null);// 添加第二根柱子
		g.drawImage(ground.img, ground.x, ground.y, null);// 添加地面
		g.drawImage(bird.img, bird.x, bird.y, bird.w, bird.h, null);// 添加第二根柱子
		/*
		 * 当游戏为未开始时,把准备页面画上去
		 */
		if(start==false) {
			g.drawImage(ImageUtil.getImage("/img/start.png"), 0, 0, null);
		}
		/*
		 * 当游戏为结束时,把结束页面面画上去
		 */
		if(GameOver) {
			g.drawImage(ImageUtil.getImage("/img/gameover.png"), 0, 0, null);
		}	
		//画板中字体设置
			Font f=new Font("宋体",Font.BOLD,18);
			g.setFont(f);
			g.setColor(Color.white);
			g.drawString("分数 :"+ socre, 20, 30);
	}
	//线程类
	class MyThread implements Runnable {
		//写在run()方法中,就可以用线程的方法同时进行判断
		@Override
		public void run() {
			/*
			 * 用死循环方式不断运行对象的方法
			 */
			while (true) {
				ground.Move();
				column1.Move();
				column2.Move();
				bird.fly();
				bird.move();
				bool1 = bird.hit();
				bool2 = bird.hit(column1);
				bool3 = bird.hit(column2);
				if (bool1||bool2||bool3) {
					GameOver = true;// 窗体内的对象全部静止
					break;// 结束循环
				}
				if(bird.x==column1.x+column1.w||bird.x==column2.x+column2.w) {
					socre++;//分数加一
				}
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				repaint();//刷新画面
			}
		}
	}
}

需要问题可以留言哦

  • 9
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值