我正在尝试创造像牛顿摇篮这样的东西。但是当一个球撞到另一个球时,所有球都会同时朝同一个方向移动。我该如何决定这个问题?我应该在 createFixtureDef 中创建另一个球的物理选项吗?或者我需要使用一些特定的算法在球之间传递脉冲?
public class MainActivity extends SimpleBaseGameActivity implements IAccelerationListener,
IOnAreaTouchListener
{
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;
private BitmapTextureAtlas mBitmapTextureAtlas;
final String TAG = "States";
private Scene mScene;
protected ITiledTextureRegion mBoxFaceTextureRegion;
protected ITiledTextureRegion mCircleFaceTextureRegion;
protected PhysicsWorld mPhysicsWorld;
@Override
public EngineOptions onCreateEngineOptions() {
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}
@Override
protected 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
protected Scene onCreateScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
this.mScene = new Scene();
this.mScene.setBackground(new Background(0, 0, 0));
//this.mScene.setOnSceneTouchListener(this);
this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
this.initJoints(mScene);
this.mScene.registerUpdateHandler(this.mPhysicsWorld);
this.mScene.setOnAreaTouchListener(this);
return this.mScene;
}
private void initJoints(final Scene pScene) {
final float centerY = CAMERA_HEIGHT / 2;
final float spriteWidth = this.mBoxFaceTextureRegion.getWidth();
final float spriteHeight = this.mBoxFaceTextureRegion.getHeight();
final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(30, 0.2f, 0.2f);
for(int i = 0; i < 10; i++) {
final float anchorFaceX = 100 + i * spriteWidth ;
final float anchorFaceY = centerY;
final AnimatedSprite anchorFace = new AnimatedSprite(anchorFaceX, anchorFaceY,
this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager());
final Body anchorBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld,
anchorFace, BodyType.StaticBody,
objectFixtureDef);
final AnimatedSprite movingFace = new AnimatedSprite(anchorFaceX, anchorFaceY + 150,
this.mCircleFaceTextureRegion, this.getVertexBufferObjectManager()) ;
// movingFace.setScale(1.2f);
final Body movingBody = PhysicsFactory.createCircleBody(this.mPhysicsWorld,
movingFace, BodyType.DynamicBody, objectFixtureDef);
movingFace.setUserData(movingBody);
// anchorFace.setScale(1.2f);
anchorFace.animate(200);
anchorFace.animate(200);
final Line connectionLine = new Line(anchorFaceX + spriteWidth / 2,
anchorFaceY + spriteHeight / 2,
anchorFaceX + spriteWidth / 2,
anchorFaceY + spriteHeight / 2,
this.getVertexBufferObjectManager());
pScene.registerTouchArea(movingFace);
pScene.attachChild(connectionLine);
pScene.attachChild(anchorFace);
pScene.attachChild(movingFace);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(anchorFace,
anchorBody, true, true){
@Override
public void onUpdate(final float pSecondsElapsed) {
super.onUpdate(pSecondsElapsed);
final Vector2 movingBodyWorldCenter = movingBody.getWorldCenter();
connectionLine.setPosition(connectionLine.getX1(), connectionLine.getY1(),
movingBodyWorldCenter.x * PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT,
movingBodyWorldCenter.y * PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT);
}
});
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(movingFace, movingBody, true, true));
final RevoluteJointDef revoluteJointDef = new RevoluteJointDef();
revoluteJointDef.initialize(anchorBody, movingBody, anchorBody.getWorldCenter());
this.mPhysicsWorld.createJoint(revoluteJointDef);
}
}
@Override
public void onAccelerationAccuracyChanged(final AccelerationData pAccelerationData) {
}
@Override
public void onAccelerationChanged(final AccelerationData pAccelerationData) {
final Vector2 gravity = Vector2Pool.obtain(pAccelerationData.getX(), pAccelerationData.getY());
this.mPhysicsWorld.setGravity(gravity);
Vector2Pool.recycle(gravity);
}
public boolean onAreaTouched( final TouchEvent pSceneTouchEvent,
final ITouchArea pTouchArea,final float pTouchAreaLocalX,
final float pTouchAreaLocalY) {
if(pSceneTouchEvent.isActionMove())
{
float touchX = pSceneTouchEvent.getX();
float touchY = pSceneTouchEvent.getY();
Log.d(TAG, "move to in X" +touchX + "n Y " +touchY);
final AnimatedSprite anchorFace = (AnimatedSprite) pTouchArea;
final Body tochedBody = (Body)anchorFace.getUserData();
//move sprite to xy
final float x = pSceneTouchEvent.getX();
final float y = pSceneTouchEvent.getY();
final float widthD2 = anchorFace.getWidth() / 2;
final float heightD2 = anchorFace.getHeight() / 2;
final float angle = tochedBody.getAngle(); // keeps the body angle
final Vector2 v2 = Vector2Pool.obtain((x + widthD2) / 32, (y + heightD2) / 32);
tochedBody.setTransform(v2, angle);
Vector2Pool.recycle(v2);
return true;
}
return false;
}
}