热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

四、碰撞检测

四、碰撞检测我们该谈谈碰撞检测了。它影响了我们游戏中明显的部分,比如我们无法穿过的墙。就像我们不

四、碰撞检测

我们该谈谈碰撞检测了。它影响了我们游戏中明显的部分,比如我们无法穿过的墙。就像我们不会掉下去的地板。它还会影响到我们游戏中模糊的部分,比如武器发射和关卡。

我们还没到达重力。我们也不会关注玩家的健康和重生。地板、投射物和检查站很有趣,但是它们应该有自己的部分。在这一章中,我们将创建不可逾越的对象。我们将学习知道两个物体是否占据同一个空间的方法。

我花了一些时间研究这个话题。似乎有很多方法可以计算出两个物体是否占据相同的空间。其中一些很容易解释和实现。我们会看的。其他方式都不容易。不过,他们还是很酷。

创建盒子

玩家只是同时存在于屏幕上的众多对象中的一个。我们的游戏是一个平台游戏,所以我们可以期待在任何给定的时间屏幕上至少有一个平台。

平台有一些有趣的特征。有时他们会让玩家摔倒。就像当你站在一个平台上,你按住并按下跳跃(同时)。一些游戏认为这个顺序意味着你想从平台上掉下去。

同样,一些游戏允许玩家在平台底部跳跃。这使得垂直移动在高架平台上没有间隙。

有时候平台甚至会动!

平台是如此的特殊,以至于我们将花几个小节来实现它们不同的行为。但是现在我们要关注另一个常见的物体。通用盒子。

把这个盒子想象成平台的祖先。它可能会共享一些平台功能,但它存在的主要原因是为了与它发生冲突。尤其是像播放器这样的东西。

我们要做的盒子可能看起来都不像盒子。当我们开始实现重力时,我们需要一个又宽又薄的盒子来防止玩家从世界中掉出来。我们还需要又高又薄的盒子来防止球员从地板上跑出来。我们会用它们做墙。我们甚至可以用盒子做盒子。又大又木的“跳到我身上去够更高的东西”的盒子。

好了,说够了。

class Box {
constructor(sprite, x, y, w, h) {
this.sprite = sprite
this.x = x
this.y = y
this.w = w
this.h = h
this.sprite.x = this.x
this.sprite.y = this.y
}
animate(state) {
this.sprite.x = this.x
this.sprite.y = this.y
}
}

这是出自 http://codepen.io/assertchris/pen/qaokJj

为了制作这个类,我复制粘贴了Player类,删除了一堆东西。我确实需要给它添加宽度和高度属性。我们一会儿会谈到这一点。

接下来,我们需要在舞台上添加两个这样的盒子:

const playerSprite = new PIXI.Sprite.fromImage(
"path/to/sprites/player-idle.png",
)
const player = new Player(
playerSprite,
window.innerWidth / 2,
window.innerHeight / 2,
44,
56,
)
const blob1Sprite = new PIXI.Sprite.fromImage(
"path/to/sprites/blob-idle-1.png",
)
const blob1 = new Player(
blob1Sprite,
(window.innerWidth / 2) - 150,
(window.innerHeight / 2) - 35,
48,
48,
)
const blob2Sprite = new PIXI.Sprite.fromImage(
"path/to/sprites/blob-idle-2.png",
)
const blob2 = new Player(
blob2Sprite,
(window.innerWidth / 2) + 150,
(window.innerHeight / 2) + 35,
48,
48,
)
const stage = new PIXI.Container()
stage.addChild(playerSprite)
stage.addChild(blob1Sprite)
stage.addChild(blob2Sprite)
let state = {
"renderer": renderer,
"stage": stage,
"keys": {},
"clicks": {},
"mouse": {},
"objects": [
player,
blob1,
blob2,
],
}

这是出自 http://codepen.io/assertchris/pen/qaokJj

那就奇怪了!我已经创建了两个新的Box实例,并将其命名为blob s。这是因为我们即将看到…

检测圆形碰撞

