2012-08-26 69 views
1

我在AndEngine中遇到了物理問題。我的精靈在移動時抖動,有時跳躍。我製作了32x32的「地板」,每個人都是另一個身體,所以我認爲這是問題(與角落或某物碰撞)。我試圖使用一個形狀而不是那些盒子,但問題仍然存在。AndEngine物理 - 我的角色在移動時動搖

它看起來像我的地板surfece不直,但不知何故不規則...

我的問題是,如何讓我的性格在這個表面上平滑移動?

順便說一句,如何讓我的角色更重?

我的整個代碼是在這裏:

private final int CAMERA_WIDTH = 800; 
private final int CAMERA_HEIGHT = 480; 

enum PlayerAction { 
    RUN, 
    NONE, 
    JUMP 
} 

enum Direction { 
    RIGHT, 
    LEFT, 
    NONE 
} 

enum BodyId { 
    PLAYER, 
    BOX 
} 

Direction mPlayerDirection = Direction.NONE; 
Direction mLastPlayerDirection = Direction.NONE; 

private Camera mCamera; 
private Scene mGameScene; 

private PhysicsWorld mPhysicsWorld; 

private BitmapTextureAtlas mBoxBitmapTextureAtlas; 
private BitmapTextureAtlas mPlayerBitmapTextureAtlas; 
private ITextureRegion mBoxTextureRegion; 
private TiledTextureRegion mPlayerTextureRegion; 

private AnimatedSprite mPlayer; 
private Body mPlayerBody; 

private BitmapTextureAtlas mOnScreenControlTexture; 
private ITextureRegion mOnScreenControlBaseTextureRegion; 
private ITextureRegion mOnScreenControlKnobTextureRegion; 

private AnalogOnScreenControl mAnalogOnScreenControl; 

@Override 
public EngineOptions onCreateEngineOptions() { 

    this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT); 
    EngineOptions mEngineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new FillResolutionPolicy(), this.mCamera); 
    mEngineOptions.getTouchOptions().setNeedsMultiTouch(true); 

    return mEngineOptions; 
} 
@Override 
public void onCreateResources(
     OnCreateResourcesCallback pOnCreateResourcesCallback) 
     throws Exception { 

    BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/"); 
    this.mBoxBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 32, 32, TextureOptions.BILINEAR); 
    this.mBoxTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBoxBitmapTextureAtlas, this, "box.png", 0, 0); 
    this.mBoxBitmapTextureAtlas.load(); 

    this.mPlayerBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 256, 128, TextureOptions.BILINEAR); 
    this.mPlayerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mPlayerBitmapTextureAtlas, this, "player.png", 0, 0, 3, 4); 
    this.mPlayerBitmapTextureAtlas.load(); 

    this.mOnScreenControlTexture = new BitmapTextureAtlas(this.getTextureManager(), 256, 128, TextureOptions.BILINEAR); 
    this.mOnScreenControlBaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_base.png", 0, 0); 
    this.mOnScreenControlKnobTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_knob.png", 128, 0); 
    this.mOnScreenControlTexture.load(); 

    pOnCreateResourcesCallback.onCreateResourcesFinished(); 
} 
@Override 
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) 
     throws Exception { 

    this.mGameScene = new Scene(); 

    initPhysics(this.mGameScene); 

    for(int i = 0; i <= 50; i++) { 
     Sprite sprite = new Sprite(i*32, this.mCamera.getHeight() - this.mBoxTextureRegion.getHeight(), this.mBoxTextureRegion, this.getVertexBufferObjectManager()); 
     createBody(sprite, BodyType.StaticBody, 1, 0, 0, BodyId.BOX); 
     this.mGameScene.attachChild(sprite); 
    } 

    /* Calculate the coordinates for the face, so its centered on the camera. */ 
    final float playerX = (CAMERA_WIDTH - this.mPlayerTextureRegion.getWidth())/2; 
    final float playerY = CAMERA_HEIGHT - this.mPlayerTextureRegion.getHeight() - 128; 

    this.mPlayer = new AnimatedSprite(playerX, playerY, this.mPlayerTextureRegion, this.getVertexBufferObjectManager()) { 

     @Override 
     protected void onManagedUpdate(float pSecondsElapsed) { 
      super.onManagedUpdate(pSecondsElapsed); 
      switch (mPlayerDirection) { 
      case RIGHT: 
       if (!mPlayerDirection.equals(mLastPlayerDirection)) { 
        mLastPlayerDirection = Direction.RIGHT; 
        GameActivity.this.mPlayer.animate(new long[]{200, 200, 200}, 3, 5, true); 
       } 
       break; 
      case LEFT: 
       if (!mPlayerDirection.equals(mLastPlayerDirection)) { 
        mLastPlayerDirection = Direction.LEFT; 
        GameActivity.this.mPlayer.animate(new long[]{200, 200, 200}, 9, 11, true); 
       } 
       break; 
      case NONE: 
       mLastPlayerDirection = Direction.NONE; 
       GameActivity.this.mPlayer.setCurrentTileIndex(6); 
       GameActivity.this.mPlayer.stopAnimation(); 
       break; 
      default: 
       mLastPlayerDirection = Direction.NONE; 
       GameActivity.this.mPlayer.setCurrentTileIndex(6); 
       GameActivity.this.mPlayer.stopAnimation(); 
       break; 
      } 
     } 
    }; 

    this.mPlayer.setScaleCenterY(this.mPlayerTextureRegion.getHeight()); 
    this.mPlayer.setScale(2); 
    this.mGameScene.attachChild(this.mPlayer); 

    this.mCamera.setChaseEntity(mPlayer); 

    this.mPlayerBody = createMovingBody(this.mPlayer, BodyType.DynamicBody, 1, 0, 0, BodyId.PLAYER); 

    this.mAnalogOnScreenControl = new AnalogOnScreenControl(32, CAMERA_HEIGHT - this.mOnScreenControlBaseTextureRegion.getHeight() - 32, this.mCamera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, 200, this.getVertexBufferObjectManager(), new IAnalogOnScreenControlListener() { 
     @Override 
     public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) { 

      GameActivity.this.mPlayerBody.setLinearVelocity(new Vector2(pValueX*10, GameActivity.this.mPlayerBody.getLinearVelocity().y)); 

      if (pValueX > 0) 
       GameActivity.this.mPlayerDirection = Direction.RIGHT; 
      else if (pValueX < 0) 
       GameActivity.this.mPlayerDirection = Direction.LEFT; 
      else 
       GameActivity.this.mPlayerDirection = Direction.NONE; 
     } 

     @Override 
     public void onControlClick(
       AnalogOnScreenControl pAnalogOnScreenControl) { 
      GameActivity.this.mPlayerBody.setLinearVelocity(new Vector2(GameActivity.this.mPlayerBody.getLinearVelocity().x, -8.0f)); 
     } 
    }); 

    this.mAnalogOnScreenControl.getControlBase().setBlendFunction(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 
    this.mAnalogOnScreenControl.getControlBase().setAlpha(0.2f); 
    this.mAnalogOnScreenControl.getControlBase().setScaleCenter(0, 128); 
    this.mAnalogOnScreenControl.getControlBase().setScale(1.25f); 
    this.mAnalogOnScreenControl.getControlKnob().setScale(1.25f); 
    this.mAnalogOnScreenControl.refreshControlKnobPosition(); 

    this.mGameScene.setChildScene(this.mAnalogOnScreenControl); 

    pOnCreateSceneCallback.onCreateSceneFinished(this.mGameScene); 
} 
@Override 
public void onPopulateScene(Scene pScene, 
     OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception { 

    this.mEngine.registerUpdateHandler(new TimerHandler(3f, true, new ITimerCallback() { 
     @Override 
     public void onTimePassed(TimerHandler pTimerHandler) { 
      // TODO Auto-generated method stub 

     } 

    })); 

    pOnPopulateSceneCallback.onPopulateSceneFinished(); 
} 

private void initPhysics(Scene pScene) 
{ 
    mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false); 
    pScene.registerUpdateHandler(mPhysicsWorld); 
} 

