最近研究了一下古老的Java Swing,研究之余,突发奇想开发了一个打砖块小游戏。
首先看一下效果图

具体过程

  • 1.游戏框架搭建
    • 1.1步骤
  • 2.开发过程
    • 2.1各种游戏对象的绘制
    • 2.2游戏对象的运动
    • 2.3小球和砖块的碰撞检测
    • 2.4砖块被碰撞后的爆炸效果
  • 3.测试、完善。

1.游戏框架搭建

 整个游戏的画面的绘制渲染都位于JFrame上面,通过重写JFrame的paint(Graphics g)方法,完成所有游戏对象的绘制和各种效果的处理。注意不要调用super.paint(g)方法。
*[在这个过程中参考了一个大牛的Java 2D游戏系列文章,在此表示由衷的感谢。]*具体参考:https://blog.csdn.net/xcantloadx/category_7191132.html

1.1步骤

(1)这个过程主要是启动了一个游戏运行的窗口;
(2)为了让游戏中的对象动起来增加了一个渲染线程,按固定频率刷新;
(3)为与用户交互,控制挡板,窗口增加了键盘事件的监听和处理;
(4)当游戏中的对象动起来的时候出现闪烁现象,增加了双缓冲处理解决之;

2.开发过程

 为了方便和简单,在游戏开发过程中最终没有使用图片,也尝试了图片的小球、挡板、砖块,但是最终决定用最简单的几何图形绘制来表现各种游戏对象,在打砖块中只有简单的圆形和矩形,没有复杂的形状。

2.1各种游戏对象的绘制

(1)小球的绘制直接使用圆形,给定一个固定的半径,然后画圆,Swing的画圆是根据一个矩形,绘制矩形的内切圆,给出的坐标是矩形左上角的坐标,因此,如果需要获得圆心坐标,还需要在此基础只是各增加半径得到。
(2)挡板和砖块的绘制均为直接使用矩形,给出宽度、高度、坐标,然后画矩形。

2.2游戏对象的运动

(1)挡板的左右移动主要是靠键盘的左右方向键来控制,在挡板的左右移动中主要注意挡板到达边界的处理,不要移动到可视区域外面即可。
(2)按住方向键(up)游戏开始,小球开始运动。小球的运动范围位于整个窗口范围内,碰到墙后相应的改变方向,碰到挡板上面后继续弹起,如果落到挡板以下,则Game Over,碰到游戏内的砖块,显示一个爆炸效果并播放音效,砖块消失。

2.3小球和砖块的碰撞检测

 在实现小球和砖块碰撞效果的时候,自己直接使用逻辑判断来实现,然而常常没有考虑全面,出现了一些违反常理的现象,比如小球没有碰到砖块呢,可是砖块它消失了。而且觉得小球和砖块的碰撞情况也很复杂,没有想出全面的方法,小球碰到砖块的四个角是碰撞,碰到砖块的四个面那也是碰撞,感觉颇为棘手。于是借助了搜索引擎找到了一篇CSDN大牛的文章https://blog.csdn.net/yorhomwang/article/details/18195993,作者是在开发塔防游戏中涉及到此功能,给出了原理讲解和JavaScript的实现,于是借鉴之,改为Java实现,运行之后发现,这碰撞处理,简直完美!在此表示由衷的感谢。
 概括的说就是简化为圆形和矩形的碰撞,然后根据他们的坐标判断2者是否在平面直角坐标系的同一个象限内,只有2种情况,一种是矩形全部位于一个象限,另一种是矩形跨越了2个或2个以上的象限。

(1)矩形全部在一个象限内是圆形的圆心坐标和矩形的某个角的坐标之间距离计算处理。

这里示例了矩形全部在第一象限,任何一个象限都是这个原理,只要矩形全部在这个象限内。

这种情况比较好解决,首先,我们计算出矩形每个角的坐标,然后用勾股定理依次算出这个角到圆心的距离是否小于或者等于半径。设这个角与圆心横坐标之差为d1,纵坐标之差为d2,半径为r,公式表达如下

如果有一个角满足要求则说明产生碰撞。
怎么判断矩形是不是在一个象限内呢?很简单,只要判断这个矩形左上角和右下角是否在同一个象限内就可以了。代码方法如下:

    /*** 判断矩形是不是在一个象限里面(参考CSDN某大牛的碰撞检测JS代码,作者牛批)** @param center 圆形小球的圆心坐标* @param objA 矩形的左上角坐标* @param objB 矩形的右下角坐标* @return 圆形小球和矩形是否处于同一个直角坐标系象限*/protected boolean isSameQuadrant(Point center, Point objA, Point objB) {int cX = center.x;int cY = center.y;int xoA = objA.x, yoA = objA.y, xoB = objB.x, yoB = objB.y;int deltaACX = xoA - cX;int deltaBCX = xoB - cX;int deltaACY = yoA - cY;int deltaBCY = yoB - cY;if (deltaACX > 0 && deltaBCX > 0) {if ((deltaACY > 0 && deltaBCY > 0) || (deltaACY < 0 && deltaBCY < 0)) {return true;}return false;} else if (deltaACX < 0 && deltaBCX < 0) {if ((deltaACY > 0 && deltaBCY > 0) || (deltaACY < 0 && deltaBCY < 0)) {return true;}return false;} else {return false;}}

