目录

前言

一、大体思路

二、具体步骤

1、创建窗体类

2、创建一个获取图片的工具类

3、创建画布

4、把地面画上去

5、创建一个新线程让画面动起来

6、创建柱子类

7、实现柱子在画布上的移动

8、创建小鸟类

9、小鸟添加到画布

10、实现键盘监听

11、判断游戏结束的方法

12、游戏结束后回到准备状态

13、统计分数

总结


提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

一个简单的单机小游戏:flypybird ,用来巩固java基础。

涉及主要知识点:JFrame 、 JPanel 、 继承、 键盘/鼠标监听 、 多线程 、 工具类设计


提示:这是大致的实现过程,实际实现过程有一定的修改,具体以源码为准。

一、大体思路

1、首先要有一个框架,作为主程序入口,这里使用 JFrame  类。

2、然后需要有一个画布,用来把游戏场景画上去,然后在上面添加键盘/鼠标监听来控制,这里使用的是 JPenal 类。

3、需要创建几个类:小鸟、地面、障碍物柱子、一个获取图片的工具类

4、然后逐步添加到画布中,实现对应的功能

二、具体步骤

1、创建窗体类

相当于窗户的框架,有了框架才能装玻璃。然后也是主程序执行的入口

1.1 具体代码:

public class MainFrame extends JFrame {/* 图标 */BufferedImage Icon;/** 构造器用来初始化框架*/public MainFrame() throws IOException {/* 设置图标 */Icon = ImageUtil.getImage("bird1_1.png");setIconImage(Icon);/* 设置关闭 */setDefaultCloseOperation(EXIT_ON_CLOSE);/* 设置标题 */setTitle("飞翔的小鸟");/* 设置尺寸*/setSize(298, 550);/* 设置大小不可变 */setResizable(false);/* 设置窗体居中 */setLocationRelativeTo(null);}/** 主程序* */public static void main(String[] args) throws IOException {MainFrame mainFrame = new MainFrame();mainFrame.setVisible(true);}
}

1.2效果展示

1.3小结

大体框架做好,考虑到后面还需要使用比较多的图片,因此接下来先建一个工具类,用来获取图片资源。

2、创建一个获取图片的工具类

2.1 具体代码:

/** 工具类,用来获取图片* */
public class ImageUtil {public static BufferedImage getImage(String name) throws IOException {return ImageIO.read(new BufferedInputStream(new FileInputStream("birdGame/flyBird/" + name)));}
}

2.2小结

图片获取方式改为用工具类获取,只需要输入图片名+格式。后期方便减少重复代码的书写。

3、创建画布

使用 Jpanel 类,创建画布(相当于玻璃) ,就能在上面画游戏的画面了。后期还需要在上面添加鼠标/键盘监听。

3.1具体代码

public class GameJPenal extends JPanel {/** 各种参数应该设置在这* */BufferedImage bg; /** 构造方法用来完成数据的初始化* */public GameJPenal() throws IOException {bg = ImageUtil.getImage("bg_day.png"); }/** 开始游戏的方法* */public void start() {gameStart = true;Thread myThread = new Thread(new MyThread());myThread.start();}//绘制的方法@Overridepublic void paint(Graphics g) { g.drawImage(bg, 0, 0, 288, 512, null);     //背景}
}

3.2 效果展示

先在main方法中创建对象,把画布添加到框架里面,注意要重新在最后设置可见,否者看不到背景

 /** 主程序* */public static void main(String[] args) throws IOException {MainFrame mainFrame = new MainFrame();GameJPenal gameJPenal = new GameJPenal();mainFrame.add(gameJPenal);  /* 画布添加到框架上 */mainFrame.setVisible(true);gameJPenal.requestFocus(); /* 请求屏幕焦点 ,否则无法实现键盘监听 */}

接下来就可以运行,效果如下

3.3、小结

这里需要注意一个点就是请求屏幕焦点:后期如果要做键盘监听的话必须有焦点,否则无法实现键盘控制

4、把地面画上去

4.1、代码

