【问题标题】:XNA 2D object collision (without Tiles/Grid)XNA 2D 对象碰撞(没有 Tiles/Grid)
【发布时间】:2014-11-01 14:30:26
【问题描述】:

第一次在这里发帖。尝试寻找以前的主题以提供帮助。

我使用的是 Visual Basic,但到目前为止,我已经能够使用 C# 并只是翻译成 VB。

我想要没有瓷砖的碰撞。流畅的运动,没有任何卡顿。我已经向下移动了,我的精灵停在了屏幕的边缘。

我读过我可以使用边界和相交,我已经尝试过了。当我每次按下箭头键时应用 IF 语句,使用 Bounds 和 Intersects(如果它相交,我只是防止精灵移动),它适用于 ONE 键。我向左移动进入一个物体,然后停下。如果我将 IF 应用于所有键,它将第一次工作。假设我向左移动到一个对象中,IF 语句会检查 Intersects 是否为真并采取相应的行动。

现在我想向右移动,远离物体。我不能,因为我的精灵已经与对象发生碰撞,因为每个箭头键都被编程为如果有交叉点则不会移动。我完全明白为什么会发生这种情况。

我目前拥有的代码:(每个箭头键都有相同的代码,改成它)

If Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Right) And rBlockBounds.X <= 
    graphics.GraphicsDevice.Viewport.Width - rBlockBounds.Width = True Then


            If rBlockBoundBoxBounds.Intersects(rObstructBounds) Then

                rBlockBounds.X += 0
                rBlockBoundBoxBounds.X = rBlockBounds.X - 1
            Else

                rBlockBounds.X += 1
                rBlockBoundBoxBounds.X = rBlockBounds.X - 1
            End If
        End If
  • rBlockBounds 是我的精灵作为矩形

  • rBlockBoundBoxBounds 是另一个 Rectangle(比 rBlockBounds 大 1 个像素),用作或多或少随 rBlockBounds 移动的 Hit Box,是进行碰撞检查的对象

  • rObstructBounds 是我将 Sprite 移动到的静止物体。

有人对我如何完成这项工作有建议吗?

【问题讨论】:

  • 您应该每次都检查 Key,然后根据该方向检查碰撞。因此,可能是一个 Select Case 的 Key,然后是 4 个 subs 来处理每个单独的动作。另外我会使用投影矩形来测试碰撞 - 如果不移动精灵 - 这样移动就不会发生,除非它可以。

标签: vb.net xna collision


【解决方案1】:

由于我自己使用 C# 编程,而不是 VB,因此我无法编写您的解决方案,但我可以解释一种更好的处理方法。

您想要做的是防止两个矩形相交。为此,您需要在代码中实现move 方法,该方法可以检查两个图块是否发生碰撞。这是一个 C# 示例:

public bool MoveX(float distance) // Move Player Horizontally in this example
{
    rBlockBounds.X += distance;
    if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
    {
        rBlockBounds.X -= distance;
        return false;
    }
    return true;
}

这实质上意味着,如果您遇到一个物体,您将被推出它。由于它发生在一个滴答声中,您不会得到任何前后动画。

这应该可以满足您的需求。您可以对此进行测试,然后也可以针对 y 坐标实现它。

另外,你可能会注意到我已经让函数返回一个布尔值。这是可选的,但允许您检查您的播放器是否已移动。

请注意,如果您将一个对象传送到另一个对象,则会导致问题,因此请记住每次移动任何东西时都要执行此操作。

但这应该可以满足您的需求。

编辑

请注意,由于您的对象不在平铺网格中,因此您需要以非常小的步长移动大量时间。

类似这样的:

public bool MoveX(float distance) // Move Player Horizontally in this example
{
    rBlockBounds.X += distance;
    if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
    {
        rBlockBounds.X -= distance;
        return false;
    }
    return true;
}

public bool MoveX(float distance, int repeat)
{
    for(int i=0; i < repeat; i++)
    {
        rBlockBounds.X += distance;
        if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
        {
            rBlockBounds.X -= distance;
            return false;
        }
    }
    return true;
}

第二个将采取多个步骤。这就是你会使用它的原因:

MoveX(500); // Will move 500 right. Could easily skip over objects!
MoveX(5, 100); // Will move 5 right one hundred times
// ^ This will take more time but will not skip object

您也可以这样做:

MoveX(3);        // If contact object will be max 3 pixels away
MoveX(1, 3);     // If contact object will be max 1 pixels away
MoveX(0.5f, 6);  // If contact object will be max 0.5 pixels away

现在我猜你所有的xy 位置都是整数。如果是这样,您可以在打第二个电话时离开并彼此紧挨着。如果不是,您将进行第三次调用。

希望这会有所帮助。

【讨论】:

  • 我的 X 运动在 rObstruct 和我的精灵之间留下了 1 个像素。然而,Y 运动导致对象彼此紧挨着,但没有相交。哦,这么近!它可能与 rObstruct 的位置有关吗?或者当我调用 MoveX/MoveY 时我通过了 3 或 -3?
  • 两者。要修复它,您必须更改后者。过段时间看看我的编辑。如果对绿色箭头有帮助,请不要忘记让我的解决方案正确。
  • 效果很好。不过,我现在看到这种方法有问题。要么我的电脑玩得不好,要么这样做会导致跳过/性能下降(特别是如果我想添加更多精灵)。虽然我正在输入这个,但屏幕上出现了字符跳过,所以它可能只是我的电脑:P 我现在可能会查看图块,因为我也想做一些编辑器..所以我可以将瓷砖放置到位以创建地图/区域。
  • 酷。我也是一个业余爱好者,但如果你想一起工作,我很乐意提供帮助。将您的代码发布在 github 或其他地方,我可以帮忙。 @比尔
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
相关资源
最近更新 更多