我要你为这几个盒子画圈。我们首先要做的碰撞检测类型是圆形。盒子有宽度和高度而不是半径是没问题的。你不会经常用这种碰撞检测,除非你的平台游戏里面有很多圈。

让我们看看这种检测是如何工作的:

class Player {
constructor(sprite, x, y, w, h) {
this.sprite = sprite
this.x = x
this.y = y
this.w = w
this.h = h
this.velocityX = 0
this.maximumVelocityX = 8
this.acceleratiOnX= 2
this.frictiOnX= 0.9
this.sprite.x = this.x
this.sprite.y = this.y
}
animate(state) {
if (state.keys[37]) { // left
this.velocityX = Math.max(
this.velocityX - this.accelerationX,
this.maximumVelocityX * -1,
)
}
if (state.keys[39]) { // right
this.velocityX = Math.min(
this.velocityX + this.accelerationX,
this.maximumVelocityX,
);
}
this.velocityX *= this.frictionX
let move = true
state.objects.forEach((object) => {
if (object === this) {
return
}
var deltaX = this.x - object.x
var deltaY = this.y - object.y
var distance = Math.sqrt(
deltaX * deltaX + deltaY * deltaY,
);
if (distance if (this.velocityX <0 && object.x <= this.x) {
move = false
}
if (this.velocityX > 0 && object.x >= this.x) {
move = false
}
}
});
if (move) {
this.x += this.velocityX
}
this.sprite.x = this.x
this.sprite.y = this.y
}
}

这是出自 http://codepen.io/assertchris/pen/qaokJj

我们需要做的第一件事是定义宽度和高度。虽然我们假装我们的玩家和盒子是圆,但我们只需要半个宽度作为半径。

接下来,我们检查状态中的每个对象。我们可以忽略玩家对象,因为我们不需要知道什么时候有东西和自己碰撞。不过,我们确实需要检查其他的东西。

当圆的原点之间的距离小于它们的组合半径时,圆会发生碰撞。它们的中点如此接近,以至于它们的线必须重叠。

我们快速检查玩家移动的方向是否是盒子所在的位置。如果是这种情况,那么我们阻止玩家向那个方向移动。

试一试。看到非正方形如何互相阻挡是相当有趣的。当然,为了这个简单的算法,它们都必须是正圆。

检测矩形碰撞

检测矩形的碰撞几乎和圆一样容易。继续把斑点图像换成方框图像。你甚至可以调整精灵的名字来反映你的盒子的方形。

这一次,我们将把玩家视为一个矩形。代替半径,我们需要检查玩家矩形和任一框之间是否有间隙。我们称之为轴对齐包围盒碰撞检测(简称 AABB)。

如果没有间隙,玩家想要向盒子的方向移动,那么我们会阻止这种情况发生:

let move = true
state.objects.forEach((object) => {
if (object === this) {
return
}
if (this.x this.x + this.w > object.x &&
this.y this.y + this.h > object.y) {
if (this.velocityX <0 && object.x <= this.x) {
move = false
}
if (this.velocityX > 0 && object.x >= this.x) {
move = false
}
}
})
if (move) {
this.x += this.velocityX
}

这是出自 http://codepen.io/assertchris/pen/qaokJj

这些是检测碰撞的简单方法,但还有其他方法。有一种使用基于投影的矢量数学(www.sevenson.com.au/actionscript/sat)来确定重叠。还有一个检查几个多边形中的每条线,看看是否有任何线相交( http://stackoverflow.com/questions/9043805/test-if-two-lines-intersect-Javascript-function )。太疯狂了。

你甚至可以用几组圆碰撞在一起做实验。那可能会很有趣。在图 4-1 中,我将这个小角色放进这些小盒子里一会儿…

A435434_1_En_4_Fig1_HTML.jpg

图 4-1。

Players and boxes

摘要

在这一章中,我们看了一些方法,可以用来检测游戏中玩家唾液和各种其他物体之间的碰撞。

花些时间重新排列方块和斑点,这样你就能感觉到你的第一关会是什么样子。


推荐阅读
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
author-avatar
王柱柱
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有