0
\$\begingroup\$

I have a scene and i can set gravity in the PhysicsWorld like

this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, -SensorManager.GRAVITY_EARTH),false);

but i would like all bodies to gravitate to a point.

I tried

physicsWorld.setGravity(new Vector2(centerX, centerY));

but that has not worked- i assume because i need to calculate the vector to the centre. But I'm not sure how to do that and where to calculate it so it changes.

I would like the input (of force) to be from the touch handler of the sprite. The sprite at the moment can be moved via

@Override
    public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
            float pTouchAreaLocalX, float pTouchAreaLocalY) {               

        //this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2, pSceneTouchEvent.getY() - this.getHeight() / 2);

        if (pSceneTouchEvent.isActionMove() || pSceneTouchEvent.isActionDown() || pSceneTouchEvent.isActionOutside())
        {
            this.setX(pSceneTouchEvent.getX() - this.getWidth() / 4);
            this.setY(pSceneTouchEvent.getY() - this.getHeight() / 4);
        }

        return true;
    }

I would like to do the calculation in there so as the sprite is dragged, the vector changes, then when it's released it should 'fall' to the centre

EDIT:

Mass can be set as 1 unit since it's not relevant

Thanks for the help.

\$\endgroup\$
1
\$\begingroup\$

You don't do it by trying to set the global gravity. Instead you set the global gravity to zero and then you calculate the force that your gravity would affect the object with and apply that.

Pseudo-code-wise it could look something like this;

Vector2 centerOfGravity = new Vector2(someX, someY);

