2
votes

I'm not understanding something about setting the magnitude of angular velocity in Box2d/AndEngine. I have this:

final float omegaFactor = (float) 1.0; ballBody.setAngularVelocity((float) ( (Math.PI) * omegaFactor) );

with omegaFactor > 0, the body spins in one direction. If I change omegaFactor to -1.0, the body spins in the opposite direction, which is good. However, changing the magnitude has no effect. For example, a value of 1111.0 exhibits the same behavior as 1.0. Note that body is a DynamicBody. What do I need to do to affect the rate of spin? Here's the entire test code:

package example.bouncingball;

import java.io.IOException;
import java.io.InputStream;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.Sprite;
import org.andengine.extension.physics.box2d.PhysicsConnector;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.input.sensor.acceleration.AccelerationData;
import org.andengine.input.sensor.acceleration.IAccelerationListener;
import org.andengine.opengl.texture.ITexture;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.bitmap.BitmapTexture;
import org.andengine.opengl.texture.region.TextureRegion;
import org.andengine.opengl.texture.region.TextureRegionFactory;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.ui.activity.SimpleBaseGameActivity;
import org.andengine.util.adt.io.in.IInputStreamOpener;
import org.andengine.util.debug.Debug;

import android.hardware.SensorManager;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;

/**
 * Demonstrate some physics
 * Image file: assets/gfx/ball.png 128x128
 *
 */
public class MainActivity extends SimpleBaseGameActivity implements IAccelerationListener {

    // ===========================================================
    // Fields
    // ===========================================================
    private Scene scene;

    private PhysicsWorld mPhysicsWorld;

    private TextureRegion mBallTextureRegion;
    private Sprite mBallSprite;

    private final int LEFT_EDGE = 0;
    private final int CAMERA_WIDTH = 720; // right of screen

    private final int TOP_OF_SCREEN = 0;
    private final int CAMERA_HEIGHT = 480; // bottom of screen

    public EngineOptions onCreateEngineOptions() {

        final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

        final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);

        return engineOptions;

    }

    @Override
    protected void onCreateResources() {

        try {
            BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

            setBallTexture();

        }
        catch (Exception exception) {
            System.out.println ("MainActivity.onCreateResources(): " + exception);
            Debug.d("MainActivity.onCreateResources(): " + exception);
        }
    }

    @Override
    protected Scene onCreateScene() {

        scene = new Scene();

        final VertexBufferObjectManager vertexBufferObjectManager = this.getVertexBufferObjectManager();

        // physics world
        this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);

        final Rectangle ground = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH, 2, vertexBufferObjectManager);
        //final Rectangle roof = new Rectangle(0, 0, CAMERA_WIDTH, 2, vertexBufferObjectManager); // roof at top of screen
        // y < 0 so as to lift the roof to start the ball off-screen
        final Rectangle roof = new Rectangle(0, -200, CAMERA_WIDTH, 2, vertexBufferObjectManager);
        final Rectangle left = new Rectangle(0, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
        final Rectangle right = new Rectangle(CAMERA_WIDTH - 2, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);

        final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f);
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef);
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof, BodyType.StaticBody, wallFixtureDef);
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef);
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef);

        scene.attachChild(ground);
        scene.attachChild(roof);
        scene.attachChild(left);
        scene.attachChild(right);

        scene.registerUpdateHandler(this.mPhysicsWorld);

        // end physics world

        // if we use body.Transform() then x,y do not matter here 
        // except that it appears to flash at the x,y defined here before the transform
        // so set it to the same
        final int startX = CAMERA_WIDTH - 160;
        mBallSprite = new Sprite( startX, 
                TOP_OF_SCREEN - 100,  // off screen
                this.mBallTextureRegion, 
                getVertexBufferObjectManager());

        final Sprite ballFace = new Sprite( startX, TOP_OF_SCREEN - 100, this.mBallTextureRegion, this.getVertexBufferObjectManager());

        // increasing elasticity makes the ball more 'bouncy'
        // if friction is 0, it doesn't roll on the floor, it just spins in one spot
        // if friction is < 0, the ball disappears when it hits the floor, or wall presumably
        final FixtureDef BALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(
                1,     // density
                0.5f,  // elasticity 
                0.5f); // friction

        final Body ballBody = PhysicsFactory.createCircleBody(this.mPhysicsWorld, ballFace, BodyType.DynamicBody, BALL_FIXTURE_DEF);

        // Angular velocity - omega of the object is the change of angle with respect to time
        // Angular velocity is measured in radians per second
        // omegaFactor:  2.0: 2 revolutions per second, clockwise
        //              -0.5: 1/2 revolution per second, counterclockwise
        final float omegaFactor = (float) 1.0;
        ballBody.setAngularVelocity((float) ( (Math.PI) * omegaFactor) ); 

        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(mBallSprite, ballBody, true, true));

        scene.attachChild(mBallSprite);

        return scene;
    }

    private void setBallTexture() throws IOException {

        ITexture texture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {

            @Override
            public InputStream open() throws IOException {
                return getAssets().open("gfx/ball.png");
            }
        });

        texture.load();
        this.mBallTextureRegion = TextureRegionFactory.extractFromTexture(texture);

    }

    // IAccelerationListener interface
    @Override
    public void onAccelerationAccuracyChanged(final AccelerationData pAccelerationData) {
    }

    @Override
    public void onAccelerationChanged(final AccelerationData pAccelerationData) {
    }
    // end IAccelerationListener interface

}
1
There is a maximum angular rotation speed enforced to keep the simulation stable, so very large values will be capped to that speed which is pi/2 rads per time step. Does it make any difference if you make the value smaller, say 0.1 ?iforce2d
Thanks for your reply. Using 0.1 results slower rotation. So I guess when I have omegaFactor set to 1.0, that is somewhere around the max, which is not fast at all. How do I determine the time step? Is it related to fps?numberwang
I see the problem now. I was looking only on the emulator. When I look at it on an actual device, the spin is faster. Thanks for your help.numberwang
The time step is whatever value you give to the world's Step function. The rotation limit is per time step, whereas the value you give to SetAngularVelocity is per second. If you are doing 60 steps per second, then the max angular velocity you could use would be 60*pi/2 == 30pi rad/siforce2d

1 Answers

2
votes

I was looking only on the emulator. When I look at it on an actual device, the spin is faster.