(2)矩形跨越2个或2个以上象限,将圆形看做一个正方形,简化为2个矩形中心点坐标距离的计算和处理。

矩形碰撞算法如图:

 如果要横向判断碰撞的话,判断(x1-x2)的绝对值是否小于或者等于w1/2+w2/2,如果是则横向则有碰撞。纵向判断是一样的,判断(y1-y2)的绝对值是否小于或等于h1/2+h2/2即可。
代码片段如下

boolean is = isSameQuadrant(ball.getCenter(), getLeftTop(), getRightBottom());
if (is) {int r = ball.getRadius();Point lt = getLeftTop();Point lb = getLeftBottom();Point rt = getRightTop();Point rb = getRightBottom();Point c = ball.getCenter();int dx1 = Math.abs(c.x - lt.x), dy1 = Math.abs(c.y - lt.y);int dx2 = Math.abs(c.x - lb.x), dy2 = Math.abs(c.y - lb.y);int dx3 = Math.abs(c.x - rt.x), dy3 = Math.abs(c.y - rt.y);int dx4 = Math.abs(c.x - rb.x), dy4 = Math.abs(c.y - rb.y);if(((dx1*dx1) + (dy1*dy1) <= r*r)||((dx2*dx2) + (dy2*dy2) <= r*r)||((dx3*dx3) + (dy3*dy3) <= r*r)||((dx4*dx4) + (dy4*dy4) <= r*r)){System.out.println("发生了碰撞");}} else {Point c = ball.getCenter();int squareW = ball.getRadius() * 2;int squareH = squareW;int brcx = x + getWidth() / 2;int brcy = y + getHeight() / 2;if((Math.abs(c.x - brcx) <= (squareW + getWidth())*0.5)&&(Math.abs(c.y - brcy) <= (squareH + getHeight())*0.5)){System.out.println("......发生碰撞");}}

2.4砖块被碰撞后的爆炸效果

 爆炸效果的实现方法,爆炸现象一般是以一个点为中心呈辐射状向周围发散。基于此可以创建一堆粒子,每个粒子模拟一个碎片,粒子为圆形,半径在一个范围内随机给出,每一帧修改一次粒子圆心的x,y坐标,粒子向四周发散出去速度也在一个范围内随机给出,这样就会更加的像一个爆炸的效果,粒子运动固定的帧数后消失。
 爆炸的起始点为被撞砖块的中心点。
 粒子的颜色要和砖块的颜色相同。

 // 粒子的初始化public ExplodeObject(){for (int i = 0; i < DEFAULT_COUNT; i++) {Particle p = new Particle(x, y, random.nextInt(3) + 2);p.setSpeed(random.nextInt(3) + 2);p.setNewRate(0.1);list.add(p);}}

