nicolasgramlich/AndEngine — Issue #43: Texture+Body shaking
Author: JFixbi
Created: 2012-02-17 17:10:49+00:00
State: open

Hi.

There is serious issue when we use PhysicalWorld: bodies has problems with updating sprites positions.
That's why moving sprites perform "jumping" during movement.

Looks like a general bug (in architecture) appearing because of difference in time intervals inside onUpdate for the Engine and for the World. Probably it is necessary to redesign the way of using the Box2d.

Here is the code to demonstrate the bug. The flowing is a modification of the FixedStepPhysics example.
I removed walls and add one body falling in the gravity field.

There you can see how the sprite is jumping during movement.

Also it demonstrates the "velocity=double-frame-rate" bug ( see: https://github.com/nicolasgramlich/AndEnginePhysicsBox2DExtension/issues/3 ).

package org.andengine.examples;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.Scene.IOnSceneTouchListener;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.util.FPSLogger;
import org.andengine.extension.physics.box2d.FixedStepPhysicsWorld;
import org.andengine.extension.physics.box2d.PhysicsConnector;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.extension.physics.box2d.util.Vector2Pool;
import org.andengine.input.sensor.acceleration.AccelerationData;
import org.andengine.input.sensor.acceleration.IAccelerationListener;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.ui.activity.SimpleBaseGameActivity;
import org.andengine.util.debug.Debug;

import android.hardware.SensorManager;
import android.widget.Toast;

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;

/**
* (c) 2010 Nicolas Gramlich (c) 2011 Zynga
*
* @author Nicolas Gramlich
* @since 18:47:08 - 19.03.2010
*/
public class PhysicsFixedStepExample extends SimpleBaseGameActivity implements
IUpdateHandler {
// ===========================================================
// Constants
// ===========================================================

private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;

// ===========================================================
// Fields
// ===========================================================

private BitmapTextureAtlas mBitmapTextureAtlas;

private TiledTextureRegion mBoxFaceTextureRegion;
private TiledTextureRegion mCircleFaceTextureRegion;

private Scene mScene;

private PhysicsWorld mPhysicsWorld;
private int mFaceCount = 0;

// ===========================================================
// Constructors
// ===========================================================

// ===========================================================
// Getter & Setter
// ===========================================================

// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================

Camera camera;

@Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}

@Override
public void onCreateResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

this.mBitmapTextureAtlas = new BitmapTextureAtlas(
this.getTextureManager(), 64, 64, TextureOptions.BILINEAR);
this.mBoxFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory
.createTiledFromAsset(this.mBitmapTextureAtlas, this,
"face_box_tiled.png", 0, 0, 2, 1); // 64x32
this.mCircleFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory
.createTiledFromAsset(this.mBitmapTextureAtlas, this,
"face_circle_tiled.png", 0, 32, 2, 1); // 64x32
this.mBitmapTextureAtlas.load();
}

@Override
public Scene onCreateScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());

this.mScene = new Scene();
this.mScene.setBackground(new Background(0, 0, 0));

this.mPhysicsWorld = new FixedStepPhysicsWorld(30, new Vector2(0,
SensorManager.GRAVITY_EARTH), false, 3, 2);

this.mScene.registerUpdateHandler(this.mPhysicsWorld);

this.mScene.registerUpdateHandler(this);

final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(1,
0.5f, 0.5f);

face = new AnimatedSprite(100, 100, this.mBoxFaceTextureRegion,
this.getVertexBufferObjectManager());
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face,
BodyType.DynamicBody, objectFixtureDef);

face.animate(200);

this.mScene.attachChild(face);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face,
body, true, true));
camera.setChaseEntity(face);

return this.mScene;
}

private void addFace(final float pX, final float pY) {
this.mFaceCount++;
Debug.d("Faces: " + this.mFaceCount);

final AnimatedSprite face;
final Body body;

final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(1,
0.5f, 0.5f);

if (this.mFaceCount % 2 == 0) {
face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion,
this.getVertexBufferObjectManager());
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face,
BodyType.DynamicBody, objectFixtureDef);
} else {
face = new AnimatedSprite(pX, pY, this.mCircleFaceTextureRegion,
this.getVertexBufferObjectManager());
body = PhysicsFactory.createCircleBody(this.mPhysicsWorld, face,
BodyType.DynamicBody, objectFixtureDef);
}

face.animate(200);

this.mScene.attachChild(face);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face,
body, true, true));
}

AnimatedSprite face;
Body body;
private Vector2 v;
long t;

@Override
public void onUpdate(float pSecondsElapsed) {
// TODO Auto-generated method stubbody
if (System.currentTimeMillis() - t > 2000) {
t = System.currentTimeMillis();

v = body.getLinearVelocity();
Debug.e("linear speed Vx=" + v.x + " Vy=" + v.y);
}

}

@Override
public void reset() {
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}