使用 Box2D 的 Raycast 进行激光镜像

问题描述

在我正在编写的游戏中,我想借助从 b2RayCastCallback 继承的类来实现 Box2d 的激光。 我有一个方形盒子,里面有一个对角镜,我希望激光从镜子返回一个与原始光束成 45 度方向的新激光束。

添加一个大小和角度都合适的对角线夹具,但仍然效果不佳。 有时是激光工作,有时是因为镜子损坏角度错误而重新光束,有时会得到想要的结果。

我该怎么办?

    b2polygonShape polygonShape;
    b2FixtureDef myFixtureDef;
    myFixtureDef.shape = &polygonShape;
    myFixtureDef.density = 1;
    myFixtureDef.friction = 2.5f;
    myFixtureDef.isSensor = true;
    polygonShape.SetAsBox((CELL_DIMENSIONS.x * HALF_RATIO * EIGHTH_RATIO) / PIXEL_METER_RATIO,CELL_DIMENSIONS.y / PIXEL_METER_RATIO,b2Vec2(0,0),-((b2_pi /180)* 45));
    b2Fixture* mirrorFixture = getBody()->CreateFixture(&myFixtureDef);
    mirrorFixture->SetUserData((void*)2);

///////////////////////////////////////////////////////////////////////////////////////////////
class RaysCastCallback : public b2RayCastCallback
{
public:
    RaysCastCallback() : m_fixture(NULL),m_fraction(0){}
    
    virtual float ReportFixture(b2Fixture* fixture,const b2Vec2& point,const b2Vec2& normal,float fraction) override
    {        
        m_fixture = fixture;
        m_point = point;
        m_normal = normal;
        m_fraction = fraction;

        if (m_fixture)
        {
            if (auto body = m_fixture->GetBody())
            {
                auto object = static_cast<GameObject*>(body->GetUserData());

                if ((object->getobjectType() == object::mirrorBox && int(m_fixture->GetUserData()) != 2) ||
                    (object->getobjectType() == object::gate && m_fixture->IsSensor()))
                {
                    m_fraction = -1;
                }
            }
        }

        return m_fraction;     
    }    

    b2Fixture* m_fixture;    
    b2Vec2 m_point;    
    b2Vec2 m_normal;    
    float m_fraction;
};

////////////////////////////////////////////////////////////////////////////////////////

void LaserSource::laserRayCast(b2Vec2 p1,b2Vec2 p2,b2World& world)
{
    sf::VertexArray laserRay(sf::Lines,2);
    sf::VertexArray laserRayGlow(sf::Quads,4);

    laserRay[0].color = sf::Color::Yellow;
    laserRay[1].color = sf::Color::Yellow;

    laserRayGlow[0].color = sf::Color(255,255,60);
    laserRayGlow[1].color = sf::Color(255,60);
    laserRayGlow[2].color = sf::Color(255,60);
    laserRayGlow[3].color = sf::Color(255,60);

    RaysCastCallback callback;
    world.RayCast(&callback,p1,p2);
    if (callback.m_fixture)
    {
        laserRay[0].position = sf::Vector2f(p1.x * PIXEL_METER_RATIO,p1.y * PIXEL_METER_RATIO);
        laserRay[1].position = sf::Vector2f(callback.m_point.x * PIXEL_METER_RATIO,callback.m_point.y * PIXEL_METER_RATIO);

        laserRayGlow[0].position = sf::Vector2f(p1.x * PIXEL_METER_RATIO,(p1.y * PIXEL_METER_RATIO) - DIFF);
        laserRayGlow[1].position = sf::Vector2f(callback.m_point.x * PIXEL_METER_RATIO,(callback.m_point.y * PIXEL_METER_RATIO) - DIFF);
        laserRayGlow[2].position = sf::Vector2f(callback.m_point.x * PIXEL_METER_RATIO,(callback.m_point.y * PIXEL_METER_RATIO) + DIFF);
        laserRayGlow[3].position = sf::Vector2f(p1.x * PIXEL_METER_RATIO,(p1.y * PIXEL_METER_RATIO) + DIFF);
    }

    m_laserRay.emplace_back(laserRay);
    m_laserRayGlow.emplace_back(laserRayGlow);

    if (callback.m_fixture)
    {
        auto object = static_cast<GameObject*>(callback.m_fixture->GetBody()->GetUserData());
        if (object->getobjectType() == object::laserDestination)
        {
            auto laserDestination = static_cast<LaserDestination*>(object);
            laserDestination->activateControlledobject();
        }


        if (object->getobjectType() == object::mirrorBox)
        {
            b2Vec2 remainingRay = (p2 - callback.m_point);
            b2Vec2 projectedOntonormal = b2Dot(remainingRay,callback.m_normal) * callback.m_normal;
            b2Vec2 nextp2 = p2 - 2 * projectedOntonormal;
            laserRayCast(callback.m_point,nextp2,world);
        }
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)