【问题标题】:(Boolean/SFML) How do I create a boolean that checks collision?(布尔值/SFML)如何创建一个检查碰撞的布尔值?
【发布时间】:2019-04-27 13:10:59
【问题描述】:

所以我最近进入了 SFML 编程,我需要帮助创建一个布尔值来检查两个矩形是否发生碰撞或相互重叠。

这是目前的代码:

     bool collision(sf::Rect rect, sf::Rect rect2){
            return rect.getGlobalBounds().intersects(rect2.getGlobalBounds());
     }

我收到以下错误:

  • “rect”之前缺少模板参数
  • “rect2”之前缺少模板参数
  • ')' 标记之前的预期主表达式

我正在制作平台游戏,但找不到测试玩家与世界之间碰撞的有效方法。

这是我想为这个简单程序编写的代码:

if(collision(rectangle1,rectangle2)){
std::cout << "collision" << std::endl;
}

感谢任何帮助! :)

这是我的代码:

#include <SFML/Graphics.hpp>
#include <SFML/Window/Keyboard.hpp>
#include <SFML/Graphics/Rect.hpp>

int main(){
    sf::RenderWindow window(sf::VideoMode(800,600),"INSERT_WINDOW_TITLE", sf::Style::Titlebar | sf::Style::Close);
    sf::RectangleShape rect1(sf::Vector2f(20.f,20.f));
    rect1.setFillColor(sf::Color::Blue);
    sf::RectangleShape rect2(sf::Vector2f(20.f,20.f));
    rect2.setFillColor(sf::Color::Green);

    bool collision(sf::FloatRect r1, sf::FloatRect r2)
    {
        return r1.intersects(r2, sf::FloatRect());
    }

    while(window.isOpen()){
        sf::Event event;

        while(window.pollEvent(event)){
             if (event.type == sf::Event::Closed)
                window.close();
        }
        if(sf::Keyboard::isKeyPressed(sf::KeyBoard::W) && collision(rect1,rect2) == false) rect1.move(0.f,-1.f);
        if(sf::Keyboard::isKeyPressed(sf::KeyBoard::S) && collision(rect1,rect2) == false) rect1.move(0.f,1.f);
        if(sf::Keyboard::isKeyPressed(sf::KeyBoard::A) && collision(rect1,rect2) == false) rect1.move(-1.f,0.f);
        if(sf::Keyboard::isKeyPressed(sf::KeyBoard::D) && collision(rect1,rect2) == false) rect1.move(1.f,0.f);

        window.draw(rect1);
        window.draw(rect2);
        window.display();
    }
}

【问题讨论】:

  • sf::Rect 是一个模板,所以你需要指定它保存的数据类型。例如sf::Rect&lt;float&gt;.

标签: c++ graphics boolean sfml


【解决方案1】:

Rect 是一个类模板,而不是一个实际的类。有预定义的typedefs,分别称为IntRectFloatRect,分别对应Rect&lt;int&gt;Rect&lt;float&gt;。您想使用其中之一:

bool collision(sf::FloatRect r1, sf::FloatRect r2)
{
    sf::FloatRect intersection;
    return r1.intersects(r2, intersection);
}

更新:

这是您的代码的“固定”版本。我添加了一个重载,它采用Shapes 并转发到Rect 碰撞检查函数。我还重新定位了您的 rect2 矩形;否则你不能移动,因为你已经发生了碰撞。

#include <SFML/Graphics.hpp>
#include <SFML/Window/Keyboard.hpp>

    bool collision(sf::FloatRect r1, sf::FloatRect r2)
    {
        sf::FloatRect intersection;
        return r1.intersects(r2, intersection);
    }

bool collision(sf::Shape const & r1, sf::Shape const & r2)
{
    return collision(r1.getGlobalBounds(), r2.getGlobalBounds());
}

int main(){
    sf::RenderWindow window(sf::VideoMode(800,600),"INSERT_WINDOW_TITLE", sf::Style::Titlebar | sf::Style::Close);
    sf::RectangleShape rect1(sf::Vector2f(20.f,20.f));
    rect1.setFillColor(sf::Color::Blue);
    sf::RectangleShape rect2(sf::Vector2f(20.f,20.f));
    rect2.setFillColor(sf::Color::Green);
    rect2.setPosition(100.f, 100.f);

    while(window.isOpen()){
        sf::Event event;

        while(window.pollEvent(event)){
             if (event.type == sf::Event::Closed)
                window.close();
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::W) && collision(rect1,rect2) == false) rect1.move(0.f,-1.f);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::S) && collision(rect1,rect2) == false) rect1.move(0.f,1.f);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::A) && collision(rect1,rect2) == false) rect1.move(-1.f,0.f);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::D) && collision(rect1,rect2) == false) rect1.move(1.f,0.f);

        window.clear();
        window.draw(rect1);
        window.draw(rect2);
        window.display();
    }
}

请注意,这里还有其他问题;例如您的游戏循环现在尽可能快地运行,这可能不是您想要的。不过,这段代码确实可以运行。

【讨论】:

  • 那行不通。我尝试使用它,但收到一个错误:在 '{' token 之前不允许函数定义
  • 这意味着你的代码结构混乱了。尝试发布或链接到完整的文件...
  • 您能否提供一个示例,包括一个 if 语句来说明它是如何使用的?以 rect1 和 rect2 为例,或者类似的。
  • 您的代码有几个问题。首先,你不能在另一个函数中声明一个函数,除非使用 lambdas。如果将collision 的定义移出main 可以解决that 错误。但这仍然行不通,因为您实际上没有要比较的sf::Rects,而是有sf::RectangleShapes,这是非常不同的。您可以通过在您的形状上调用getGlobalBounds() 来获得所需的Rects。最后,您需要先重新定位其中一个矩形(在同一位置绘制它们),并且在绘制它们之前需要调用window.clear()
  • 有趣的是,您的原始代码几乎是正确的。您应该使用RectangleShape 类型的参数而不是Rect。这就是为什么您应该始终发布minimal, complete, and verifiable example 的原因。
猜你喜欢
  • 2022-01-17
  • 2010-09-25
  • 2017-01-22
  • 2016-10-05
  • 2021-10-06
  • 2022-07-13
  • 1970-01-01
  • 1970-01-01
  • 2022-01-28
相关资源
最近更新 更多