private Body createBody(Sprite pSprite, BodyType pBodyType, float pDensity, float pElasticity, float pFriction, BodyId pBodyId) 
{ 
    final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(pDensity, pElasticity, pFriction); 
    Body body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, pSprite, pBodyType, objectFixtureDef); 
    body.setUserData(pBodyId); 
    return body; 
} 

private Body createMovingBody(Sprite pSprite, BodyType pBodyType, float pDensity, float pElasticity, float pFriction, BodyId pBodyId) { 
    Body body = createBody(pSprite, pBodyType, pDensity, pElasticity, pFriction, pBodyId); 
    mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(pSprite, body, true, false)); 
    return body; 
} 

回答

2

我相信這可以通過CPU速度不夠造成的。當處理器不能滿足Box2D的要求時,仿真會受到影響。屍體可能會落入地板佔據的空間,並在下一個模擬週期中向上推。當某些後臺應用程序導致CPU負載飆升時也會發生這種情況。

嘗試在更快的手機上運行該應用程序,或在沒有其他應用程序在後臺運行的情況下運行該應用程序。我解決了使用大MaxStepPhysicsWorld,可以在這裏發現了類似的問題:http://www.andengine.org/forums/features/max-step-physics-to-avoid-choppyness-and-bad-simulation-t1271.html

它的工作原理是這樣的,當發動機無法執行每秒足夠的仿真步驟,MaxStepPhysicsWorld上是實時的放棄和而進行足夠的模擬步驟每「秒」,從而確保良好的模擬。

+0

其實我覺得我的手機速度夠快了......我用的是HTC Sensation,所以CPU不應該有任何問題。其他的,即使更復雜的遊戲與更先進的物理工作很好!效果不是那種滯後,而是它看起來像我的Sprite與每個盒子角落發生碰撞,或者像我的'地面'不規則,我不知道爲什麼......但是我會嘗試固定 - 一步物理 – daltostronic

+0

