使用Box2D应用Y线性脉冲时,X速度减慢

spi*_*ce7 5 java box2d libgdx

我正在使用libgdx和box2d作为我的物理引擎.现在我只需要在一个平面上控制一个非常简单的盒子:

在此输入图像描述

一切似乎都运作良好.我用箭头键控制盒子.如果我按向右箭头,框会加速到右边.当我按向上箭头时,框会跳跃.出乎意料的是,当盒子跳跃时,它的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);
  }
}
Run Code Online (Sandbox Code Playgroud)

游戏画面:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

m.a*_*icz 0

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

  1. 计算forceX和forceY(根据按下的键)
  2. 施加力 X 和力 Y

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

代替

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

做类似的事情

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

然后在渲染方法中

    ...

    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
Run Code Online (Sandbox Code Playgroud)

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