public class Ground {BufferedImage land;/*  x,y 是地面在画布上的坐标 */ private int x;private int y;private final int SPEED = 4;  //控制地面移动的速度public Ground() throws IOException {land = ImageUtil.getImage("land.png");x = 0;y = 512 - land.getHeight();}/** 地面移动的效果* */public void move() {if (x == (288 - land.getWidth())) {x = 0;}x-=SPEED;}/** get方法* */public int getX() {return x;}public int getY() {return y;}
}

接下来就是把地面的图片用画笔画上去

g.drawImage(land.landImg, land.x, land.y, land.w, land.h, null);

5、创建一个新线程让画面动起来

先把变量添加到 GamePanel 类

    Land land;    //地面Thread newThread;  //线程boolean gameStart; // 游戏状态变量,准备状态为 false ,游戏开始为 trueboolean gameOver;  //状态变量, 游戏开始为false ,游戏结束为true

在GamePanel 构造器里面初始化变量,创建一个新线程,用死循环不断调用地面移动的方法,然后重画画面,实现移动的效果

这里还加了俩个游戏的状态变量,主要是为了方便实现游戏的准备画面和游戏结束后可以重新开始游戏:

boolean gameStart;  //游戏准备状态
boolean gameOver;   //游戏结束状态
 /** 新开一个线程* */class MyThread implements Runnable {@Overridepublic void run() {while (true) {ground.move();c0.move();c1.move();bird.fly();bird.move();isGameOver();repaint();if (gameOver) {return;}try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}}}}

小结:

这时候画面已经能动起来了,接下来就是把其它的对象创建出来添加进去:鸟 、 障碍物(柱子)

6、创建柱子类

和创建地面类似,需要有他的坐标点和高度,同时为了画面柱子的连续性,需要俩组不同的柱子,

/** 柱子类* */
public class Column {private final int SPEED = 2;int w1;int h1;int x1;int y1;BufferedImage img1;int w2;int h2;int x2;int y2;BufferedImage img2;/** 构造方法* 初始化对象*/public Column(int i) throws IOException {img1 = ImageUtil.getImage("pipe_down.png");w1 = img1.getWidth() / 2;h1 = img1.getHeight();x1 = 288 + i * 150;y1 = -100 - i * 20;img2 = ImageUtil.getImage("pipe_up.png");w2 = img2.getWidth() / 2;h2 = img2.getHeight();x2 = 288 + i * 150;y2 = h2 - i * 25 -20;}/*柱子移动的方法* */public void move() {if (x1 == -w1) {x1 = 288;}if (x2 == -w2) {x2 = 288;}x1 -= SPEED;x2 -= SPEED;}
}

7、实现柱子在画布上的移动

和地面的初始化一样,在画布上添加成员变量,进行初始化,接下来用画笔在画布上画出来,在线程里面的死循环调用它移动的方法,实现柱子的移动

小结:

接下来就是把小鸟添加到画布上来

8、创建小鸟类

小鸟的x轴位置其实是固定的,因此小鸟只需要能在y轴移动就行,这一部分可以通过鼠标活着键盘监听来控制

小鸟有一个扇翅膀的动作,通过把图片存在一个集合里面,通过循环,每次画一个图片,就能实现扇翅膀的效果

难点:小鸟的上下移动的方法的设计

这里通过设计一个类似抛物线的动作,每次按下键盘Up,就改变它的上抛的初速度,让小鸟往上飞,经过时间 t 开始做落体运动

public class Bird {private double v0;  /* 小鸟运动的初速度 */double t;  /* 往上运动的时间 */int s;   /* 往上运动的路程 */int x;int y;int g;   /* 重力 */BufferedImage img;ArrayList<BufferedImage> list;  /* 装三张不同动作的图片 */public Bird() throws IOException {g = 3;v0 = 5;t = 0.3;img = ImageUtil.getImage("bird1_1.png");x = 100;y = 200;list = new ArrayList<>();list.add(ImageUtil.getImage("bird1_0.png"));list.add(ImageUtil.getImage("bird1_1.png"));list.add(ImageUtil.getImage("bird1_2.png"));}/** 鸟飞的动作,通过改变每次画不同动作的图片来实现* */int i = 0;public void fly() {if (i >= 3) {i = 0;}img = list.get(i);i++;}/** 鸟的上抛移动* */public void moveUP() {v0 = 10;}/** 鸟的落体运动*/public void move() {s= (int) (v0*t);y -= s;double v2 = v0 - g * t;v0 = v2;}
}

