0
\$\begingroup\$

I ported simple Box2d Explosion simulation the function is called once when there is some event with the "Truck Car"
the problem is that the Explosion working fine but it looks like when the explosion done the "parts" of the car Returning to
the initial car position instead of bean scatter on the floor.
what am i doing wrong here ?

here is the code for the Explosion

class MyQueryCallback : public b2QueryCallback {
public:
    std::vector<b2Body*> foundBodies;

    bool ReportFixture(b2Fixture* fixture) {
        foundBodies.push_back(fixture->GetBody());
        return true;//keep going to find all fixtures in the query area
    }
};
void BackgroundSprite::explode()
{
        float m_blastRadius = 40.0f;
        float m_blastPower = 50.5f;
        MyQueryCallback queryCallback;
        b2Vec2 locationPnt = _truck->truckBody->GetPosition();
        b2AABB aabb;
        aabb.lowerBound.Set((locationPnt.x - m_blastRadius), (locationPnt.y - m_blastRadius));
        aabb.upperBound.Set((locationPnt.x + m_blastRadius), (locationPnt.y + m_blastRadius));
        m_world->QueryAABB(&queryCallback, aabb);

        for (int i = 0; i < queryCallback.foundBodies.size(); i++) {
            b2Body* pBody = queryCallback.foundBodies.at(i);
            b2Vec2 pBodyPos = pBody->GetWorldCenter();
            b2Vec2 pHitVector(pBodyPos.x - locationPnt.x, pBodyPos.y - locationPnt.y);
            float radDist = pHitVector.Normalize();
            radDist = (radDist * PTM_RATIO);
            if ((pBody->GetType() == b2_dynamicBody) == (radDist <= m_blastRadius)){

                float nHitForce = ((m_blastRadius - radDist) / m_blastRadius) * m_blastPower;
                b2Vec2 appForce(pHitVector.x*nHitForce, pHitVector.y*nHitForce);
                pBody->ApplyLinearImpulse(appForce, pBody->GetWorldCenter(),true);
            }
        }
 }

see what i mean in the video at 3:30 https://www.youtube.com/watch?v=3JmimxLiTpo

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

It doesn't matter what forces you apply, explicitly or implicitly to the joined bodies, the joints will always attempt to restore the relative position/angle of the joined bodies in accordance with the joint type. There are only three ways I can think of for which a joint will stop functioning:

  1. The joint is explicitly destroyed using b2World::DestroyJoint
  2. One of the bodies is destroyed using b2World::DestroyBody which destroys all connected joints automatically.
  3. At least one of the bodies is deactivated by passing a false argument to the b2Body::SetActive function. All connected joints are implicitly deactivated. The joint is reactivated when both bodies are again active.

I recommend option 1, unless you have some special reason to do otherwise:

    /* ... */

    void BackgroundSprite::explode()
    {
        /* ... */

        for (int i = 0; i < queryCallback.foundBodies.size(); i++) {
            b2Body* pBody = queryCallback.foundBodies.at(i);

            /* ... */

            b2JointEdge* jointEdge = pBody->GetJointList();
            while(jointEdge) {
                b2Joint* joint = jointEdge->joint
                jointEdge = jointEdge->next;
                m_world->DestroyJoint(joint);
            }
        }
    }

What you may want to do is destroy the joints when a threshold force is exceeded. For those cases, you need to check the forces exerted by every joint on every iteration to determine which (if any) joints need to be destroyed.

\$\endgroup\$
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .