【问题标题】:3D Collision detection not functioning properly3D 碰撞检测无法正常工作
【发布时间】:2013-09-08 17:36:51
【问题描述】:

我一直在为我正在做的 3D 事物创建碰撞检测问题。

我进行碰撞检测的方式是,首先将旧的 xyz 坐标存储到变量中,然后调用移动函数,然后调用碰撞函数。如果移动后发生碰撞,相机 - 就像玩家(现在)一样 - 将被设置回旧的 x y z 坐标。

我希望角色能够沿着立方体的一侧“滑动”——这样如果你在 x 轴上发生碰撞,你仍然可以沿着 z 轴轻微滑动。然而,在拐角处,角色完全停止了——因为同时存在 x 和 z 碰撞。我决定为 z 和 x 碰撞创建单独的变量以阻止这种情况的发生,但现在我可以在拐角处进入立方体内部 - 但只能在 X 轴上。我不知道如何解决这个问题,我尝试了各种方法(比如代码中的最新变量),但我无法弄清楚。帮助将不胜感激。这是代码的相关部分:

def otherCollision(self,x,y,z):
       print(float(Camera.x))
       xcol = 0
       zcol = 0
       latest = 0
       if (-Camera.x >= cubez[0][0] - 1) and \
          (-Camera.x <= cubez[0][0] + cubez[0][3] + 1) and \
          (-Camera.z >= cubez[0][2] - 1) and \
          (-Camera.z <= cubez[0][2] + cubez[0][5] + 1):

            if (-Camera.x >= cubez[0][0] - 1) and \
               (-Camera.x <= cubez[0][0]) or \
               (-Camera.x <= cubez[0][0] - 1 + cubez[0][3] + 2) and \
               (-Camera.x >= cubez[0][0] - 1 + cubez[0][3] + 1): #>
                #Camera.x = x
                xcol = 1
                latest = 1

            if (-Camera.z >= cubez[0][2] - 1) and \
               (-Camera.z <= cubez[0][2]) or \
               (-Camera.z <= cubez[0][2] - 1 + cubez[0][5] + 2) and \
               (-Camera.z >= cubez[0][2] - 1 + cubez[0][5] + 1):    #>=
                #Camera.z = z
                zcol = 1
                latest = 2

       if xcol == 1 and zcol == 0:
           Camera.x = x
       if zcol == 1 and xcol == 0:
           Camera.z = z
       if xcol == 1 and zcol == 1 and latest == 2:
           Camera.x = x
       if xcol == 1 and zcol == 1 and latest == 1:
           Camera.z = z

应该提到cubez在一个列表中有个列表——第一个索引是对象的编号,下一个索引是我们要查找的值。他们依次是x,y,z,width,height,depth

我正在使用 pyglet 1.2alpha,但我认为这与帖子不太相关,因为很明显问题出在我的逻辑中。

【问题讨论】:

    标签: python pyglet collision


    【解决方案1】:

    我认为最好的解决方案是为你的演员添加一个速度属性(在你的例子中是“角色”还是“相机”?)。然后根据碰撞,将速度属性归零。

    给定一个像这样的简单矢量类:

    class Vector(object):
        def __init__(self, x=0.0, y=0.0, z=0.0):
            self.x = x
            self.y = y
            self.z = z
    

    ...你的演员看起来像这样:

    class Actor(object):
        def __init__(self):
            self.pos = Vector()
            self.vel = Vector()
    

    现在,当您更新场景时,请执行以下步骤(抽象为您的示例):

    1. 计算施加在演员身上的力,并更新vel 属性。
    2. 确定冲突,并相应地更新vel 属性。
    3. 使用来自vel 的数据更新演员的pos

    为简单起见,以下示例使用 2D 世界(z 始终为 0),并且更新的恒定时间步长(dt 被视为 1 秒)。

    class Actor(object):
        #(...)
        def update(self, dt=1):
            # Step 1 - assumes a constant movement to the top right
            self.vel.x = 1
            self.vel.y = 1
    
            # Step 2 - cube is your collision tested object
            cube = Cube()
            new_pos = self.pos + (self.vel * dt)
            if new_pos.x > cube.left and new_pos.x < cube.right:
                self.vel.x = 0
            if new_pos.y > cube.bottom and new_pos.y < cube.top:
                self.vel.y = 0
    
            # Step 3
            self.pos += self.vel * dt
    

    首先你应该得到这样的工作。当正常运行时,为您的actor添加一个边界框,以便在侧面而不是中心执行碰撞。

    【讨论】:

    • 如果没有办法用我现在做的方式来做,我会把它标记为正确的结果。我很想知道如何通过反转坐标(我现在使用的系统)来做到这一点 - 因为我读到许多游戏通过将玩家传送到以前的非碰撞坐标来进行碰撞检测。
    • 我猜这有点像番茄。在我的示例中,您正在将玩家“传送”到新位置,如果发生碰撞,请调整移动方向,使其不会发生碰撞。所以“传送”也会发生,但以不同的方式发生,我认为这是更可取的:你所做的计算是在一个临时的计算对象上进行的。然后pos always 表示你的actor的实际位置,而不是根据某些条件恢复它。
    猜你喜欢
    • 2011-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多