好的。這是更好的使用你鏈接MaxStepPhysicsWorld類,但我仍然有一個問題,「因爲有時我的性格停止,我必須跳,使其走得更遠...你有什麼想法?非常感謝幫助 – daltostronic

+0

好的,我把我的身體設置成了圓圈......我找不到任何其他的方式,現在它已經很好了。也許以後我會簡單地設置多邊形的左下角和右下角,現在不需要 – daltostronic

2

OKAY我解決了它!

如果有人感興趣: 我使用here的功能,因爲我想檢查我的身體與他人發生碰撞的方向。我改變了這種功能爲我用,所以:

  1. 我已經修改了它的價值shrinkToFactor使用,所以它實際上並沒有改變所有的三角形的大小,但要拐角之間的空間,因此,如果你接觸地面你不會與3個三角形發生碰撞,而只與其中一個三角形發生碰撞。 (但它的另一個故事,也許有人需要它還是會覺得有用)
  2. 我稍微「切割」我的底部夾具的邊緣,所以它的幻燈片上的邊緣,而不是被他們停了下來,這裏是我的底部夾具矢量定義:

    final Vector2[] vertices2 = { // DOWN 
          new Vector2((wd2 - shrinkToFactor - 1)/P2M, (hd2 - 1)/P2M), 
          new Vector2((wd2 - shrinkToFactor)/P2M, hd2/P2M), 
          new Vector2((-wd2 + shrinkToFactor)/P2M, hd2/P2M), 
          new Vector2((-wd2 + shrinkToFactor + 1)/P2M, (hd2 - 1)/P2M), 
          new Vector2(0/P2M, 0/P2M) 
        }; 
    

這裏是我的全部功能。

public static Body createPlayerBody(final MaxStepPhysicsWorld pPhysicsWorld, final Sprite pSprite, final FixtureDef pFixtureDef, final float pPixelToMeterRatio, final BodyType bodyType, final float shrinkToFactor) { 
     final BodyDef bodyDef = new BodyDef(); 
     bodyDef.type = bodyType; 
     final float P2M = pPixelToMeterRatio; 

     final float[] sceneCenterCoordinates = pSprite.getSceneCenterCoordinates(); 
     bodyDef.position.x = sceneCenterCoordinates[Constants.VERTEX_INDEX_X]/P2M; 
     bodyDef.position.y = sceneCenterCoordinates[Constants.VERTEX_INDEX_Y]/P2M; 

     final Body boxBody = pPhysicsWorld.createBody(bodyDef); 

     final float wd2 = (pSprite.getWidth()/2); 
     final float hd2 = (pSprite.getHeight()/2); 

     final Vector2[] vertices1 = { // RIGHT 
       new Vector2(wd2/P2M, (hd2 - shrinkToFactor)/P2M), 
       new Vector2(0/P2M, 0/P2M), 
       new Vector2(wd2/P2M, (-hd2 + shrinkToFactor)/P2M) 
     }; 
     final Vector2[] vertices2 = { // DOWN 
       new Vector2((wd2 - shrinkToFactor - 1)/P2M, (hd2 - 1)/P2M), 
       new Vector2((wd2 - shrinkToFactor)/P2M, hd2/P2M), 
       new Vector2((-wd2 + shrinkToFactor)/P2M, hd2/P2M), 
       new Vector2((-wd2 + shrinkToFactor + 1)/P2M, (hd2 - 1)/P2M), 
       new Vector2(0/P2M, 0/P2M) 
     }; 
     final Vector2[] vertices3 = { // LEFT 
       new Vector2(-wd2/P2M, (hd2 - shrinkToFactor)/P2M), 
       new Vector2(-wd2/P2M, (-hd2 + shrinkToFactor)/P2M), 
       new Vector2(0/P2M, 0/P2M) 
     }; 
     final Vector2[] vertices4 = { // UP 
       new Vector2((-wd2 + shrinkToFactor)/P2M, -hd2/P2M), 
       new Vector2((wd2 - shrinkToFactor)/P2M, -hd2/P2M), 
       new Vector2(0/P2M, 0/P2M) 
     }; 

     PolygonShape poly = new PolygonShape(); 
     pFixtureDef.shape = poly; 
     poly.set(vertices1); 
     final Fixture f1 = boxBody.createFixture(pFixtureDef); 
     f1.setUserData(BodyId.PLAYER); 
     poly.set(vertices2); 
     final Fixture f2 = boxBody.createFixture(pFixtureDef); 
     f2.setUserData(BodyId.PLAYER_FOOT); 
     poly.set(vertices3); 
     final Fixture f3 = boxBody.createFixture(pFixtureDef); 
     f3.setUserData(BodyId.PLAYER); 
     poly.set(vertices4); 
     final Fixture f4 = boxBody.createFixture(pFixtureDef); 
     f4.setUserData(BodyId.PLAYER_HEAD); 
     poly.dispose(); 

     return boxBody; 
} 
+0

還有一件事可能會有用 - 最好是使用更大的表面件(我的遊戲中的盒子),比如64x64而不是32x32 – daltostronic