2014-02-27 47 views
0

我用PhysicsJumpExample(https://code.google.com/p/andengineexamples/source/browse/src/org/anddev/andengine/examples/PhysicsJumpExample.java)作爲基礎,使用帶有Box2D擴展的Andengine構建2D平臺遊戲。我也使用TMX擴展來進行級別加載。Andengine/Box2D平臺遊戲中的物理和重力

我的等級,玩家控制等似乎工作正常,但我真的在重力方面與Box2D物理鬥爭。受到控制的AnimatedSprite受重力作用,但在使用「地球」重力(〜-9.8)時下降非常緩慢。如果我增加這個重力,那麼下降速度會更快,但是隨着Sprite在固定的「地板」上上下跳動並且橫向運動大大減少(由於我會假設的摩擦力)。

最後,出於某種原因,我查看過的每個示例在實例化PhysicsWorld時都使用了一個正值來引力,但爲了使重力「正常」,我必須將其倒轉。

很明顯,我做的事情非常錯誤,並非常感謝一些指針,在獲得這個整理。

下面兩個問題的代碼。

public class GameActivity extends SimpleBaseGameActivity { 

private final static String TAG = "GameActivity"; 

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

private HUD _hud; 
private Text _score; 
private Text _debug; 
private PhysicsWorld mPhysicsWorld; 
private PhysicsHandler _playerPhysics; 
private TMXTiledMap _map; 
private PlayerSprite _player; 
private BitmapTextureAtlas mOnScreenControlTexture; 
private TextureRegion mOnScreenControlBaseTextureRegion; 
private TextureRegion mOnScreenControlKnobTextureRegion; 
private Scene mScene; 
private Font mFont; 

private ITexture mPlayerTexture; 
private TiledTextureRegion mPlayerTextureRegion; 

@Override 
public EngineOptions onCreateEngineOptions() { 
    final BoundCamera camera = new BoundCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT); 
    EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera); 
    engineOptions.getAudioOptions().setNeedsMusic(true).setNeedsSound(true); 
    engineOptions.setWakeLockOptions(WakeLockOptions.SCREEN_ON); 
    return engineOptions; 
} 

@Override 
public void onCreateResources() throws IOException { 
} 

@Override 
public Scene onCreateScene() { 
    this.mEngine.registerUpdateHandler(new FPSLogger()); 
    this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, 0 - (SensorManager.GRAVITY_EARTH)), false); 
    this.mScene = new Scene(); 
    this.mScene.getBackground().setColor(Color.BLACK); 
    try { 
     createFont(); 
     createWorld(); 
     createPlayer(); 
     createControllers(); 
     createHUD(); 
    } catch (Exception e) { 
     Log.e(TAG, e.getMessage()); 
    } 
    this.mScene.registerUpdateHandler(this.mPhysicsWorld); 
    return mScene; 
} 

private void createFont() { 
    FontFactory.setAssetBasePath("media/fonts/"); 
    final ITexture mainFontTexture = new BitmapTextureAtlas(getTextureManager(), 256, 256, TextureOptions.NEAREST); 
    mFont = FontFactory.createStrokeFromAsset(getFontManager(), mainFontTexture, getAssets(), "game.otf", 40f, true, android.graphics.Color.WHITE, 2f, 
     android.graphics.Color.BLACK); 
    mFont.load(); 
} 

private void createHUD() { 
    Log.d(TAG, "createHud"); 
    _hud = new HUD(); 
    _score = new Text(mEngine.getCamera().getCameraSceneWidth() - 80, mEngine.getCamera().getCameraSceneHeight() - 20, mFont, "", new TextOptions(
     HorizontalAlign.RIGHT), getVertexBufferObjectManager()); 
    _score.setText("0000"); 
    _hud.attachChild(_score); 
    _debug = new Text(150, mEngine.getCamera().getCameraSceneHeight() - 20, mFont, "abcdefghijklmnopqrstuvwxyz.,()[] ", new TextOptions(HorizontalAlign.LEFT), 
     getVertexBufferObjectManager()); 
    _debug.setText(""); 
    _hud.attachChild(_debug); 
    mEngine.getCamera().setHUD(_hud); 
} 

private void createPlayer() throws Exception { 
    Log.d(TAG, "createPlayer"); 
    this.mPlayerTexture = new AssetBitmapTexture(getTextureManager(), getAssets(), "media/sprites/p1.png"); 
    this.mPlayerTextureRegion = TextureRegionFactory.extractTiledFromTexture(this.mPlayerTexture, 5, 2); 
    this.mPlayerTexture.load(); 
    _player = new PlayerSprite(50, 320, this.mPlayerTextureRegion, mEngine.getCamera(), this.mPhysicsWorld, getVertexBufferObjectManager()); 
    _player.setUserData(_player.getBody()); 
    _playerPhysics = new PhysicsHandler(_player); 
    this.mPhysicsWorld.setContactListener(new ContactListener() { 

     @Override 
     public void preSolve(Contact contact, Manifold oldManifold) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void postSolve(Contact contact, ContactImpulse impulse) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void endContact(Contact contact) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void beginContact(Contact contact) { 
      if (contact == null || contact.getFixtureA() == null || contact.getFixtureB() == null) 
       return; 
      if (contact.getFixtureA().getBody().getUserData() == null || contact.getFixtureB().getBody().getUserData() == null) 
       return; 
      if (contact.getFixtureA().getBody().getUserData().toString().equals("player") || contact.getFixtureB().getBody().getUserData().toString().equals("player")) { 
       _player.setJumping(false); 
      } 
     } 
    }); 
    _player.registerUpdateHandler(_playerPhysics); 
    this.mScene.attachChild(_player); 
} 