粒子坐标的变化

        for (int i = 0; i < list.size(); i++) {Particle p = list.get(i);double temp = DEFAULT_RADIUS * p.getNewRate();double angle = (2 * Math.PI / DEFAULT_COUNT)*i;p.x = x+getWidth()/2+(int) Math.round(temp*Math.sin(angle));p.y = y+getHeight()/2+(int) Math.round(temp * Math.cos(angle));//System.out.println(String.format("p.x:%d, p.y:%d, p.radius:%d", p.x,p.y,p.radius));p.setNewRate(p.getNewRate() + 0.05*p.getSpeed());}

3.测试、完善。

  窗口初始的宽高和实际游戏对象运动范围的宽高是不一样的,如果不注意小球可能会跑出去一点,到顶部甚至就看不到了。通过获取JFrame的Insets(外镶边)可以得到每个边界的值,相应处理即可。
  目前小球在碰到砖块的角的时候,还缺乏一个改变小球方向的功能,参考了2个流行的打砖块游戏发现,有一个打砖块游戏改变了小球的方向,另外一个也并没有处理方向问题,碰到砖块的角砖块消失,小球继续前进,目前也是采用了这一做法。
  在小球落到挡板下面,game over之后,需要鼠标点击重新开始重新进行游戏,目前这个鼠标落点是硬编码,有待改进。
  放一张代码的结构图

  项目已托管到github: https://github.com/ximen502/BrickGame,欢迎浏览和star。项目中有一个压缩包rar文件,下载解压后点击里面的runGame.bat即可愉快的开始游戏了。

Java Swing制作古老的打砖块游戏相关推荐

  1. 使用java swing制作人机五子棋

    使用java swing制作人机五子棋 背景 算法原理 棋盘分值更新范围 更新分值方法 判断分值方法 局势分数权重 设计模式 战局类Battle AI类 Integration UI设计 窗口类UIi ...

  2. 【使用java swing制作简易贪吃蛇游戏】软件实习项目二

    一.项目准备 需求分析: 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后" ...

  3. Java Swing制作2048小游戏【完整版】

    技术讨论群:1005611884 可获取各种资料/代码,群内有Java/Python/C++/C#方向大佬,妹子多 /*** 技术 Swing* 实现思路:* 1. 绘制窗口* 2. 初始化游戏界面* ...

  4. java swing制作密钥生成器-AES对称加密

    本代码采用的是AES加密算法实现一个密钥生成器. 项目结构如下所示: [代码如下] LicenseEntry.java package cn.evansung.license;import java. ...

  5. 使用javaHelp制作java swing帮助文档

    使用javaHelp制作java swing帮助文档 最近在做一个Swing项目,项目接近尾声,需要做最后的帮助系统了.就想到了javaHelp.JavaHelp是sun退出的编写帮助系统的一个类库, ...

  6. java闪屏怎么制作,Java Swing创建自定义闪屏:在闪屏下画进度条(一)

    Java Swing创建自定义闪屏:在闪屏上画进度条(一) 由于本人十分热爱Java Swing,所以平时闲暇之余总是喜欢极尽所能去搜藏一些自认为比较"酷"的Swing代码来研究揣 ...

  7. java swing 右键_java swing制作右键菜单

    java swing中如何实现右键菜单呢?    直接上代码: /*** java * 设置弹出菜单 * @param qrResultLabel */ private void setPopupMe ...

  8. java 柱状图下载_(JFreeChart)Java图表制作

    (JFreeChart)Java图表制作软件时一个灵活的设计,很容易扩展,和目标服务器端和客户端应用程序;,支持多种图表类型. 输出类型也是多样化.包括Swing组件.图像文件(包括PNG和JPEG) ...

  9. java swing图形界面开发 java.swing简介

    最近在看YouTube上面的视频的时候,虽然学着做了一点界面和一点可以运行的东西,但是里面用到的库文件我还是不明就里的.所以我打算在制作游戏之前,先花几天的时间大概地研究一下关于java.swing的 ...

  10. java word转html 烟火,Java多线程制作烟花效果.doc

    Java多线程制作烟花效果 Java多线程应用实例: 制作烟花效果 本例知识点一句话讲解新学知识使用Thread类管理线程已学知识Math类产生随机数使用Color类设置颜色使用Graphics类绘制 ...

最新文章

  1. 专访陈天桥:把钱投给甘坐冷板凳的AI研究员
  2. WebConfig的经典使用,大家一起交流一下吧!!!
  3. oracle 中关于null的操作
  4. crontab 运行pyhon脚本
  5. Appendix之setup.py:附录文件内容记录setup.py
  6. 既生瑜何生亮 access_token VS refresh_token
  7. Oracle 1204 RAC failover 测试 (一)
  8. ACM MM2021 HANet:从局部到整体的检索!阿里提出用于视频文本检索的分层对齐网络HANet!代码已开源!...
  9. 【声传播】——多层介质平面波的反射问题
  10. (转)Arcgis for Js之GeometryService实现测量距离和面积
  11. ECMA-262 6th Edition
  12. hbase java 教程_Hbase 教程-安装
  13. python 获取qq群成员信息_Python获取统计自己的qq群成员信息的方法
  14. 备份 dup linux,13个开源备份解决方案盘点
  15. android 使用流量监控,android流量监控
  16. 【Windows】win10如何拦截弹窗?
  17. thinkpad10平板电脑装linux,ThinkPad X61上经历Ubuntu 8.10(安装笔记)
  18. Android进阶之光 读书笔记
  19. 王牌战争文明重启服务器维修中,王牌战争:文明重启在哪下,为什么王牌战争:文明重启进不去...
  20. Python处理Excel(6):处理清产核资表格(1)

热门文章

  1. 利用sklearn.cluster实现k均值聚类
  2. MongoDB分组查询数据库sql
  3. 英语思维导图大全 介词(七)
  4. [CTF]天下武功唯快不破
  5. mysql roundup_五星评分系统,Excel也能做
  6. ColdFusion CGI or Application variables
  7. echarts地图设置legend_ECharts 的第 100 个版本!
  8. 彻底关闭win10的自动更新
  9. 你可能不知道,你登曾是个气喘小胖子,靠努力逆袭完成梦想
  10. 14-父子组件通讯,父传子(props)