How do I make a body ignore gravity (AndEngine)?

2019-02-24 10:21发布

问题:

I have a sprite (with a body) that bounces around the scene. It needs to be unaffected by gravity, but also able to collide with other bodies on the scene. This means I cannot use a kinematic body. I tried:

body = PhysicsFactory.createCircleBody(mPhysicsWorld, this, BodyType.DynamicBody, PhysicsFactory.createFixtureDef(.5f, .5f, .5f));
        MassData md = new MassData();
        md.mass=0;
        body.setMassData(md);
        mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(this, body, true, true));

with different values for my FixtureDef, but nothing seemed to work. My body still falls to the bottom of the scene and sits there. I saw something about applying an equal and opposite force. If my gravitational force is the earth default and this is a viable option, how exactly would I do it? Or is there a better way to remove this body from the gravitational field and still have it interact with other dynamic bodies?

回答1:

I am not sure what version of Box2D is included in the current version of AndEngine, but you could try body.setGravityScale(0);

If that does not work, you'll have to put this in onUpdate:

body.applyForce(new Vector2(0,-SensorManager.GRAVITY_EARTH), new Vector2(body.getWorldCenter()));


回答2:

Your code is not using Kinematic body, it is using Dynamic. "BodyType.DynamicBody"

You should change that line with something like "BodyType.KinematicBody"

If you apply a force opposed to gravity, your code will do unnecesary steps and will be inefficient.



回答3:

I had a similar issue - I needed a body unaffected by gravity but could still collision detect and resolved it by adding the setGravityScale and getGravityScale to the andengine box 2d extension.

If your using GLES1,

Steven Box2D With SetGravityScale

This is my prebuilt version, contains the .so files and the jar.

Alternatively if you want to do this yourself, these are the steps I took.

I downloaded the Box2D directly v2.2.1 from the Box2D site. I then followed the necessary steps to download the source project for the extension and get it to build,

build-the-examples-and-box2d-extension

I imported the GLES2 branch of the Box2D extension. Make sure you change the paths in the jni\build.sh file to match your workspace and location of the android ndk. This is all explained in the link above.

Next do a top level text search, (in \Box2D\Dynamics) for GravityScale in the Box2D 2.2.1 and locate all of the files that contain this string. Make equivalent changes to the corresponding files in your extension.

The files you need to change are,

  • b2Body.cpp
  • b2Body.h
  • b2Island.cpp

Although most changes are identical, one minor difference is in Box2D\Dynamics\b2Island.cpp, change the code as follows

// Integrate velocities.
    b->m_linearVelocity += step.dt * (gravity + b->m_invMass * b->m_force);

to,

// Integrate velocities.
    b->m_linearVelocity += step.dt * (b->m_gravityScale * gravity + b->m_invMass * b->m_force);

Once all of the changes are in, we need to alter two more files in the extension, these are located in jni\Box2D.

I altered Body.cpp and Body.h and added the jniSetGravityScale and jniGetGravityScale routines. For this simply copy the jniSetAngularVelocity and jniGetAngularVelocity and change appropriately. So the code in Body.cpp will appear as follows for example,

     JNIEXPORT void JNICALL Java_com_badlogic_gdx_physics_box2d_Body_jniSetGravityScale
(JNIEnv *, jobject, jlong addr, jfloat Scale)
        {
            b2Body* body = (b2Body*)addr;
            body->SetGravityScale(Scale);
        }

        JNIEXPORT jfloat JNICALL Java_com_badlogic_gdx_physics_box2d_Body_jniGetGravityScale
(JNIEnv *, jobject, jlong addr)
    {
        b2Body* body = (b2Body*)addr;
        return body->GetGravityScale();
    }

Do the same for src\Body.java, (again you can copy AngularVelocity get and setters and change appropriately).

Finally run the jni\build.bat and copy the produced .so files to your project. I then exported the extension src folder as a jar and added this to my project also.

You should now be able to call,

Body.setGravityScale(0.0f);

on your Dynamic Body.

Hope this helps.