【问题标题】:C++ DirectX11 2d Game: Stopping enemy sprites moving over each other?C++ DirectX11 2d 游戏:阻止敌方精灵相互移动?
【发布时间】:2014-04-04 19:32:44
【问题描述】:

我正在使用IntersectsWith(this->boundingBox)) 方法来检测精灵和玩家之间的碰撞。我希望能够以某种方式使用这种方法来检测我的敌人精灵相互碰撞,并确保它们不会相互移动。

所有敌方精灵都跟随玩家。

MainGame.cpp

遍历向量中的每个敌人并进行更新循环:

for (auto &enemyMobsObj : this->enemyMobs)
        {

            enemyMobsObj->Update(tickTotal, tickDelta, timeTotal, timeDelta, windowBounds, this->ship, this->firstBoss,
                this->enemyMobs, this->bullets, this->missiles, NULL, "NULL", "NULL");
        }

这是我之前尝试阻止每个精灵相互移动的方法:

EnemyMobOne::更新:

int nextEnemy;

    for (int i = 0; i < enemyMobOne.size(); i++)
    {
        nextEnemy = i + 1;
        if (nextEnemy < enemyMobOne.size())
        {
            //Deal with mobs collision
            if (enemyMobOne[i].boundingBox.IntersectsWith(enemyMobOne[nextEnemy].boundingBox))
            {
                enemyMobOne[i].position.x = enemyMobOne[nextEnemy].position.x - enemyMobOne[i].boundingBox.Width;
            }
        }
    }   

然而这让每个敌方精灵明显相互粘连,看起来不太对劲,也让他们瞬移。

有人知道阻止它们相互移动的正确代码吗?谢谢。

【问题讨论】:

  • 我想当你真正尝试将敌人移向玩家时,最好进行碰撞检查。这样,当它们发生碰撞时,它们只会停留在原地。您的解决方案将敌人置于一个与其上一个位置无关的新位置。此外,如果您在碰撞检查中移动了一个敌人,您将不得不再次检查所有其他碰撞,您可能通过移动敌人创建了一个新的碰撞。这可能导致无限的碰撞。因此,阻止敌人移动要比在敌人移动后重新设置要容易得多。
  • 旁注:this 很少需要。如果这是您的编程风格,并且这样对您来说更容易,那很好。但通常您不需要在每个成员前面指定this。它使代码比它必须的要长得多。
  • 所以你的意思是当他们碰撞时,阻止敌人的精灵移动?我试过这个,但问题是我需要精灵始终跟随玩家(我游戏的主要部分)。我现在也确实使用 m_ 而不是 this->。我是 C++ 新手,所以这就是我使用 this->. 的原因
  • 我不是游戏编程方面的专家,也许其他人有更好的想法。但是当发生碰撞时你想做什么?您不希望它们彼此重叠,因此可能会出现敌人无法移动的情况,因为此时有障碍物阻挡了它。除了完全阻止它们移动之外,您还可以尝试将它们移动到尽可能靠近下一个碰撞的敌人的位置。我在这里看到的主要问题是你总是将enemy[i] 移动到enemy[nextEnemy] 的左侧,但是你怎么知道碰撞发生时enemy[i] 在哪一侧?

标签: c++ collision


【解决方案1】:

当您检测到两个碰撞对象之间的交叉点时,您需要决定如何抵消重叠(我相信您已经知道了)。但是,如何做到这一点比简单地将它们“推”到一侧(正如您在代码中所做的那样)有点棘手。可以这么说,您可能想要做的是对施加的力产生反作用力。基本上,您想要计算最小平移,或需要最少移动量的方向,以使至少一个盒子移出另一个盒子。

这比简单地“把我放在另一个人的右边(或左边,取决于你如何设置坐标,我想)”要复杂一些,这或多或少是你的代码所做的,现在。

对于一个简单的解决方案,只需检查其中一个碰撞器是否更靠近另一个碰撞器的左侧、右侧、顶部或底部。为此,您可以简单地获取碰撞交点位置并检查该点与相对于其中一个碰撞器的最小和最大 x 和 y 坐标之间的相对距离,然后相应地移动一个或两个精灵。

例如: [编辑] 在查看了我之前的答案后,我意识到您需要计算框的重叠,这样可以更轻松地完成这一切:

float minX = min(sprite0.boundingBox.maxX, sprite1.boundingBox.maxX);// Minimum of the boxes' right-side points (top right and bottom right) x coordinates
float minY = min(sprite0.boundingBox.maxY, sprite1.boundingBox.maxY);// Minimum of the boxes' top-side points (top left and top right) y coordinates

float maxX = max(sprite0.boundingBox.minX, sprite1.boundingBox.minX);// Maximum of the boxes' left-side points (top left and bottom left) x coordinates
float maxY = max(sprite0.boundingBox.minY, sprite1.boundingBox.minY);// Maximum of the boxes' bottom-side points (bottom left and bottom right) y coordinates

float distHoriz = minX - maxX;// The horizontal intersection distance
float distVert = minY - maxY;// The vertical instersection distance

// If the boxes are overlapping less on the horizontal axis than the vertical axis,
// move one of the sprites (in this case, sprite0) in the opposite direction of the
// x-axis overlap
if(abs(distHoriz) < abs(distVert))
{
    sprite0.x -= distHoriz;
}
// Else, move one of the sprites (again, I just decided to use sprite0 here,
// arbitrarily) in the opposite direction of the y-axis overlap
else
{
    sprite0.y -= distVert;
}

为了进一步澄清(除了 cmets),我们在这里所做的基本上是检查重叠线之间的距离。例如:

Box 0 x-axis  xmin0|------------------|xmax0
Box 1 x-axis                xmin1|----------------------|xmax1
                                 |----|<-- Overlap (xmax0 - xmin1)

请注意,用于重叠的两个边界框的最小值是两个最小值(xmin0 和 xmin1)中的最大值,用于重叠的最大值是两个最大值(xmax0 和xmax1).

y 轴计算的工作方式完全相同。一旦我们有了两个轴,我们只需检查哪个轴的绝对值较低(哪个距离更短)并沿着该距离移动以抵消交叉点。

【讨论】:

  • 你确定这段代码是正确的吗?我最初将enemyMob[0] .x 设置为500,将.y 设置为200,将enemyMob[1] .x 设置为800,将.y 设置为200,并且enemyMob[1] 只是在没有相交的情况下飞过。这是我的代码,因为我无法在 cmets 中发布代码,boundingBox.Width 是作为 X co 的精灵的宽度。在左上角:pastebin.com/fTLsiU6d
  • 我很肯定它会起作用,只要你在我使用的伪代码中拥有与那些方法/函数相当的东西。如果它们是轴对齐的,那将是最简单的(最简单的意思是您不需要重新计算边界框上的最大/最小位置)。为了清楚起见,我将添加更多细节。
  • 诚然,我确实需要再做一次我弄混的小修正,即最小-最大交易。您需要从两个最大值的最小值中减去两个最小值中的最大值(查看答案以获得更详细的解释)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
相关资源
最近更新 更多