SFML中的碰撞检测效果不太好,如何改进?

3

最近我一直在使用C++和SFML的最新版本开发一个简单的游戏,但我遇到了一个问题,就是碰撞检测不太好,例如即使敌人还没有碰到玩家,但只是靠近他,玩家也会死亡。下面是玩家类的代码,其中包括移动函数和碰撞检测代码以及敌人类的移动:

`class PlayerA : public CircleShape { public:

    //Constructor:
    PlayerA(float xposition, float yposition, float radius, float s)
    {
        setRadius(radius);
        setFillColor(Color::Yellow);
        setOutlineColor(Color(00,80,00));
        setOutlineThickness(-2);
        setPointCount(3);
        setSpeed(s);
        setPosition(xposition,yposition);
    }

    //Movements of the player:
    void up()
    {
        move(0,-10*speed);
    }
    void down()
    {
        move(0,10*speed);
    }
    void right()
    {
        move(10*speed,0);
    }
    void left()
    {
        move(-10*speed,0);
    }
     void checkA(ObsA *obs1=NULL,ObsA *obs2=NULL, ObsA *obs3=NULL, ObsA *obs4=NULL, ObsA *obs5=NULL)
    {
        if(obs2==NULL)
        {
            if(getGlobalBounds().intersects(obs1->getGlobalBounds()))
            {
                relevel();
            }
        }
     private:
      float speed=0.00;

    void obs()
    {
        if(speed > 0)
        {
                rotate(0.5*speed);
        }
        else
        {
                rotate(0.5*speed);
        }
    }


private:
    float speed = 0.00;


    void obs()
    {
        if(speed > 0)
        {
                rotate(0.5*speed);
        }
        else
        {
                rotate(0.5*speed);
        }
    }


private:
    float speed = 0.00;

代码有问题吗?如何解决这个问题,谢谢!


3
可能是 SFML Bounding Box Collision Detection 的重复内容。 - Conduit
3个回答

6
intersects函数只是检查两个矩形是否相交。如果您想在SFML中进行像素完美的碰撞检测,则需要自己编写代码。
基本上,从intersects开始,如果返回true,则获取相交的矩形,并检查原始矩形中任何一个像素区域是否包含重叠的相关像素。

谢谢!我认为那是最好的。 - QApps

3
您可以使用此功能来执行更好的碰撞检测。它是基本的,但效果很好。
bool circleTest(const sf::Sprite &first, const sf::Sprite &second)
{
    sf::Vector2f firstRect(first.getTextureRect().width, first.getTextureRect().height);
    firstRect.x *= first.getScale().x;
    firstRect.y *= first.getScale().y;

    sf::Vector2f secondRect(second.getTextureRect().width, second.getTextureRect().height);
    secondRect.x *= second.getScale().x;
    secondRect.y *= second.getScale().y;

    float r1 = (firstRect.x + firstRect.y) / 4;
    float r2 = (secondRect.x + secondRect.y) / 4;
    float xd = first.getPosition().x - second.getPosition().x;
    float yd = first.getPosition().y - second.getPosition().y;

    return std::sqrt(xd * xd + yd * yd) <= r1 + r2;
}

不要对一个方向进行平方根运算,而应该对另一个方向进行平方运算。这样可以提高运行速度,并且得到相同的结果。我也不认为这种方法更好,只是不同而已。它仍然不能完全精确(这可能重要也可能不重要),并且比轴对齐边界框相交测试慢得多。 - Merlyn Morgan-Graham

0

你在使用圆形吗?如果我没记错的话,圆形将会有一个矩形的碰撞框。如果是这样的话,那么你可能会在看不见的矩形角落之间发生碰撞。

如果你正在使用圆形,也许可以将类更改为正方形矩形,看看碰撞是否能够正确工作。或者尝试直接在x或y轴上测试碰撞,让它们沿着一条直线相互移动,只改变1个轴。(圆的边缘将与左、右、上和下部分的矩形边缘相同)。

如果你需要更好的圆形碰撞,SFML中可能已经内置了一个。但我认为,使用你两个圆的半径、两个对象的中心以及中心之间的角度斜边编写自己的逻辑并不会太麻烦。

根据Merlyn Morgan-Graham的评论进行编辑。


是的,你说得对,我会尝试一下。谢谢你的帮助! - QApps
1
“中心点之间的夹角”。我建议使用由中心点形成的直角三角形的斜边长度,并将其与半径1 + 半径2进行比较,而不是尝试在角度上进行投影。这是您想要的吗?(如果我过于追求精确,对不起) - Merlyn Morgan-Graham

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