类似于“马里奥”的2D横向卷轴游戏中的碰撞反应

11

这几周一直困扰着我。在这段时间里,我上网搜寻了答案,甚至去Borders的电脑书籍区域阅读书籍,但没有太多运气。

我编写了一个2D关卡编辑器,用于侧向滚动视频游戏。现在我想把它变成一个游戏,让玩家可以奔跑和跳跃来探索关卡,就像“马里奥”一样。

真正困扰我的事情是碰撞响应(不是检测:我已经知道如何判断两个块是否碰撞)。下面是一些场景,我将详细说明这些问题(阴影块表示地面,箭头表示玩家的速度向量,虚线是玩家的预期路径)。

请查看这个碰撞响应示例图:

example http://dl.dropbox.com/u/12556943/collision_detection.jpg

假设场景(1)和(2)中的速度向量相等(方向和大小相同)。然而,在场景(1)中,玩家撞到了方块的侧面,在场景(2)中,玩家着陆在方块顶部。这让我得出结论:确定碰撞响应不仅取决于玩家的速度向量,还取决于玩家与碰撞块的相对位置。这引出了我的第一个问题:如何从玩家的速度向量和相对位置中确定玩家是从哪个方向(左侧、右侧、顶部或底部)与块发生碰撞?

另一个问题是,如果玩家在同一帧内与多个方块碰撞,我该如何确定碰撞响应。例如,在情况(3)中,假设玩家同时与这两个方块发生碰撞。我假设我需要循环遍历玩家正在发生碰撞的每个方块,并从每个方块相应地调整反应。总结一下,这是我的第二个问题:如果玩家与多个方块发生碰撞,我该如何处理碰撞响应?

请注意,我从未透露过我使用的编程语言;这是因为我更喜欢伪代码而不是特定于某种语言的代码。

谢谢!


你是否正在使用基于瓦片的世界(类似于2D马里奥游戏)?你的图片让我觉得是这样,但我不确定。 - chaosTechnician
是的,我有一个二维数组,它存储了关卡中每个方块的类型。 - Rob
3个回答

11

我认为XNA的示例平台游戏处理碰撞的方式可能适合你。我在Stack Overflow上的其他地方发布了对一个非常相似问题的回答,但也会在这里转述。

  1. 应用运动后,检查并解决碰撞问题。
  2. 根据玩家的边界框确定玩家重叠的瓷砖。
  3. 遍历所有这些瓷砖,并执行以下操作:(通常不会很多,除非您的玩家相对于世界瓷砖非常巨大)
    1. 如果正在检查的瓷砖是不可通过的:
      1. 确定玩家在X和Y轴上与不可通过的瓷砖重叠的距离
      2. 仅在浅轴(最小渗透轴)上将玩家移出该瓷砖以解决碰撞
        • 例如,如果Y是浅轴并且碰撞在下面,则将玩家向上移动,使其不再重叠该瓷砖。
        • 类似于此:if(abs(overlap.y) < abs(overlap.x)) { position.y += overlap.y; } else { position.x += overlap.x; }
      3. 根据玩家的新位置更新边界框位置
      4. 继续下一个瓷砖...
    2. 如果正在检查的瓷砖是可通过的,则不执行任何操作
  4. 如果解决碰撞可能将玩家移动到另一个碰撞中,则您可能需要再运行以上算法一次。或重新设计您的关卡。

如果您有兴趣获取他们的代码以查看他们特别在那里做什么,则此逻辑的XNA版本在player.csHandleCollisions()函数中。


如果你的玩家站在两个方块的顶部,就像这张图片所示:https://i.gyazo.com/01d4258366e7353492b78af9bbb97b11.png 这种情况可能会导致玩家侧移,这不是你想要的行为。 - Oli414
1
@Oli414 对于你的示例,常见的简单解决方案是通过将实体先在X轴方向上移动,仅水平解决碰撞,然后在Y轴方向上重复以上过程(或反之亦然)。 - Bryan W. Wagner

3
因为重力的持续作用会影响玩家的位置,所以这使得问题稍微有些棘手。如果玩家跳上方块,他们不应该反弹,而是应该落在方块上并停留在那里。但是,如果玩家撞到左侧或右侧的方块,他们不应该只停留在那里,重力必须将他们拉下来。我认为这大概是你的高层次问题。
我认为你需要从碰撞检测/响应算法中分离出重力和玩家速度两个力量。使用玩家的速度,如果他们与方块碰撞,无论方向如何,都将玩家的位置移动到碰撞的边缘,并从玩家的速度中减去等效的相反向量,因为如果不这样做,他们将再次与物体碰撞。您需要计算交点并将玩家的位置放置在方块上。
另外,您可以通过玩家与方块碰撞的类型来改变真正大的力量,从而产生有趣的响应,例如,如果玩家的速度>方块的力量,则玩家可以破坏方块。
然后,继续对玩家的位置施加恒定的重力,并继续进行正常的计算,以确定玩家是否到达了地面。
我认为通过将这两个概念分开,您可以得到一个非常简单直观的碰撞响应算法,并且您拥有一个相当简单的重力地板算法。这样,您可以在不必重新设计碰撞响应算法的情况下改变重力。例如水平面、太空等,碰撞检测响应都是相同的。

2

最近我思考了很久。

我正在使用分离轴定理,所以如果我检测到碰撞,我会将物体投影到规范化速度向量上,并沿着负速度向量的方向移动该物体的距离。假设该物体来自一个安全的位置,这个解决方案将在碰撞后将物体定位在一个安全的位置。

也许这不是你想要得到的答案,但希望它能指引你朝着正确的方向前进?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接