这是与JavaFX 2游戏教程相关的六个部分系列的第四部分。 如果您错过了第1部分 , 第2部分或第3部分 ,我建议您在开始本教程之前仔细阅读它们。 回顾一下,在第3部分中,我为您提供了许多经典街机风格游戏和所使用的不同输入设备的历史记录。 然后,我向您展示了如何创建类似于著名街机“小行星”的简单游戏。 但是,控件(船的移动)与PC游戏“星际争霸”的控件更为相似。 在第3部分中,您应该对如何从键盘和鼠标接收输入有很好的了解。
图1 JavaFX 2游戏教程第4部分 |
本教程的内容是调整第2部分的游戏引擎,并更新第3部分中现有的“ Asteroids”风格的游戏以处理碰撞检测。 在本教程中,我将简要讨论精灵以及如何处理碰撞检测。 现在,飞船将具有产生力场的能力,以保护自己免受敌人和小行星的伤害。 这让人想起经典的街机“ 小行星豪华版 ”。 如果要运行演示,请向下滚动并单击下面的WebStart按钮。 在启动游戏之前,请先阅读要求。
什么是雪碧?
根据Wikipedia的说法,“ 子画面是整合到更大场景中的二维图像或动画。” 从Java游戏世界的角度来看,子画面是一个对象,其中包含图像帧和基于要动画化到场景区域上的演员的上下文的其他数据。 在沃尔特·迪斯尼 ( Walt Disney)时代 ,用铅笔和纸画漫画时,艺术家制作了许多图画,成为了动画。 这个例子指向了翻书的创建。 我确定您小时候就已经制作了翻书。 我知道我做到了 我曾经在笔记本的各个角落进行涂鸦和制作炫酷的动画。 在我们的Asteroid型游戏中,我创建了一个sprite对象,其中包含像翻书一样预先旋转的飞船的所有图像( ImageView )。 为了使船转弯具有动画效果,我使当前帧可见,而其余帧不可见。 与翻书类似,它似乎围绕其中心(枢轴)点旋转。 子画面还可以包含其他信息,例如速度或健康点。
碰撞检测
当演员或小精灵在整个场景中设置动画时,游戏引擎将检查每个小精灵是否与其他小精灵相互冲突,以确定它们是否相互碰撞。 此过程应该非常有效,尤其是当您在屏幕上移动大量精灵时。 在效率方面需要权衡。 因为游戏循环中的每个循环都会检查碰撞,所以更精确通常会降低性能。 许多游戏会使用图像的边界区域来确定两个精灵是否相互碰撞。 一些游戏使用矩形作为边界区域。 下面的图2中显示了两个精灵碰撞:
图2边界框为矩形碰撞区域。 |
我敢肯定,到现在为止,当围绕角色的像素是透明的时,游戏中的大多数角色(图像)都不会显示为矩形。 但是,即使像素是透明的,演员或图像的确是矩形的。
图3描绘了一个演员图像 |
那些使用矩形边界区域的游戏通常会在精灵图像中刻出边界框。 如图4下方所示,两个矩形边界区域(橙色和绿色)被刻在宇宙飞船图像中。
图4两个用作碰撞边界框的矩形。 |
我相信您会注意到船和机翼的鼻尖没有被任何一个边界盒覆盖。 这意味着,当小行星与子画面的无界区域重叠时,不会发生碰撞。 有些游戏使用这种策略。 您会注意到,子画面的矩形边界区域很小,并放置在子画面图像的关键区域中。 对于多边形和其他非矩形形状,使用更好的算法会发现更高的精度。 在此博客文章中,我基本上将圆形用作边界区域,而不是矩形。 我本可以使每个精灵包含一组碰撞形状,但我选择为每个精灵只设置一个碰撞区域。 每个碰撞区域在场景图上将为圆形。 对于宇宙飞船,我根据飞船的中心点划了一个圆圈,半径扩展到了飞船的驾驶舱。 下图5中显示了该船的有界圆形碰撞区域,用红色圆圈表示。
图5船舶的碰撞区域。 |
我选择一个圆作为边界区域是因为相对容易根据距离公式 ( 勾股定理 )确定两个对象的碰撞,该距离公式仅需要每个子图形的边界区域的中心点及其半径。 在基于两个中心点计算距离之后,您将比较结果以查看它是否小于或等于两个半径的总和。 如果结果确实小于或等于两个半径的总和,则发生了碰撞。 图6描述了距离公式如何与圆形边界区域的两个中心点相关。
图6两个中心点之间的距离公式。 |
以下代码从GameWorld类创建主游戏循环:
@Overridepublic void handle(javafx.event.ActionEvent event) {// update actorsupdateSprites();// check for collisioncheckCollisions();// removed dead thingscleanupSprites();}
下面的代码从GameWorld类创建checkCollision()方法:
protected void checkCollisions() {// check other sprite's collisionsspriteManager.resetCollisionsToCheck();// check each sprite against other sprite objects.for (Sprite spriteA : spriteManager.getCollisionsToCheck()) {for (Sprite spriteB : spriteManager.getAllSprites()) {if (handleCollision(spriteA, spriteB)) {// The break helps optimize the collisions// The break statement means one object only hits another// object as opposed to one hitting many objects.// To be more accurate comment out the break statement.break;}}}}
派生的Game World( TheExpanse )类对其handleCollision()方法的实现:
/*** How to handle the collision of two sprite objects.** @param spriteA Sprite from the first list.* @param spriteB Sprite from the second list.* @return boolean returns a true if the two sprites have collided otherwise false.*/@Overrideprotected boolean handleCollision(Sprite spriteA, Sprite spriteB) {if (spriteA != spriteB) {if (spriteA.collide(spriteB)) {if (spriteA != myShip) {spriteA.handleDeath(this);}if (spriteB != myShip) {spriteB.handleDeath(this);}}}return false;}
Sprite类使用距离公式的collide()方法的默认实现:
public boolean collide(Sprite other) {if (collisionBounds == null || other.collisionBounds == null) {return false;}// determine it's sizeCircle otherSphere = other.collisionBounds;Circle thisSphere = collisionBounds;Point2D otherCenter = otherSphere.localToScene(otherSphere.getCenterX(), otherSphere.getCenterY());Point2D thisCenter = thisSphere.localToScene(thisSphere.getCenterX(), thisSphere.getCenterY());double dx = otherCenter.getX() - thisCenter.getX();double dy = otherCenter.getY() - thisCenter.getY();double distance = Math.sqrt(dx * dx + dy * dy);double minDist = otherSphere.getRadius() + thisSphere.getRadius();return (distance < minDist);}
Sprite类的handleDeath()方法的默认实现:
public void handleDeath(GameWorld gameWorld) {gameWorld.getSpriteManager().addSpritesToBeRemoved(this);}
Atom (小行星或导弹)类将覆盖handleDeath()方法:
public void handleDeath(GameWorld gameWorld) {implode(gameWorld);super.handleDeath(gameWorld);}
JavaFX 2 Sprite和碰撞演示
这个简单的演示游戏将是星际争霸和小行星之间的混合体。 使用鼠标导航飞船时,您会注意到控件类似于StarCraft的Battle Cruiser 。 目的是在武器撞击您的飞船或其他因撞击而爆炸的球体之前向它们发射武器。 由于这是一个简单的教程,甚至是处于开发初期的游戏,因此该游戏无法跟踪得分。 我鼓励您去GitHub下载代码并增强游戏。 为了简洁起见,我不会显示所有代码更改,但是我相信您会在这里访问GitHub: https : //github.com/carldea/JFXGen,以获取所有演示和源代码。
要求 :
- Java 7或更高版本
- JavaFX 2.1或更高版本
- Windows XP或更高版本(应该很快可用于Linux / MacOS)
一个简单的小行星类型游戏,名为“ The Expanse”。
说明:
- 右键单击(在Windows上)以飞船。
- 单击鼠标左键(在Windows鼠标上单击鼠标左键)即可射击武器。
- 按键'2? 变成大型导弹。 (蓝色圆形弹丸)
- 其他按键默认为较小的导弹。 (红色圆形弹丸)
- 按下空格键将切换力场,以保护飞船免受敌人和小行星的伤害。
单击下面的启动按钮以启动演示:
继续本教程的第5部分 。
相关文章
Sprite的定义: http : //en.wikipedia.org/wiki/Sprite_%28computer_graphics%29
沃尔特·迪斯尼(Walt Disney): http : //en.wikipedia.org/wiki/Walt_Disney
如何制作翻书: http : //www.bitrebels.com/design/how-to-create-a-flip-book/
JavaFX的ImageView: http : //docs.oracle.com/javafx/2/api/javafx/scene/image/ImageView.html
碰撞检测:http: //zetcode.com/tutorials/javagamestutorial/collision/
Java中的AABB碰撞检测: http : //www.youtube.com/watch?v = JIxV-LXqa1g
勾股定理: http : //en.wikipedia.org/wiki/Pythagorean_theorem
距离公式: http : //en.wikipedia.org/wiki/Distance
严肃的Asteroids Deluxe游戏(Youtube): http : //www.youtube.com/watch?v= 6DG-GJENHgg
参考:来自我们的JCG合作伙伴 Carl Dea的JavaFX 2 GameTutorial第4部分 ,位于Carl's FX Blog博客上。
翻译自: https://www.javacodegeeks.com/2012/06/javafx-2-gametutorial-part-4.html