首页 > 解决方案 > 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!!!");
    }

}

标签: javaopenglcollision-detectionlwjglgame-development

解决方案


碰撞检测的实现可能非常复杂,并且让碰撞看起来物理上正确是使碰撞变得困难的部分原因。

但是,从您提供的代码来看,您似乎在询问轴对齐边界框 (AABB) 碰撞,这一点都不复杂。

AABB 碰撞是一种非常简单的近似碰撞方法。总体思路很简单;获取游戏中的每个对象并为该对象创建一个边界框。对于轴对齐的边界框碰撞,这意味着您创建的边界框与世界轴对齐,并且每个碰撞框都用六个数字表示;最小 x 和最大 x,最小 y 和最大 y,以及最小 z 和最大 z。

要执行碰撞检查,您可以使用其中任意两个框并简单地检查它们是否在每个轴上重叠。如果它们在 x、y 和 z 轴上重叠,则这些对象正在碰撞。

要专门解决这个问题:

如何防止玩家穿过物体?

当您进行 AABB 碰撞时,这实际上也相当简单。这里的答案是简单地扭转最初产生碰撞的运动。所以你有一个球员和球员的AABB。更新球员位置时,您将球员边界框平移一些固定量。翻译完成后,您将执行碰撞检查。如果您发现玩家正在与某物发生碰撞,那么您撤消刚刚执行的平移,将玩家移出它正在碰撞的对象。

当您最终绘制场景时,您看到的是玩家不再发生碰撞,因为每次将玩家移动到碰撞中时,您都会撤消移动。

当然,这种方法并非没有问题,因为它是一种基本技术。例如,如果玩家的速度太高,它可能会导致玩家在物体之间移动。您还可能遇到撤消玩家移动不足以撤消碰撞的情况,尤其是在场景中有许多对象的情况下。使用AABB也有很多问题,例如下图;

在此处输入图像描述

如果您假设黑线是游戏中的某个对象,那么红框就是您创建的用于进行碰撞检查的 AABB。对于这个对象,显然有一种方法可以让其他边界框与这个框相交,这将记录一次碰撞,但大部分框都被空白空间填充。

即使其中包含的对象没有发生碰撞,这两个 AABB 也会记录碰撞。

在此处输入图像描述

要解决这些问题,您需要一些更聪明的东西,例如定向边界框和检查定向边界框之间碰撞的方法。


推荐阅读