2013-06-23 3 views
0

Я пытаюсь создать что-то вроде колыбели Ньютона. Но когда один мяч попадает в другой, все шары движутся одновременно в одном направлении. Как я могу решить эту проблему? Должен ли я создавать другие физические параметры шаров в createFixtureDef? Или мне нужно использовать какой-то конкретный алгоритм для передачи импульсов между шарами?Колыбель Ньютона на andengine, box2d

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; 
} 

}

ответ

1

К сожалению Box2D не очень подходит для этого.

По моему опыту, вы можете заставить один или два качания работать, пока шарики не касаются друг друга, чтобы начать. То есть каждый шар начинается с очень маленького промежутка между ним и соседом с каждой стороны. Это означает, что когда они сталкиваются, каждое столкновение решается с использованием всего лишь двух шаров за раз, в общей сложности 4 отдельных столкновения для удара, чтобы переместиться на другую сторону (на 5 шаров), вместо того, чтобы решать все 5 шаров в качестве одного " остров.

Проблема заключается в том, что позиционирование должно быть очень точным, и после нескольких колебаний шары отклоняются от этого, так что вы оказываетесь в столкновениях с участием более чем двух мячей за раз. Я когда-либо видел не более 2-3 качелей по желанию ...

Смежные вопросы