【问题标题】:Problem detecing window border collision in SFML在 SFML 中检测窗口边界冲突的问题
【发布时间】:2021-06-03 21:11:03
【问题描述】:

我试图让我的移动矩形在与它们碰撞时从窗口边框反弹,但是矩形正在旋转。我不确定如何定义我的碰撞函数,这就是我想出的:

//left border collision
     if(rectangle.getPosition().y<0){
         rectangle.setPosition(rectangle.getPosition().x,0);
     //top border collision
     };
     if(rectangle.getPosition().x<0){
         rectangle.setPosition(0,rectangle.getPosition().y);
     };
     //right border collision
     if(rectangle.getPosition().y+rectangle.getGlobalBounds().width>WINDOW_W){
         rectangle.setPosition(rectangle.getPosition().y,WINDOW_W-rectangle.getGlobalBounds().width);
     };
     //bottom border collision
     if(rectangle.getPosition().x+rectangle.getGlobalBounds().height>WINDOW_H){
         rectangle.setPosition(WINDOW_H-rectangle.getGlobalBounds().height,rectangle.getPosition().y);
     };

代码检测到一些碰撞,但我认为它没有考虑矩形的旋转。

这是我的全部代码:

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

int main() {
    // create the window
    sf::RenderWindow window(sf::VideoMode(800, 600), "My window");

    // create some shapes
    sf::CircleShape circle(100.0);
    circle.setPosition(100.0, 300.0);
    circle.setFillColor(sf::Color(100, 250, 50));

    sf::RectangleShape rectangle(sf::Vector2f(120.0, 60.0));
    rectangle.setPosition(500.0, 400.0);
    rectangle.setFillColor(sf::Color(100, 50, 250));

    sf::ConvexShape triangle;
    triangle.setPointCount(3);
    triangle.setPoint(0, sf::Vector2f(0.0, 0.0));
    triangle.setPoint(1, sf::Vector2f(0.0, 100.0));
    triangle.setPoint(2, sf::Vector2f(140.0, 40.0));
    triangle.setOutlineColor(sf::Color::Red);
    triangle.setOutlineThickness(5);
    triangle.setPosition(600.0, 100.0);

    //clock function
    sf::Clock clock;

    //finding screen resolutions for collision
    int WINDOW_W = window.getSize().y;
    int WINDOW_H = window.getSize().x;

    //declaring moving speeds for the rectangle
    float rec_vel_x = 50;
    float rec_vel_y = 150;
    //delcaring speed of rotation of the rectangle
    float rec_ang_vel = 10;


    // run the program as long as the window is open
    while (window.isOpen()) {
        //Time elapsed function
         sf::Time elapsed = clock.getElapsedTime();
         // getting elapsed time as float, needed fro the float function
         float el1 = clock.restart().asSeconds();
        // check all the window's events that were triggered since the last iteration of the loop
        sf::Event event;
        while (window.pollEvent(event)) {
            // "close requested" event: we close the window
            if (event.type == sf::Event::Closed)
                window.close();
        }
        // clear the window with black color
        window.clear(sf::Color::Black);
        // moving the rectangle per each elapsed second with the preset values
        rectangle.move(el1*rec_vel_x,el1*rec_vel_y);
        //rotating the rectangle
        rectangle.rotate(el1*rec_ang_vel);


        // draw everything here...
        window.draw(circle);
        window.draw(rectangle);
        window.draw(triangle);

        // end the current frame
        window.display();
        //game updates
         std::cout<<elapsed.asSeconds()<<std::endl;
         //extracting values for the collision
         //sf::FloatRect rectangle_bounds = rectangle.getGlobalBounds();
         //left border collision
         if(rectangle.getPosition().y<0){
             rectangle.setPosition(rectangle.getPosition().x,0);
         //top border collision
         };
         if(rectangle.getPosition().x<0){
             rectangle.setPosition(0,rectangle.getPosition().y);
         };
         //right border collision
         if(rectangle.getPosition().y+rectangle.getGlobalBounds().width>WINDOW_W){
             rectangle.setPosition(rectangle.getPosition().y,WINDOW_W-rectangle.getGlobalBounds().width);
         };
         //bottom border collision
         if(rectangle.getPosition().x+rectangle.getGlobalBounds().height>WINDOW_H){
             rectangle.setPosition(WINDOW_H-rectangle.getGlobalBounds().height,rectangle.getPosition().y);
         };
    }
    sf::FloatRect rectangle_bounds = rectangle.getGlobalBounds();
    std::cout << rectangle_bounds.top << " " << rectangle_bounds.left << " " ;
    std::cout << rectangle_bounds.width << " " << rectangle_bounds.height << std::endl;
    std::cout <<"wysokosc okna to: " << WINDOW_H << std::endl;
    std::cout <<"szerokosc okna to: " << WINDOW_W << std::endl;
    return 0;
}

我还没有实现弹跳,现在我希望矩形不要超出窗口

【问题讨论】:

    标签: c++ collision-detection sfml collision


    【解决方案1】:

    您在某些地方交换了 xs 和 ys,请记住 setPosition()getPosition() 先取 x 再取 y。

    这里是固定代码:

    //left border collision
    if(rectangle.getPosition().x<0){
         rectangle.setPosition(0,rectangle.getPosition().y);
    };
    
    //top border collision
    if(rectangle.getPosition().y<0){
         rectangle.setPosition(rectangle.getPosition().x, 0);
    };
    
    //right border collision
    if(rectangle.getPosition().x+rectangle.getGlobalBounds().width>WINDOW_W){
         rectangle.setPosition(WINDOW_W-rectangle.getGlobalBounds().width, rectangle.getPosition().y);
    };
    
    //bottom border collision
    if(rectangle.getPosition().y+rectangle.getGlobalBounds().height>WINDOW_H){
         rectangle.setPosition(rectangle.getPosition().x, WINDOW_H-rectangle.getGlobalBounds().height);
    };
    

    上下边框在 y 轴上停止矩形,因此当它碰到它们时我们改变 y。左右手边界的情况类似:x 坐标应设置而 y 保持不变。

    显然,WINDOW_HWINDOW_W 也被交换了,应该是:

    //finding screen resolutions for collision
    int WINDOW_W = window.getSize().x;
    int WINDOW_H = window.getSize().y;
    

    编辑:修正了语法错误并添加了一个关于 WINDOW_H 的词。

    【讨论】:

    • 我明白了,谢谢你,但是碰撞仍然不会被检测到并且矩形会超出我的窗口,你有什么解决方案吗?
    • WINDOW_HWINDOW_W 也有可能被交换。请记住,宽度对应于 x 轴,高度对应于 y 轴。
    • 这似乎已经修复了顶部和底部边框的冲突,但是左右边框似乎都向左移动了几个单位。
    • 我没有看到任何其他纯粹的数学错误,所以我猜原因可能是您的矩形按顺序操作:移动-->渲染-->更新窗口。所以每一帧首先你的矩形超出窗口,然后它被渲染在这个“错误”的位置,然后才被纠正(在循环结束时)。解决方案是首先处理所有更正(更新),然后将内容呈现到窗口。
    • 另一件事可能是旋转矩形的边界框始终与轴对齐。这意味着当矩形的左上角顺时针旋转时,它将不再是最左边的角,并且它的边界框将根据变换而改变。我强烈推荐阅读SFML documentation
    猜你喜欢
    • 2016-02-08
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    相关资源
    最近更新 更多