java - LWJGL 碰撞 3D OpenGL
问题描述
目前,我正在为我的引擎开发碰撞检测系统。我的代码工作得很好,但我怎样才能防止玩家穿过一个物体?
我的代码:
public void isCollide(Player player, Entity entity) {
if (
( player.getPosition().x <= entity.getScale() + entity.getPosition().x && player.getScale() + player.getPosition().x >= entity.getPosition().x ) &&
( player.getPosition().y <= entity.getScale() + entity.getPosition().y && player.getScale() + player.getPosition().y >= entity.getPosition().y ) &&
( player.getPosition().z <= entity.getScale() + entity.getPosition().z && player.getScale() + player.getPosition().z >= entity.getPosition().z )
)
{
System.out.println("Player is colliding!!!");
}
}
解决方案
碰撞检测的实现可能非常复杂,并且让碰撞看起来物理上正确是使碰撞变得困难的部分原因。
但是,从您提供的代码来看,您似乎在询问轴对齐边界框 (AABB) 碰撞,这一点都不复杂。
AABB 碰撞是一种非常简单的近似碰撞方法。总体思路很简单;获取游戏中的每个对象并为该对象创建一个边界框。对于轴对齐的边界框碰撞,这意味着您创建的边界框与世界轴对齐,并且每个碰撞框都用六个数字表示;最小 x 和最大 x,最小 y 和最大 y,以及最小 z 和最大 z。
要执行碰撞检查,您可以使用其中任意两个框并简单地检查它们是否在每个轴上重叠。如果它们在 x、y 和 z 轴上重叠,则这些对象正在碰撞。
要专门解决这个问题:
如何防止玩家穿过物体?
当您进行 AABB 碰撞时,这实际上也相当简单。这里的答案是简单地扭转最初产生碰撞的运动。所以你有一个球员和球员的AABB。更新球员位置时,您将球员边界框平移一些固定量。翻译完成后,您将执行碰撞检查。如果您发现玩家正在与某物发生碰撞,那么您撤消刚刚执行的平移,将玩家移出它正在碰撞的对象。
当您最终绘制场景时,您看到的是玩家不再发生碰撞,因为每次将玩家移动到碰撞中时,您都会撤消移动。
当然,这种方法并非没有问题,因为它是一种基本技术。例如,如果玩家的速度太高,它可能会导致玩家在物体之间移动。您还可能遇到撤消玩家移动不足以撤消碰撞的情况,尤其是在场景中有许多对象的情况下。使用AABB也有很多问题,例如下图;
如果您假设黑线是游戏中的某个对象,那么红框就是您创建的用于进行碰撞检查的 AABB。对于这个对象,显然有一种方法可以让其他边界框与这个框相交,这将记录一次碰撞,但大部分框都被空白空间填充。
即使其中包含的对象没有发生碰撞,这两个 AABB 也会记录碰撞。
要解决这些问题,您需要一些更聪明的东西,例如定向边界框和检查定向边界框之间碰撞的方法。
推荐阅读
- bash - 如何根据 File1 第一列比较 3 个 csv 文件
- java - 无法为 org.gradle.api.Project 类型的根项目“MyApplication3”获取未知属性“删除”
- javascript - 使用 javascript 和 html 将搜索提交到外部网站并在新选项卡中打开
- javascript - 聚合组合两个 ObjectAarray
- encoding - JPEG 编码器性能
- javascript - 使用 node.js ejs express 显示 mysql 查询结果
- css - 使用 :first-letter 伪元素的跨浏览器首字母大写
- php - 在过滤器中使用可扩展匹配时 ldap_search 失败
- mysql - 从 MySQL 中选择最近的行以获得一组不同的键
- python - 在 Matplotlib 中配置绘图