Java小游戏之飞翔的小鸟


Java小游戏之飞翔的小鸟


大家好,今天给大家带来一个Java经典小游戏—飞翔的小鸟。鉴于小博主初学,文章不足之处,还请见谅。

一、所用知识

  1. JFrame
  2. 线程

二、开发工具

  1. myeclipse
  2. jdk 1.8

三、开发过程

  1. 创建项目
  • 右键—new—Java Project
  • 为项目起个名字flappybird
  1. 导入素材
  • 右键项目—new—Package包
  • 把包命名为img,用来存放素材
  • 将素材图片全部粘贴到img包里
  • 素材一览

在这里插入图片描述
3. 窗体设计

(1) 创建JFrame容器

  • 右键项目—new—Package包,命名为ui
  • 右键ui包—new----class,新建一个类,命名为GameFrame
public class GameFrame extends JFrame{
	public GameFrame(){
		//设置窗体标题
		this.setTitle("飞翔的小鸟");
		//设置窗体大小
		this.setSize(432, 644);
		//设置窗体居中
		this.setLocationRelativeTo(null);
		//不允许用户改变窗体大小
		this.setResizable(false);
		//关闭窗体的同时关闭程序
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	public static void main(String[] args) {
		GameFrame frame = new GameFrame();
		frame.setVisible(true);
	}
}

(2) 在进行其他操作之前,我们可以想一下,素材图片这么多,我们不能每次都要写一大串的io代码吧,本着能省就省的原则,我们定一个工具类GameUtil,专门用来读取图片。

public class ImageUtil {
	//添加读取指定路径下的图片方法(给洗衣机添加洗衣服的功能)
	//path 需要读取图片的路径(相当于将衣服丢入洗衣机中)
	//如果不写下面的方法,每传输一张图片就要执行一次try……
	
	public static BufferedImage getImg(String path){

		try {
			//尝试根据地址找到图片
			BufferedImage img=ImageIO.read(ImageUtil.class.getResource(path));
			//如果找到,就返回图片
			return img;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			//如果找不到,就捕获找不到的原因,并将其输出出来
			e.printStackTrace();
		}//把图片变成流
		return null;
	}
}

这样的话,如果需要读取图片,仅需要调用该工具类的getImg方法即可。

  • 在GameFrame中用新创建额工具类设置窗体图标。
		//获取图标图片
		BufferedImage icon=FlayUtil.getImg("/img/0.png");
		//将图标图片设置成窗体图标
		this.setIconImage(icon);

(3) 创建JPanel容器

  • 用来存放诸多控件
  • 可以把JFrame当成一张桌子,把JPanel当成一个盘子,把控件当成菜,我们总不能直接把菜倒到桌子上吧。
    -右键ui包—new----class,新建一个类,命名为GamePanel,我们先把背景图加载出来,代码如下:
package ui;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;
public class GamePanel extends JPanel{
	GameFrame fr;
	//定义背景图片
	BufferedImage bg;
	
	public GamePanel(GameFrame frame) {
		// TODO Auto-generated constructor stub
		this.fr = frame;
		bg = GameUtil.getImg("/img/bg.png");
	}

	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		super.paint(g);
		//画背景图片
		g.drawImage(bg, 0, 0, null);
	}
}

效果如下:
在这里插入图片描述
(4) 窗体基本上就搭建好了,下一步我们要做的就是加载地面图片,并让它动起来。

  • 首先定义一个地面类Ground,用来定地面的属性和方法。代码如下:
package ui;

import java.awt.image.BufferedImage;

/**
 * 地面类
 * 注释方法:1./**  2.shift+alt+j
 * @author Lenovo
 *
 */
public class Ground {
	//定义地面的横坐标纵坐标
	int x;
	int y;
	//定义地面的宽高
	int w;
	int h;
	BufferedImage img;
	//地面的构造器,用来构造一个地面对象
	public Ground(){//在此处双击,可以选中括号中所有内容
		//地面图片
		img=GameUtil.getImg("/img/ground.png");
		w=img.getWidth();
		h=img.getHeight();
		x=0;
		y=644-h;
	}
}
  • 像画背景的步骤一样,在GamePanel中把地面画出来。代码如下:
