0

我正在尝试创造像牛顿摇篮这样的东西。但是当一个球撞到另一个球时,所有球都会同时朝同一个方向移动。我该如何决定这个问题?我应该在 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;
}

}

4

1 回答 1

1

不幸的是 Box2D 并不适合这个。

根据我的经验,只要球一开始没有相互接触,你就可以让一两个摆动推力发挥作用。也就是说,每个球开始时它与每一侧的相邻球之间有一个非常小的间隙。这意味着当它们发生碰撞时,每次仅使用两个球来解决每次碰撞,总共 4 次单独的碰撞以使撞击传播到另一侧(对于 5 个球),而不是将所有 5 个球作为一个单独的球来解决岛'。

麻烦的是,定位需要非常精确,在几次挥动之后,球就会偏离那个位置,这样你最终会遇到一次涉及两个以上球的碰撞。我只见过最多 2-3 次挥杆按预期工作......

于 2013-06-24T01:00:16.633 回答