c++sfmlbox2d

cannot convert from 'b2BodyUserData' to 'sf::Shape *'


i had combine sfml and box2d. but i have an error in the source code. in this code sf::Shape* shape = static_cast<sf::Shape*>(body->GetUserData()); how to convert from b2bodyuserdata to sf::shape??

and this code delete static_cast<sf::RectangleShape*>(body->GetUserData()); how to convert from b2bodyuserdata to sf::rectangle??

i expect to run this program successfuly.

this the source code

converter.h

namespace converter
    {
        constexpr double PIXELS_PER_METERS = 32.0;
        constexpr double PI = 3.14159265358979323846;

        template<typename T>
        constexpr T pixel_to_meters(const T& x)
        {
            return x/PIXELS_PER_METERS;
        };

        template<typename T>
        constexpr T meters_to_pixels(const T& x)
        {
            return x*PIXELS_PER_METERS;
        };

        template<typename T>
        constexpr T deg_to_rad(const T& x)
        {
            return PI*x/180.0;
        };

        template<typename T>
        constexpr T rad_to_deg(const T& x)
        {
            return 180.0*x/PI;
        }
    }

main.cpp

#include "converter.hpp"
#include <Box2D/Box2D.h>
#include <SFML/Graphics.hpp>

#include <list>
b2Body* create_box(b2World& world,int pos_x,int pos_y, int size_x,int size_y,b2BodyType type = b2_dynamicBody)
    {
        b2BodyDef bodyDef;
        bodyDef.position.Set(converter::pixel_to_meters<double>(pos_x),converter::pixel_to_meters<double>(pos_y));
        bodyDef.type = type;


        b2PolygonShape b2shape;
        b2shape.SetAsBox(converter::pixel_to_meters<double>(size_x/2.0),converter::pixel_to_meters<double>(size_y/2.0));

        b2FixtureDef fixtureDef;
        fixtureDef.density = 1.0;
        fixtureDef.friction = 0.4;
        fixtureDef.restitution= 0.5;
        fixtureDef.shape = &b2shape;

        b2Body* res = world.CreateBody(&bodyDef);
        res->CreateFixture(&fixtureDef);

        sf::Shape* shape = new sf::RectangleShape(sf::Vector2f(size_x,size_y));
        shape->setOrigin(size_x/2.0,size_y/2.0);
        shape->setPosition(sf::Vector2f(pos_x,pos_y));

        if(type == b2_dynamicBody)
            shape->setFillColor(sf::Color::Blue);
        else
            shape->setFillColor(sf::Color::White);
        
        //deprected
        //res->SetUserData(shape);
        res->GetUserData().pointer = (uintptr_t)shape;

        return res;
    }

    void display_world(b2World& world,sf::RenderWindow& render)
    {
        world.Step(1.0/60,int32(8),int32(3));

        render.clear();

        for (b2Body* body=world.GetBodyList(); body!=nullptr; body=body->GetNext())
        {   
            sf::Shape* shape = static_cast<sf::Shape*>(body->GetUserData());
            shape->setPosition(converter::meters_to_pixels(body->GetPosition().x),converter::meters_to_pixels(body->GetPosition().y));
            shape->setRotation(converter::rad_to_deg<double>(body->GetAngle()));
            render.draw(*shape);
        }

        render.display();
    }


int main(int argc,char* argv[])
{
    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "04_Basic");
    window.setFramerateLimit(60);

    b2Vec2 gravity(0.f, 9.8f);
    b2World world(gravity);

    std::list<b2Body*> bodies;

    bodies.emplace_back(book::create_box(world,400,590,800,20,b2_staticBody));


    while(window.isOpen())
    {
        sf::Event event;
        while(window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)//Close window
                window.close();
        }
        if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
        {
            int x = sf::Mouse::getPosition(window).x;
            int y = sf::Mouse::getPosition(window).y;
            bodies.emplace_back(book::create_box(world,x,y,32,32));
        }
        book::display_world(world,window);
    }

    for(b2Body* body : bodies)
    {
        delete static_cast<sf::RectangleShape*>(body->GetUserData());
        world.DestroyBody(body);
    }

    return 0;
}



Solution

  • GetUserData() returns a reference to a b2BodyUserData, which is a struct with a single pointer member. So the two lines you mention should be:

    sf::Shape* shape = reinterpret_cast<sf::Shape*>(body->GetUserData().pointer);
    

    and

    delete reinterpret_cast<sf::RectangleShape*>(body->GetUserData().pointer);