private void createControllers() { 
    Log.d(TAG, "createControllers"); 
    BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("media/"); 
    mOnScreenControlTexture = new BitmapTextureAtlas(getTextureManager(), 256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA); 
    mOnScreenControlBaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(mOnScreenControlTexture, this, "images/controller.png", 0, 0); 
    mOnScreenControlKnobTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(mOnScreenControlTexture, this, "images/controller_top.png", 128, 0); 
    getTextureManager().loadTexture(mOnScreenControlTexture); 
    final float x1 = mOnScreenControlBaseTextureRegion.getWidth(); 
    final float y1 = (this.mEngine.getCamera().getCameraSceneHeight() - mOnScreenControlBaseTextureRegion.getHeight()); 
    final DigitalOnScreenControl velocityOnScreenControl = new DigitalOnScreenControl(x1, y1, this.mEngine.getCamera(), this.mOnScreenControlBaseTextureRegion, 
     this.mOnScreenControlKnobTextureRegion, 0.1f, true, getVertexBufferObjectManager(), new IOnScreenControlListener() { 

      @Override 
      public void onControlChange(BaseOnScreenControl pBaseOnScreenControl, float pValueX, float pValueY) { 
       float x = 0, y = 0; 
       if (pValueX == -1 && pValueY == 0) { 
        if (_player.getDirection() != PlayerDirection.LEFT) { 
         _player.setRotation(-1); 
         _player.animate(75); 
        } 
        x = pValueX * 8; 
        y = pValueY * 8; 
        _player.setDirection(PlayerDirection.LEFT); 
       } else if (pValueX == -1 && pValueY == 1) { 
        if (!_player.isJumping()) { 
         if (_player.getDirection() != PlayerDirection.UP_LEFT) { 
          _player.animate(25); 
         } 
         x = SensorManager.GRAVITY_EARTH * -10; 
         y = SensorManager.GRAVITY_EARTH * -10; 
         _player.setDirection(PlayerDirection.UP_LEFT); 
        } 
       } else if (pValueX == 0 && pValueY == 1) { 
        if (!_player.isJumping()) { 
         if (_player.getDirection() != PlayerDirection.UP) { 
          _player.animate(75); 
         } 
         y = SensorManager.GRAVITY_EARTH * 2; 
         _player.setDirection(PlayerDirection.UP); 
        } 
       } else if (pValueX == 1 && pValueY == 1) { 
        if (!_player.isJumping()) { 
         if (_player.getDirection() != PlayerDirection.UP_RIGHT) { 
          _player.animate(25); 
         } 
         x = SensorManager.GRAVITY_EARTH * 10; 
         y = SensorManager.GRAVITY_EARTH * -10; 
         _player.setDirection(PlayerDirection.UP_RIGHT); 
        } 
       } else if (pValueX == 1 && pValueY == 0) { 
        if (_player.getDirection() != PlayerDirection.RIGHT) { 
         _player.animate(75); 
        } 
        x = pValueX * 8; 
        y = pValueY * 8; 
        _player.setDirection(PlayerDirection.RIGHT); 
       } else if (pValueX == 1 && pValueY == -1) { 
        _player.setDirection(PlayerDirection.DOWN_RIGHT); 
       } else if (pValueX == 0 && pValueY == 1) { 
        _player.setDirection(PlayerDirection.DOWN); 
       } else if (pValueX == -1 && pValueY == -1) { 
        _player.setDirection(PlayerDirection.DOWN_LEFT); 
       } else { 
        _player.setDirection(PlayerDirection.NONE); 
        if (!_player.isJumping()) { 
         _player.stopAnimation(0); 
        } 
       } 
       final Vector2 velocity = Vector2Pool.obtain(x, y); 
       _player.getBody().setLinearVelocity(velocity); 
       Vector2Pool.recycle(velocity); 
       _debug.setText(_player.getDirection().toString() + ": " + (pValueX * 60) + "," + (pValueY * 60)); 
      } 
     }); 
    velocityOnScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); 
    velocityOnScreenControl.getControlBase().setAlpha(0.5f); 

    this.mScene.setChildScene(velocityOnScreenControl); 
} 

