使用Box2D时,施加Y轴线性冲量会导致X轴速度减缓。

5
我正在使用libgdx和box2d作为我的物理引擎。目前我只有一个非常简单的方框被控制在一个平面上: enter image description here 一切似乎都运行良好。我用箭头键控制盒子。如果我按右箭头,盒子将向右加速。当我按上箭头时,盒子会跳跃。然而让人意外的是,当盒子跳跃时,它的x速度会减慢。有人能告诉我为什么会这样,以及如何解决吗?
带有一些Box2d设置的玩家对象:
public class Player extends Entity {
  private static BodyDef createBodyDef() {
    BodyDef bodyDef = new BodyDef();
    bodyDef.type = BodyDef.BodyType.DynamicBody;
    bodyDef.fixedRotation = true;
    bodyDef.position.set(100, 200);
    return bodyDef;
  }

  public Player(World world) {
    super(world, createBodyDef(), Textures.rectangle(Units.m2P(0.7f), Units.m2P(2f), Color.RED));
    FixtureDef fixtureDef = new FixtureDef();
    PolygonShape shape = new PolygonShape();
    shape.setAsBox(50, 50, new Vector2(50, 50), 0f);
    fixtureDef.shape = shape;
    fixtureDef.friction = 0.1f;
    getBody().createFixture(fixtureDef);
    MassData massData = new MassData();
    massData.mass = 90f;
    getBody().setMassData(massData);
  }
}

游戏屏幕:
public class GameScreen extends BaseScreen implements InputProcessor {
  private final World world = new World(new Vector2(0, -200), false);
  private final GameView view = new GameView();
  private final List<Entity> entities = new ArrayList<Entity>();
  private final Player player = new Player(world);
  private final List<Integer> pressedKeys = new ArrayList<Integer>();

  public GameScreen() {
    entities.add(player);
    view.setFollowEntity(player);
    MapBodyBuilder.buildShapes(view.getTiledMap(), 1, world);
  }

  @Override public void show() {
    super.show();
    Gdx.input.setInputProcessor(this);
  }

  @Override public void render(float delta) {
    super.render(delta);

    float forceX = 0f;
    float forceY = 0f;
    float force = 15000;
    if (pressedKeys.contains(Input.Keys.LEFT)) {
      forceX -= force;
    }
    if (pressedKeys.contains(Input.Keys.RIGHT)) {
      forceX += force;
    }
    if (pressedKeys.contains(Input.Keys.DOWN)) {
      forceY -= force;
    }

    player.getBody().applyForceToCenter(forceX, forceY, false);

    world.step(delta, 5, 5);
    view.render(entities);
  }

  @Override public void resize(int width, int height) {
    super.resize(width, height);
  }

  @Override public void hide() {
    super.hide();
    Gdx.input.setInputProcessor(null);
  }

  @Override public void dispose() {
    super.dispose();
    world.dispose();
    for (Entity entity : entities) {
      entity.dispose();
    }
  }

  @Override public boolean keyDown(int keycode) {
    if (keycode == Input.Keys.UP) {
      Body body = player.getBody();
      body.applyLinearImpulse(new Vector2(0, 30000), body.getWorldCenter(), true);
    }

    pressedKeys.add(keycode);
    return false;
  }

  @Override public boolean keyUp(int keycode) {
    pressedKeys.remove((Integer) keycode);
    return false;
  }

  @Override public boolean keyTyped(char character) {
    return false;
  }

  @Override public boolean touchDown(int screenX, int screenY, int pointer, int button) {
    return false;
  }

  @Override public boolean touchUp(int screenX, int screenY, int pointer, int button) {
    return false;
  }

  @Override public boolean touchDragged(int screenX, int screenY, int pointer) {
    return false;
  }

  @Override public boolean mouseMoved(int screenX, int screenY) {
    return false;
  }

  @Override public boolean scrolled(int amount) {
    return false;
  }

  public Player getPlayer() {
    return player;
  }
}
1个回答

0

看看你的移动机制是如何工作的:

  1. 计算forceX和forceY(由按下哪些键决定)
  2. 应用forceX和forceY

当然,你不能用它来跳跃以避免“飞行”,所以你使用applyLinearImpulse()一次性添加力量(只需将其推到顶部),但棘手的部分是你要取消在2.中添加的forceX - 请记住,在Box2D中,所有力都在world.step(...)执行所有计算之后执行。

与其说

    if (keycode == Input.Keys.UP) 
    {
        Body body = player.getBody();
        body.applyLinearImpulse(new Vector2(0, 30000), body.getWorldCenter(), true);
    }

做类似于以下的事情

    if (keycode == Input.Keys.UP) 
    {
        jumpForce = 30000; //jumpForce is variable of GameScreen class
    }

然后在渲染方法中

    ...

    if (pressedKeys.contains(Input.Keys.DOWN)) 
    {
        forceY -= force;
    }

    forceY += jumpForce; //here you add the jump force

    player.getBody().applyForceToCenter(forceX, forceY, false);

    jumpForce = 0; //but only once - in next iteration od render it will be avoided till UP key will be pressed again

当然你可以考虑自己的机制,但这是正确的方向。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接