void update(float deltaTime) {

    physicsWorld.Step(deltaTime, numberOfIterations)

    foreach Body body in allYourBodies {
       Vector2 gravityDirection = normalize(centerOfGravity - body.getPosition())
       Vector2 bodyGravity = body.mass * gravityDirection * some_scalar_to_make_it_look_right

       body.ApplyForce(bodyGravity, body.getPosition()
    }
}

I don't use AndEngine (anymore) but the Box2D API is similar in libGDX so you should be able to easily translate this example, it yields results like Low gravity or More gravity

The complete, very dirty, code I used to generate that looks like this;

package com.bornander.androidstudiosandbox;

    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.graphics.GL20;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.graphics.Texture;
    import com.badlogic.gdx.graphics.g2d.SpriteBatch;
    import com.badlogic.gdx.math.MathUtils;
    import com.badlogic.gdx.math.Vector2;
    import com.badlogic.gdx.math.Vector3;
    import com.badlogic.gdx.physics.box2d.Body;
    import com.badlogic.gdx.physics.box2d.BodyDef;
    import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
    import com.badlogic.gdx.physics.box2d.CircleShape;
    import com.badlogic.gdx.physics.box2d.FixtureDef;
    import com.badlogic.gdx.physics.box2d.PolygonShape;
    import com.badlogic.gdx.physics.box2d.Shape;
    import com.badlogic.gdx.physics.box2d.World;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;

    public class MyAndroidStudioSandboxGame extends ApplicationAdapter {
        SpriteBatch batch;
        Texture img;
        World world;
        OrthographicCamera camera;
        Box2DDebugRenderer renderer;
        List<Body> bodies = new ArrayList<Body>();

        @Override
        public void create () {
            batch = new SpriteBatch();
            img = new Texture("badlogic.jpg");


            camera = new OrthographicCamera(100, 100);
            camera.position.set(0,0,0);

            world = new World(Vector2.Zero, true);

            renderer = new Box2DDebugRenderer();

            Body planet = createCircle(5, 0, 0);
            planet.setType(BodyDef.BodyType.StaticBody);

            Random rnd = new Random();
            for(int i = 0; i < 10; ++i) {
                float angle = rnd.nextFloat() * MathUtils.PI2;
                Vector2 pos = (new Vector2(MathUtils.sin(angle), MathUtils.cos(angle))).scl(20 + rnd.nextFloat() * 30);
                Body body = createCircle(1.0f + rnd.nextFloat(), pos.x, pos.y);
                bodies.add(body);
                Vector2 dir = pos.nor();
                dir.set(dir.y, -dir.x);
                dir.scl(8);
                body.setLinearVelocity(dir);

            }

        }

        private Body createBox(float w, float h, float x, float y) {
            BodyDef nodeBodyDefinition = new BodyDef();
            nodeBodyDefinition.type = BodyDef.BodyType.DynamicBody;
            Vector2 center = new Vector2();
            nodeBodyDefinition.position.set(10, 10);

            PolygonShape shape = new PolygonShape();
            float density = 1.0f;
            shape.setAsBox(w / 2.0f, h / 2.0f);

            Body body = world.createBody(nodeBodyDefinition);
            body.setUserData(this);
            body.setTransform(x, y, 0);
            final FixtureDef nodeFixtureDefinition = createFixtureDefinition(shape, density);

            body.createFixture(nodeFixtureDefinition);
            shape.dispose();

            return body;
        }

        private Body createCircle(float r, float x, float y) {
            BodyDef nodeBodyDefinition = new BodyDef();
            nodeBodyDefinition.type = BodyDef.BodyType.DynamicBody;
            Vector2 center = new Vector2();
            nodeBodyDefinition.position.set(10, 10);

            CircleShape shape = new CircleShape();
            float density = 1.0f;
            shape.setRadius(r);

            Body body = world.createBody(nodeBodyDefinition);
            body.setUserData(this);
            body.setTransform(x, y, 0);
            final FixtureDef nodeFixtureDefinition = createFixtureDefinition(shape, density);

            body.createFixture(nodeFixtureDefinition);
            shape.dispose();

            return body;
        }

        private static FixtureDef createFixtureDefinition(final Shape shape, final float density) {
            final FixtureDef nodeFixtureDefinition = new FixtureDef();
            nodeFixtureDefinition.shape = shape;
            nodeFixtureDefinition.friction = 1;
            nodeFixtureDefinition.density = density;
            nodeFixtureDefinition.restitution = 0.1f;
            return nodeFixtureDefinition;
        }



        @Override
        public void render () {
            Gdx.gl.glClearColor(0, 0, 0, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

            world.step(Gdx.graphics.getDeltaTime(), 4, 4);
            camera.update();

            for(Body body : bodies) {
                Vector2 gravityDirection = (new Vector2()).sub(body.getWorldCenter().x, body.getWorldCenter().y);
                gravityDirection.scl(10);
                body.applyForce(gravityDirection, body.getWorldCenter(), true);
            }

            renderer.render(world, camera.combined);
        }
    }
\$\endgroup\$
  • \$\begingroup\$ mmm.. The direction stuff looks right, but I don't see Newton formula F=G*(M+m) / r^2 in your code \$\endgroup\$ – dnk drone.vs.drones Dec 10 '15 at 10:27
  • \$\begingroup\$ No it's simplified. You could let the force be dependent on the distance to the source but I don't think it's going to help you. The actual difference in force acting on an apple falling from 10m compared to one falling from 1000m is negligible. I don't think Box2D uses the full formula either, it's just a force being added in a direction every frame. \$\endgroup\$ – bornander Dec 10 '15 at 11:49
  • 1
    \$\begingroup\$ ok, I thought , having a point relative gravity, was intended for simulating some orbiting stuff. \$\endgroup\$ – dnk drone.vs.drones Dec 10 '15 at 12:10
  • \$\begingroup\$ @dnkdrone.vs.drones If that's the case, for example a planetary system, my approach would need a bit of tuning. \$\endgroup\$ – bornander Dec 10 '15 at 12:17
  • 1
    \$\begingroup\$ @bomander what i am trying to do is simulate a sort of orbiting system, a form of orbit that eventually reaches the center but not in a linear way \$\endgroup\$ – d4c0d312 Dec 10 '15 at 12:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.