private void createWorld() { 
    Log.d(TAG, "createWorld"); 
    try { 
     final TMXLoader tmxLoader = new TMXLoader(getAssets(), getTextureManager(), TextureOptions.NEAREST, getVertexBufferObjectManager()); 
     _map = tmxLoader.loadFromAsset("media/levels/1/1.tmx"); 
     final TMXLayer tmxLayer = _map.getTMXLayers().get(0); 
     tmxLayer.detachSelf(); 
     this.mScene.attachChild(tmxLayer); 
     ((BoundCamera) this.mEngine.getCamera()).setBounds(0, 0, tmxLayer.getHeight(), tmxLayer.getWidth()); 
     ((BoundCamera) this.mEngine.getCamera()).setBoundsEnabled(true); 

     float height = tmxLayer.getHeight(); 
     float width = tmxLayer.getWidth(); 

     final IShape bottom = new Rectangle(0, height - 2, width, 2, getVertexBufferObjectManager()); 
     bottom.setVisible(false); 
     final IShape top = new Rectangle(0, 0, width, 2, getVertexBufferObjectManager()); 
     top.setVisible(false); 
     final IShape left = new Rectangle(0, 0, 2, height, getVertexBufferObjectManager()); 
     left.setVisible(false); 
     final IShape right = new Rectangle(width - 2, 0, 2, height, getVertexBufferObjectManager()); 
     right.setVisible(false); 

     final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 1f); 
     PhysicsFactory.createBoxBody(this.mPhysicsWorld, bottom, BodyType.StaticBody, wallFixtureDef); 
     PhysicsFactory.createBoxBody(this.mPhysicsWorld, top, BodyType.StaticBody, wallFixtureDef); 
     PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef); 
     PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef); 

     this.mScene.attachChild(bottom); 
     this.mScene.attachChild(top); 
     this.mScene.attachChild(left); 
     this.mScene.attachChild(right); 

     float yOffset = _map.getTMXLayers().get(0).getHeight(); 
     for (final TMXObjectGroup group : _map.getTMXObjectGroups()) { 
      if (group.getTMXObjectGroupProperties().containsTMXProperty("solid", "true")) { 
       for (final TMXObject object : group.getTMXObjects()) { 
        final Rectangle rect = new Rectangle(object.getX() + object.getWidth()/2, yOffset - object.getY() - object.getHeight()/2, object.getWidth(), 
         object.getHeight(), getVertexBufferObjectManager()); 
        final FixtureDef boxFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 1f); 
        Body b = PhysicsFactory.createBoxBody(this.mPhysicsWorld, rect, BodyType.StaticBody, boxFixtureDef); 
        b.setUserData("solid"); 
        rect.setVisible(false); 
        rect.setZIndex(0); 
        this.mScene.attachChild(rect); 
       } 
      } 
     } 
    } catch (final TMXLoadException e) { 
     Log.e(TAG, e.getMessage()); 
    } 
} 

@Override 
public void onDestroyResources() throws IOException { 
    Log.d(TAG, "onDestroyResources: Cleanup scenes/resources"); 
    super.onDestroyResources(); 
} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    System.exit(0); 
} 

}

public class PlayerSprite extends AnimatedSprite { 

public enum PlayerDirection { 
    NONE, LEFT, UP_LEFT, UP, UP_RIGHT, RIGHT, DOWN_RIGHT, DOWN, DOWN_LEFT 
} 

private Body _body; 
private PlayerDirection _direction = PlayerDirection.NONE; 
private boolean _jumping = false; 

public PlayerSprite(float pX, float pY, ITiledTextureRegion region, Camera camera, PhysicsWorld physics, VertexBufferObjectManager vbo) { 
    super(pX, pY, region, vbo); 
    createPhysics(camera, physics); 
    camera.setChaseEntity(this); 
} 

public Body getBody() { 
    return _body; 
} 

public PlayerDirection getDirection() { 
    return _direction; 
} 

public void setDirection(PlayerDirection direction) { 
    _direction = direction; 
} 

public boolean isJumping() { 
    return _jumping; 
} 

public void setJumping(boolean jumping) { 
    _jumping = jumping; 
} 

private void createPhysics(final Camera camera, PhysicsWorld physics) { 
    _body = PhysicsFactory.createBoxBody(physics, this, BodyType.DynamicBody, PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f)); 
    _body.setUserData("player"); 
    physics.registerPhysicsConnector(new PhysicsConnector(this, _body, true, true)); 
} 

}

回答

2

因此,作爲始終是簡單地張貼,並尋求幫助卻神奇地導致了自我解決的情況下。

對於任何遇到類似問題的其他人(儘管我懷疑有人可能會這麼愚蠢!)問題在於「控制器」在播放器(左,右,跳等)上設置了強制力,但IOnScreenControlListener的OnControlChange事件不斷調用,我有「_player.getBody()。setLinearVelocity(velocity);」 (速度是一個默認的0,0)重複調用,從而否定一些引力。

Doh!