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

Java 使用Box2D应用Y线性脉冲时X速度减慢,java,libgdx,box2d,Java,Libgdx,Box2d,我使用libgdx和box2d作为我的物理引擎。现在我有一个非常简单的盒子,在一个平面上进行控制: 一切似乎都很顺利。我用箭头键控制这个盒子。如果我按下向右箭头,盒子将向右加速。当我按下向上箭头时,盒子会跳起来但出乎意料的是,当盒子跳跃时,它的x速度减慢。有人能告诉我为什么会这样以及如何解决吗? 仅使用一些Box2d设置的播放器对象: public class Player extends Entity { private static BodyDef createBodyDef() {

我使用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);
  }
}
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;
  }
}
游戏屏幕:

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;
  }
}
公共类GameScreen扩展BaseScreen实现InputProcessor{
私有最终世界=新世界(新向量2(0,-200),假);
私有最终GameView视图=新GameView();
私有最终列表实体=新的ArrayList();
私人决赛选手=新选手(世界);
private final List pressedKeys=new ArrayList();
公共游戏屏幕(){
实体。添加(玩家);
view.setfollownity(播放器);
MapBodyBuilder.buildShapes(view.getTiledMap(),1,world);
}
@覆盖公共void show(){
super.show();
Gdx.input.setInputProcessor(此);
}
@替代公共无效渲染(浮动增量){
超级渲染(delta);
浮动力x=0f;
浮动力y=0f;
浮力=15000;
if(按Keys.contains(Input.Keys.LEFT)){
力-=力;
}
if(按Keys.contains(Input.Keys.RIGHT)){
力X+=力;
}
如果(按按键。包含(输入。按键。向下)){
力-=力;
}
player.getBody().applyForceToCenter(forceX,forceY,false);
世界台阶(三角洲,5,5);
视图。渲染(实体);
}
@替代公共空心调整大小(整型宽度、整型高度){
超级。调整大小(宽度、高度);
}
@覆盖公共void hide(){
super.hide();
Gdx.input.setInputProcessor(null);
}
@重写公共void dispose(){
super.dispose();
世界。处置();
for(实体:实体){
entity.dispose();
}
}
@覆盖公共布尔键关闭(int-keycode){
if(keycode==Input.Keys.UP){
Body Body=player.getBody();
applylinearpulse(新向量2(0,30000),body.getWorldCenter(),true);
}
按按键。添加(按键代码);
返回false;
}
@重写公共布尔键控(int-keycode){
按按键。删除((整数)键码);
返回false;
}
@重写公共布尔键类型(字符字符){
返回false;
}
@覆盖公共布尔接地(int screenX、int screenY、int指针、int按钮){
返回false;
}
@覆盖公共布尔补色(int screenX、int screenY、int指针、int按钮){
返回false;
}
@重写公共布尔值(int-screenX、int-screenY、int-pointer){
返回false;
}
@覆盖公共布尔mouseMoved(int-screenX,int-screenY){
返回false;
}
@覆盖已滚动的公共布尔值(整数金额){
返回false;
}
公共播放器getPlayer(){
返回球员;
}
}

查看移动机构的工作原理:

  • 计算力X和力Y(根据按下的键)
  • 施力
  • 当然,你不能用它来跳跃来避免“飞行”,所以你要用applyLinearImpulse()来添加一次力(只需将其推到顶部),但棘手的是你要取消你在2中添加的力。-记住在Box2D中所有力都在世界上执行。步骤(…)所有计算后执行

    而不是

        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
    
    当然,你可以考虑你自己的机制,但这是正确的方向