9、小鸟添加到画布

和柱子一样,不做赘述

效果如下:

10、实现键盘监听

注意:实现加键盘监听需要画布获得焦点

方法1:main 方法中设置

gameJPenal.requestFocus();

方法2:直接在GamePanel 类设置

setFocusable(true);

主要代码:

 this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {if (gameOver) {if (e.getKeyCode() == KeyEvent.VK_UP) {gameOver = false;gameStart = false;try {ground = new Ground();c0 = new Column(0);c1 = new Column(1);bird = new Bird();} catch (IOException ioException) {ioException.printStackTrace();}}} else if (gameStart) {if (e.getKeyCode() == KeyEvent.VK_UP) {bird.moveUP();}} else {start();}}});

11、判断游戏结束的方法

判断游戏结束其实比较简单,通过检测小鸟的x, y 坐标以及小鸟图片的宽度与柱子的x , y 坐标加上柱子的宽度做一个碰撞检测

/** 判定游戏是否结束的方法* */public void isGameOver() {//先判断是否落地if (bird.y <= 0 || bird.y >= 512 - ground.land.getHeight() - bird.img.getHeight()) {gameOver = true;}//判断是否撞柱子int bh = bird.img.getHeight();int bw = bird.img.getWidth();//c0.img1, c0.x1, c0.y1, c0.w1, c0.h1, nullif (c0.x1 <= bird.x + bw && c0.x1 + c0.w1 >= bird.x && c0.y1 + c0.h1 >= bird.y) {gameOver = true;}if (c1.x1 <= bird.x + bw && c1.x1 + c1.w1 >= bird.x && c1.y1 + c1.h1 >= bird.y) {gameOver = true;}if (c0.x2 <= bird.x + bw && c0.x2 + c0.w2 >= bird.x && c0.y2 <= bird.y + bh) {gameOver = true;}if (c1.x2 <= bird.x + bw && c1.x2 + c1.w2 >= bird.x && c1.y2 <= bird.y + bh) {gameOver = true;}}
if (gameStart == false) {g.drawImage(imageStart, 50, 200, null);}if (gameOver == true) {g.drawImage(imageGameOver, 50, 200, null);

12、游戏结束后回到准备状态

这里其实就是状态重置,写在在键盘监听事件里面,逻辑就是游戏结束,只要按了Up键,游戏就重置为准备状态。同时,在游戏 paint 方法中加一个判断,不同的状态对应不同的图片

if (gameOver) {if (e.getKeyCode() == KeyEvent.VK_UP) {gameOver = false;gameStart = false;try {ground = new Ground();c0 = new Column(0);c1 = new Column(1);bird = new Bird();score = 0;} catch (IOException ioException) {ioException.printStackTrace();}}repaint();

13、统计分数

分数统计原理:小鸟的x坐标和柱子的( x+w)相等,分数就+1

 if (bird.x == c0.x1 + c0.w1 || bird.x == c1.x1 + c1.w1) {score++;}

总结

游戏结构并不复杂,只需要逐步实现每个功能即可。然后用到的主要是一些比较基础的知识,对于巩固基础知识还是有一定帮助的。

第一次写博客,可能不够精简,可读性不强。下次加油  。


文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

java单机小游戏:flypybird相关推荐

  1. java游戏暂停弹出字体_小白写了个java的小游戏 想加个暂停的功能 无从下手 求大佬们帮...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 第一次写java的小游戏 想实现点击右下角的暂停 实现游戏的暂停和继续 不知道该怎么加,自己找了线程的内容但试了还是成功不了,求大佬们帮一下小白.代码有点 ...

  2. 用JAVA制作小游戏——飞机大战(三)

    本篇博客是对飞机大战游戏项目完整代码的展示 详细代码讲解: 用JAVA制作小游戏--飞机大战(一) 用JAVA制作小游戏--飞机大战(二) 最下方附整个程序的文件下载链接 代码展示 主界面 impor ...

  3. 用JAVA制作小游戏——飞机大战(二)

    本篇博客是对飞机大战游戏使用代码的展示 重难点: 首先需要鼠标能够控制战机,使鼠标在窗口内时始终能够使战机的位置与鼠标相同,实现鼠标控制战斗机移动. 其次需要能够以一定的速度产生子弹和敌机,并且以一定 ...

  4. 用JAVA制作小游戏——推箱子(三)

    本篇博客主要是对推箱子地图编辑器功能的代码讲解. 首先给出这段代码的部分运行截图: 重难点: 地图编辑器主要有三个重难点: 需要有一个绘制地图的界面 能够实现地图绘制的功能 地图绘制完成后需要将地图内 ...

  5. 用JAVA制作小游戏——推箱子(二)

    本篇博客主要是推箱子游戏界面功能的代码讲解. 首先先给出这段代码的部分运行截图: 重难点: 游戏界面主要有五个重难点: 固定好地图的位置 地图的显示 构建菜单栏 读取地图数据 玩家操作功能实现 地图的 ...

  6. 用JAVA制作小游戏——推箱子(一)

    本篇博客是对推箱子游戏首页代码的展示 效果图: 难点: 在背景图上添加按钮. 由于直接使用add方法,会变成图片一块区域,按钮一块区域,彼此互不重叠,形成的界面效果不太好,因此用了JLayeredPa ...

  7. java游戏暂停_小白写了个java的小游戏 想加个暂停的功能 无从下手 求大佬们帮...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 第一次写java的小游戏 想实现点击右下角的暂停 实现游戏的暂停和继续 不知道该怎么加,自己找了线程的内容但试了还是成功不了,求大佬们帮一下小白.代码有点 ...

  8. 我的《上勾拳》网页单机小游戏有什么版权问题吗

    很遗憾,你上传的[<上勾拳>网页单机小游戏,发泄类型,可以自己上传音效适配,适配PC和安卓.大部分元素为SVG动画,云彩和火焰是canvas动画]没有通过审核,原因是:版权,如有疑问,请联 ...

  9. (心得三)java俄罗斯方块小游戏编写心得

    在"java俄罗斯方块小游戏编写心得02"中,我们已经做到了方块的各种功能的实现,那么接下来我们需要一个destroyLine()方法来对方块进行消除.我们需要想一个问题,当一个方 ...

最新文章

  1. nginx php mysql分离,详解nginx、php-fpm和mysql用户权限
  2. jq 给节点node加事件_JavaScript 原生对象、属性、方法、事件、事件参数
  3. 【Linux - mysql】怎么修改数据库编码
  4. “数据挖掘世界杯”KDD Cup不取消!全球顶尖AI团队必争之地!
  5. 面试官:限制系统扩展能力的瓶颈有哪些?
  6. php如何防sql注入攻击,php防sql注入攻击(含php6)
  7. RabbitMQ系列教程之二:工作队列(Work Queues)
  8. 性冷淡风的麻将,获红点奖!网友:没有烟火气了
  9. 国内外公共CDN静态资源网站大全
  10. androidsettitle方法_Android 去掉title bar的3个方法
  11. 第3章 系统设计和架构设计【扩胸运动,有容乃大】
  12. Function语意学之Member的各种调用方式
  13. 荧光染料Alexa Fluor 647 carboxylic acid/COOH/羧基羧酸
  14. JAVA——文件操作(全)
  15. PHP教程电子版下载
  16. Modelsim中出现Syntax error, unexpected non-printable character错误
  17. CDH5.15离线搭建简易版集群(完整版)
  18. tenda w311mi驱动安装-ubuntu
  19. 计算机病毒可以破坏网络吗,计算机病毒的主要危害
  20. OSX: QuickLook快速预览不工作?

热门文章

  1. 第一章 cucumber测试框架综述
  2. Was8.5静默安装完整步骤
  3. 高校房产管理—周转房、经营性房产管理分析
  4. Android 文本,软键盘使用指南
  5. java复制数组到数组,Java如何将一个数组元素复制到另一个数组
  6. 密码嗅探、中间人攻击
  7. CODESYS开发教程6-关键字及变量类型
  8. 【OpenWRT】自用总结
  9. 009. 我在尼泊尔看雪山
  10. 成为数据分析师,需要具备哪些技能?