package ui;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;
public class GamePanel extends JPanel{
	GameFrame fr;
	//定义背景图片
	BufferedImage bg;
	Ground ground;
	public GamePanel(GameFrame frame) {
		// TODO Auto-generated constructor stub
		this.fr = frame;
		bg = GameUtil.getImg("/img/bg.png");
		//初始化地面类对象,这样就可以引用ground中的属性和方法了
		ground = new Ground();
		
	}

	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		super.paint(g);
		//画背景图片
		g.drawImage(bg, 0, 0, null);
		//画地面
		g.drawImage(ground.img,ground.x,ground.y,null);//不设置宽高,默认为图片原始尺寸
	}
}

  • 此时地面图片已经加载出来了,下一步我们要做的就是让它动起来。
  • 在Ground类中创建一个move方法,负责地面的移动。
	//地面移动的方法
	public void move(){//访问修饰符    返回值类型   方法名
		x=x-2;
		//越界问题
		if(x<=-(w-432)){
		//1.地面图片比窗体的宽度要大。
		//2.当地面图片右侧移动到窗体右侧时,让地面图片横坐标归零
		x=0;
		}
	}
  • 在GamePanel中创建一个线程,在GameFrame中调用上面的方法,真正让地面动起来。代码如下:
//游戏开始的方法
	public void action(){
		new Thread(){

			public void run() {
				while(true){//让地面一直移动
					ground.move();
					//线程休眠时间
					try {
						Thread.sleep(20);
						//图片已经改动位置,因此要重画显示效果
						repaint();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			
		}.start();
	}

(5) 创建柱子对象,用来当做障碍物。

  • 首先定义一个柱子类Column,用来定义柱子的属性和方法。代码如下:
package ui;

import java.awt.image.BufferedImage;
import java.util.Random;

/**柱子类
 * 
 * @author Lenovo
 *
 */
public class Column {
	//柱子的图片
	BufferedImage img;
	//柱子的横纵坐标
	int x;
	int y;
	//柱子的宽高
	int w;
	int h;
	//柱子间距
	int distance;
	Random rd = new Random();
	public Column(int i){
		img=FlayUtil.getImg("/img/column.png");
		
		//建议y在-400到-250之间
		w=img.getWidth();
		h=img.getHeight();
		distance=300;
		x=400+distance*(i-1);
		y=-(rd.nextInt(150)+250);
	//	y=rd.nextDouble(-151)-250;
	}
}
  • 在GamePanel中定义柱子对象,并初始化。
//定义柱子1
	Column column1;
	//由于同一画面中可能会出现两根柱子,因此我们定义两个柱子对象
	Column column2;
		//初始化柱子1对象
		column1 = new Column(1);
		//初始化柱子2对象
		column2 = new Column(2);
  • 在GamePanel的paint方法中画出柱子。
  • 注:画柱子的代码要写在画地面的代码之后,否则地面图片将无法将多余的柱子图片覆盖。
		//画柱子1
		g.drawImage(column1.img, column1.x, column1.y, column1.w, column1.h, null);
		//画柱子2
		g.drawImage(column2.img, column2.x, column2.y, column2.w, column2.h, null);
  • 在Ground类中定义move方法,并在GamePanel的线程中调用(调用代码略)。让柱子移动起来,move方法代码如下:
//柱子移动的方法
public void move(){
		x=x-2;
		if(x<=-w){
			x=300+distance;
			y=-(rd.nextInt(150)+250);
		}
	}

(6)创建一个小鸟对象。

  • 新建一个小鸟类Bird,用来定义小鸟的属性和方法。代码如下:
package ui;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

/**
 * 小鸟类
 * @author Lenovo
 *
 */
public class Bird {
	//小鸟的横纵坐标
	int x;
	int y;
	//小鸟的宽高
	int w;
	int h;
	BufferedImage img;
	int index=0;
	//List<BufferedImage> animation = new ArrayList();
	//初速度
	double v0;
	//时间间隔(往上移动的时间)
	double t;
	//距离
	double s;
	//重力
	double g;
	Ground ground = new Ground();
	public Bird(){
		img=GameUtil.getImg("/img/0.png");
		w=img.getWidth()*2/3;
		h=img.getHeight()*2/3;
		x=200;
		y=200;
		v0=3;
		t=0.2;
		s=0;
		g=5;
	}
}
  • 在GamePanel中定义柱子对象,并初始化。
	//定义小鸟类
	Bird bird;
		//初始化小鸟对象
		bird = new Bird();
  • 在GamePanel的paint方法中画出小鸟。
		//画小鸟
		g.drawImage(bird.img,bird.x,bird.y,bird.w,bird.h,null);
  • 在GamePanel中添加键盘监听事件,通过键盘的空格键来控制小鸟上抛。
			//键盘监听
		// TODO Auto-generated method stub
		KeyAdapter adapter = new KeyAdapter(){
			public void keyPressed(java.awt.event.KeyEvent e) {
				int keyCode = e.getKeyCode();
				//按下空格键
				if(keyCode==32){
					//小鸟上抛
					System.out.println("123");
					bird.moveUp();
				}
				//按Ctrl键,游戏重新开始

			}
		};	
		fr.addKeyListener(adapter);
	}	
  • 在Bird类中定义fly方法(让小鸟实现飞翔效果)、move方法(小鸟做落体运动)、moveUp方法(键盘调用的小鸟上抛运动)、bang方法(小鸟撞到窗体顶部或底部)、beng方法(小鸟撞到柱子)。代码如下:
	//加载多张小鸟图片,让小鸟实现飞翔效果
	int step_num=0;
	public void fly(){
		index++;
		if(index>5){
			step_num++;
			img=FlayUtil.getImg("/img/"+step_num%8+".png");
			w=img.getWidth()*2/3;
			h=img.getHeight()*2/3;
			index=0;
		}
	}
	
//小鸟的落体运动
	public void move(){
		//计算小鸟上抛的距离  距离等于速度×时间
		s = v0*t;
		//得到小鸟上抛到最高点时的坐标
		y=y-(int)s;//s为double类型,y为int类型,类型不匹配,因此要做强制类型转换
		//计算小鸟到达最高点时的速度
		double v2 = v0-g*t;
		//最高点的速度就是小鸟下落时的初速度
		v0 = v2;
	}

	//小鸟上抛
	public void moveUp(){
		v0=20;
	}
	//撞到窗体顶部或底部
	public Boolean bang() {
		// TODO Auto-generated method stub
		if((y<0)||(y+h>644-ground.h)){
			return true;
		}
		//没撞到
		return false;
	}
	
//小鸟和柱子碰撞
	public Boolean beng(Column column){
		if((x>column.x-w && x<column.x+column.w) &&//鸟的宽进入柱子宽的范围
		  ((y>column.y+column.h-526-h)||(y<column.y+526))){//鸟的高不在安全区的范围
			return true;
		}
		return false;
	}
  • 在GamePanel的线程中调用这些方法。
	//加载鸟飞的动画
	bird.fly();
	//小鸟做落体运动
	bird.move();
	//小鸟和柱子相撞
	Boolean boo1 = bird.beng(column1);
	Boolean boo2 = bird.beng(column2);
	if(bird.bang()||boo1||boo2){
		//游戏窗体类对象全部静止
		//结束当前循环
		break;
	}

(7) 设置分数与关卡数。游戏规则:每过一根柱子分数便+1,每过10根柱子关卡数便+1,每次关卡升级,游戏速度加快。

  • 在FlayPanel中定义分数和关卡变量。
	//定义分数
	int fraction=0;
	//定义关卡数
	int level=1;
  • 在线程中判断小鸟是否飞过柱子,并设置分数与关卡数的值。
//判断小鸟是否飞过柱子
if(bird.x==column1.x+column1.w || bird.x==column2.x+column2.w){
		fraction++;
		//给关卡属赋值,每过10根柱子关卡数便+1
		level=(fraction/10)+1;							
}
  • 更改休眠时间
Thread.sleep(11-level);
  • 在paint方法中画出分数和关卡数。
		//画分数
		g.setColor(Color.red);
		Font f = new Font("宋体",Font.BOLD,20);
		g.setFont(f);
		g.drawString("分数:"+fraction, 120, 30);
		g.drawString("关卡数:"+level,20,30);

(8) 添加控制游戏(线程)开始和结束以及重新开始游戏的代码,由于代码位置过于琐碎,因此小博主只将思路简单概括出来,详细代码见下方链接。

  • 定义开始(start)与结束(gmov)图片,并初始化。
  • 定义一布尔变量show,用来决定游戏是否开始以及是否显示开始(start)图片,设置初始值为true。
  • paint方法中添加一if判断条件,当show=true时,画出游戏开始图片。
  • 定义一布尔变量gameover,用来决定游戏是否结束以及是否显示结束(gmov)图片,设置初始值为false。
  • paint方法中添加一if判断条件,当gameover=true时,画出游戏结束图片。
  • 键盘监听事件中添加一if判断条件,当KeyCode=17(按下Ctrl键)且gameover=true(游戏已经结束)时,重新开始游戏:重置柱子、地面、小鸟对象,将start的值设置成true、gameover值设置成false,调用action方法。
  • 键盘监听事件中添加一if判断条件,在按下空格键开始游戏之后,如果show=true时(显示开始图片),让show=false。这样既能在开始游戏之后不再显示开始图片,又能使用空格键操控小鸟上抛。
  • 在线程的while(true)死循环下添加一个if条件,当show=false,即按下空格键开始游戏之后才实现地面柱子等移动。

至此,飞翔的小鸟已基本完成。

四、 素材与源码打包

网盘链接:https://pan.baidu.com/s/1KSd8dX4oVmYPJusd6RN0Pg
提取码:bxmd

五、 结语

小博主才疏学浅,文章有不足之处,还请各位见谅,有不足之处,万望指出。整理素材、图文排版实属不易,请各位大牛们嘴下留情,我以诚待诸君,望诸君以诚待我。

一、 本课题的研究意义 如今,游戏风行的程度,是第一台电子游戏机的研制者诺兰?布什纳尔先生始料不及的。在全世界最大的城市,直至最小的村庄,从纽约最辉煌的游乐场,到高加索最小的乡镇儿童娱乐点,在千家万户,正在进行着千千万万这样的“战斗”,伴随着无数成功与失败,兴奋与懊丧。游戏机带来了一个全球性的疯狂症,其他任何娱乐与之相比都望尘莫及。然而,究竟是什么原因使游戏机如此风行呢? 在回顾了游戏机发展简史之后,我们不难悟出,技术进步在游戏机发展过程中起到了极大的促进作用。但是,技术进步绝不是游戏机风行的唯一因素。随着终端设备开发能力的加强,作为娱乐终端的游戏也得到了很大程度的发展。这也加速了游戏在全球风行程度,所以对于游戏的研究和设计具有很重要的意义,这也是本课题研究的意义所在。 用java语言来设计一个游戏,不同于现在的大型网络游戏和手机游戏,也不同于其他的小型的单机控制程序,它对游戏编写者对java语言特点认知、语法运用、工作模式、面向对象的理解的把握都提出了更高的要求,特别是在游戏运行当中对外部按键的处理,各子程序的调用流程,先后顺序等码的复杂程度也都是一般程序不能比的。可以这样说,能完整的编出游戏,并可以稳定运行,会让我们对游戏有一个更深刻的认识;对游戏编写的难度有一个更切身的理解;对自己的编程能力及逻辑思维能力有一个很大的提高;再一次看到了java语言的面向对象性、动态性、高性能性,相信对java语言的学习也不无帮助。 二、课题的国内外开发动态 随着人们生活质量的不断提高以及个人电脑和网络的普及,人们的业余生活质量要求也在不段提高,选择一款好玩、精美、画面、品质优良的休闲游戏已经成为一种流行的休闲方式。可以说在人们的日常生活中,除了工作,学习,玩一款自己喜欢的游戏正在成为一种时尚。所以,开发一款大家都比较喜欢的,高品质的休闲游戏,将会收到人们的普遍欢迎。让人们在工作学习之余,享受游戏的快乐,也是一款游戏真正成功的意义。Java是一种简单的,面向对象的,分布式的,健壮的,安全的,可移植的,性能很优异的语言。Java是休闲互动游戏开发的先导语言,使用java作为开发工具,是一种很理性的选择。 三、课题的基本内容 这是一款十分变态虐心的休闲游戏游戏主打像素风格,粗看画面十分简陋,,游戏中玩家需要点击屏幕操作一只小鸟在类似《超级马里奥》的绿色管道改变的数字中穿行,游戏的方式是飞翔小鸟带数字和2048游戏的结合体,要是不幸小鸟带的数字碰到不对应的数字障碍,或者不点击屏幕就直接Game Over。游戏里对小鸟的触碰判定非常严格,只要稍微节奏慢少许或者快了一点就会结束。由于游湖完全没有道具辅助,很多时候开局连第一个障碍也过不了就不得不重来。虽然只是一款小游戏,玩法也不特别,不过却抓住了玩家输不起的心理,用超高难度吸引玩家来挑战。 四、拟需要解决的主要问题 飞翔小鸟+2048小游戏开发的技术难点主要两个方面:一是界面的布局;二是游戏数据的安排。游戏很注重玩家的感受,所以界面的布局很重要,其次数据的显示在一个游戏的玩耍中也很重要,合理规划设计,开发出让玩家享受的游戏。正确理解实际运行中玩家的感受,解决游戏中模块的科学划分与结构组织,更好更快的开发设计游戏。 五、课题设计的实现方案 (1)本游戏开发语言的选 飞翔小鸟游戏以纯java语言来开发编写。Java是由Sun Microsystems公司推出的Java面向对象程序设计语言(以下简称Java语言)和Java平台的总称。由James Gosling和同事们共同研发,并在1995年正式推出。Java最初被称为Oak,是1991年为消费类电子产品的嵌入式芯片而设计的。1995年更名为Java,并重新设计用于开发Internet应用程序。用Java实现的HotJava浏览器(支持Java applet)显示了Java的魅力:跨平台、动态Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器均支持Javaapplet。另一方面,Java技术也不断更新。Java自面世后就非常流行,发展迅速,对C++语言形成有力冲击。在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。 (2)本游戏开发工具的选择 飞翔小鸟游戏使用的开发工具是一个开放源代码的、基于Java的可扩展开发平台eclipse来开发实现。Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。Eclipse是著名的跨平台的自由集成开发环境(IDE)。最初主要用来Java语言开发,通过安装不同的插件Eclipse可以支持不同的计算机语言,比如C++和Python等开发工具。Eclipse的本身只是一个框架平台,但是众多插件的支持使得Eclipse拥有其他功能相对固定的IDE软件很难具有的灵活性。许多软件开发商以Eclipse为框架开发自己的IDE。 六、研究方法 该毕业设计采用的研究方法主要有文献法和调查法。该毕业设计具体功能的获取过程主要使用文献法和走访调查法,通过网络调查和查阅网络资料来具体确定该软件的功能需求细节;在软件开发过程中,解决技术问题使用的方法是文献法,通过查阅课本、图书馆资料和网络在线文献等,解决在软件开发过程中的技术问题,比如数据库、建模工具的使用、软件测试等。 七、选题的特色及创新点 选题的特色:本毕业设计的开题经过走访调查和文献查阅等多种方式,基本可以与现实的需求相一致,并能体现用所学的知识和计算机技术解决实际问题。 选题的创新点:该选题采用的均是计算机成熟的技术,在计算机技术方面并没有体现创新点,但是通过完成该毕业设计,可以使得自己对计算机软件开发由更深的认识,积极培养自己的创新意识。
当然可以!以下是一个简单的Java小游戏飞翔小鸟的代码示例: ```java import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; public class BirdGame extends JFrame implements KeyListener { private int birdY = 250; // 小鸟的初始位置 private int speed = 0; // 小鸟的初始速度 public BirdGame() { setTitle("飞翔小鸟"); setSize(800, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); setVisible(true); addKeyListener(this); } public void paint(Graphics g) { super.paint(g); g.fillRect(100, birdY, 20, 20); // 绘制小鸟 } public void keyTyped(KeyEvent e) {} public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_SPACE) { speed = -10; // 按下空格键,小鸟向上飞行 } } public void keyReleased(KeyEvent e) {} public void birdMove() { birdY += speed; // 更新小鸟的位置 speed += 1; // 更新小鸟的速度 if (birdY >= 530) { birdY = 530; // 小鸟触底时停止下落 } repaint(); // 重绘界面 } public static void main(String[] args) { BirdGame game = new BirdGame(); while (true) { game.birdMove(); try { Thread.sleep(20); // 控制小鸟的速度 } catch (InterruptedException e) { e.printStackTrace(); } } } } ``` 这个代码示例实现了一个简单的飞翔小鸟游戏。通过按下空格键,小鸟会向上飞行,松开空格键后小鸟会自由下落。小鸟的位置和速度会不断更新,并通过重绘界面来实现动画效果。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值