Баг в Box2D или неверный поворот объекта

145
24 сентября 2019, 20:50

Пишу приложение которое визуализирует физику используя Box2D.
Объект в виде квадрата перемещается по клику мыши.
Отскоки и изменение поворота при ударах об стенки нормально работает, всё хорошо.
Сделал препятствие и тут увидел, при падении с края препятствия, объект крутится неверно. Ну я думал это с SFML проблема, мол поворачивает не в ту сторону, но увы, проблема в движке, он неверно поворачивает объект.
Вот, залил 2 видео на YouTube, вот они.
Первое видео
Второе видео
На первом видео показывается как всё происходит.
На втором видео, в консоли, когда я останавливаю вывод консоли, видно что в строке Engine, третий параметр которой отображает угол фигуры всегда увеличивается, а должен падать, это проблема движка. Как решать эту проблему?

Код:

#include <iostream>
#include <SFML/Graphics.hpp>
#include <Box2D/Box2D.h>
#include <Windows.h>
using namespace std;
using namespace sf;
float Radians2Degrees(float Radians)
{
    return ((Radians / b2_pi) * 180.0f);
}
float Degress2Radians(float Degrees)
{
    return ((Degrees * b2_pi) / 180.0);
}
int main()
{
    RenderWindow window(VideoMode(800, 600), "Box2D + SFML");
    sf::View view;
    view.setCenter(sf::Vector2f(0.0f, -300.0f));
    view.setSize(800, 600);
    window.setView(view);
    window.clear(Color::Cyan);
    RectangleShape rect;
    rect.setOrigin(25, 25);
    rect.setFillColor(Color::Black);
    rect.setSize(Vector2f(50, 50));
    rect.setPosition(Vector2f(0, 0));

    //устанавливаем гравитацию
    b2Vec2 gravity(0.0f, -50.0f);
    //создаём мир
    b2World world(gravity);
    //создаём определение земли
    b2BodyDef groundBodyDef;
    //устанавливаем позицию
    groundBodyDef.position.Set(0.0f, 0.0);
    //создаём тело земли на основе определения
    b2Body* groundBody = world.CreateBody(&groundBodyDef);
    //создаём фигуру земли
    b2PolygonShape groundBox;
    //делаем её прямоугольником и скрепляем тело с фигурой
    groundBox.SetAsBox(600.0f, 0.0f);
    groundBody->CreateFixture(&groundBox, 0.0f);
    //отсчёт идёт сверху внихз, левый верхний угол это (0.0)
    //ставим границы слева снизу и сверху
    {
        b2BodyDef wall;
        b2PolygonShape wallShape;
        //левая стенка
        wall.position.Set(-400.0f, 0.0f);
        b2Body* wallBody = world.CreateBody(&wall);
        wallShape.SetAsBox(0.0f, 600.0f, b2Vec2(0.0f, 0.0f), 0.0);
        wallBody->CreateFixture(&wallShape, 5.0f);
        //правая стенка
        wall.position.Set(400.0f, 0.0f);
        wallBody = world.CreateBody(&wall);
        wallShape.SetAsBox(0.0f, 600.0f, b2Vec2(0.0f, 0.0f), 0.0);
        wallBody->CreateFixture(&wallShape, 5.0f);
        //верхняя стенка
        wall.position.Set(0.0f, 600.0f);
        wallBody = world.CreateBody(&wall);
        wallShape.SetAsBox(800.0f, 0.0f, b2Vec2(0.0f, 0.0f), 0.0);
        wallBody->CreateFixture(&wallShape, 5.0f);
    }
    b2PolygonShape shape;
    shape.SetAsBox(25.0f, 25.0f);
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.angularDamping = 0.3f; //снижение угловой скорости
    bodyDef.position.Set(0.0f, 550.0f);
    bodyDef.angle = Degress2Radians(65.0f); //угол в радианах
    b2Body* body = world.CreateBody(&bodyDef);
    b2FixtureDef fd;
    fd.shape = &shape;
    fd.density = 1.0f; //плотность
    fd.restitution = 0.25f; //упргугость
    fd.friction = 0.4f; //трение
    body->CreateFixture(&fd);
    //привятсвие
        //SFML
        RectangleShape sfmlRect;
        sfmlRect.setFillColor(Color::Green);
        sfmlRect.setSize(Vector2f(400.0f, 100.0f));
        sfmlRect.setPosition(Vector2f(-200.0f, -100.0f));
        //box2d
        b2PolygonShape shapeWall;
        shapeWall.SetAsBox(200.0f, 50.0f);
        b2BodyDef bodyDefWall;
        bodyDefWall.angularDamping = 0.3; //снижение угловой скорости
        bodyDefWall.position.Set(0.0f, 50.0f);
        bodyDefWall.angle = Degress2Radians(0.0f); //угол в радианах
        b2Body* bodyWall = world.CreateBody(&bodyDefWall);
        bodyWall->CreateFixture(&shapeWall, 1.0f);
    while (window.isOpen())
    {
        window.clear(Color::Cyan);
        Event event;
        while (window.pollEvent(event))
        {
            if (event.type == Event::Closed)
                window.close();
        }
        //обработка нажатий
        if (Mouse::isButtonPressed(Mouse::Button::Left))
        {
            Vector2i pixelPos = Mouse::getPosition(window); //забираем координаты курсора
            Vector2f pos = window.mapPixelToCoords(pixelPos); //переводим их в игровые (уходим от коорд окна)
            pos.y = -pos.y; //убираем минус
            if ((pos.x >= -(800 / 2) && pos.x <= (800 / 2)) && ((pos.y >= 0) && (pos.y <= 600))) //проверяем в окне ли они(по y отрицательное)
            {
                if (body->GetLinearVelocity().x == 0 && body->GetLinearVelocity().y == 0)
                    body->SetLinearVelocity(b2Vec2(1, 1));
                b2Vec2 position = body->GetPosition();
                b2Vec2 impulseVector(body->GetPosition().x - pos.x, body->GetPosition().y - pos.y);
                body->ApplyLinearImpulseToCenter(-impulseVector, false);
                //cout << pos.x << " " << pos.y << "\n";
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::J))
        {
            b2Vec2 vel = body->GetLinearVelocity();
            vel.y = 50;
            body->SetLinearVelocity(vel);
        }
        if (Keyboard::isKeyPressed(Keyboard::R))
        {
            if (body->GetLinearVelocity().x == 0 && body->GetLinearVelocity().y == 0)
                body->SetLinearVelocity(b2Vec2(1, 1));
            float32 angle = body->GetAngle();
            body->SetTransform(body->GetPosition(), angle += float32(0.001));
        }
        //позиция и угол
        cout << "Engine:  x - " << body->GetPosition().x << " y - " << body->GetPosition().y << " " << (body->GetAngle() / b2_pi) * 180.0f << "\n";
        cout << "SFML:  x - " << rect.getPosition().x << " y - " << rect.getPosition().y << " " << rect.getRotation() << "\n";
        //cout << body->GetLinearVelocity().x << " " << body->GetLinearVelocity().y << "\n";
        world.Step(0.025f / 60.0f, 6, 2);
        rect.setPosition(Vector2f(body->GetPosition().x, -body->GetPosition().y)); //позиция, 
        //не забываем привести позицию по y в отрицательное значение
        rect.setRotation(Radians2Degrees(body->GetAngle())); //угол в градусах
        window.draw(rect);
        window.draw(sfmlRect);
        window.display();
    }
    return 0;
}
Answer 1

Коробка рисуется с обратным вращением. Оттого и смотрится странно.

rect.setRotation(-Radians2Degrees(body->GetAngle())); //угол в градусах
READ ALSO
Как написать keylogger qt c++? [закрыт]

Как написать keylogger qt c++? [закрыт]

Нужно написать keylogger в qt c++Как это можно сделать? Какие библиотеки нужно подключать?

135
Qt 4.8.2. Qt Crearor выдает ошибки

Qt 4.8.2. Qt Crearor выдает ошибки

начал изучать QtПреподаватель дал готовый код калькулятора на 4

122
Ошибка Qt. Untested Windows version 6.2 detected

Ошибка Qt. Untested Windows version 6.2 detected

Программа пытается запуститься, но не запускаетсяКомпилируется с предупреждением что не тестировалось в Windows 8, но у меня 10

127
Перевод из Java в с++

Перевод из Java в с++

Имеется такой класс:

138