使用 Scene2D 在 Libgdx 中移动精灵(演员?)

Moving a sprite (Actor?) in Libgdx using Scene2D

我一直在尝试学习 scene2d,但在按下某个键时我无法让 sprite/Actor 移动。我尝试了几种不同的方法,但我似乎无法弄清楚。这是我目前拥有的代码,它会在我每次按下按键时移动演员,但在按住按键时不会。

class Player extends Actor {
    Sprite sprite = new Sprite(new Texture (Gdx.files.internal("character.png")));

    public Player() {
        setBounds(sprite.getX(), sprite.getY(), sprite.getWidth(), sprite.getHeight());
        setTouchable(Touchable.enabled);

        addListener( new InputListener() {

            @Override
            public boolean keyDown(InputEvent event, int keycode) {
                if (keycode == Input.Keys.RIGHT) {
                    MoveByAction mba = new MoveByAction();
                    mba.setAmount(1f, 0f);

                    Player.this.addAction(mba);
                }
                return true;
            }
        });
    }

    @Override
    protected void positionChanged() {
        sprite.setPosition(getX(), getY());
        super.positionChanged();
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        sprite.draw(batch);
    }

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


}

您可以使用状态机制来做到这一点。这可以是一个简单的枚举:

public enum PlayerMoveState {
   RIGHT,
   LEFT,
   IDLE
}

在您的 sprite 类型的 PlayerMoveState 下方定义一个字段,如下所示:

PlayerMoveState moveState;

根据您的 keyDown 方法中的 Input.Keys.RIGHT、Input.Keys.LEFT 将其设置为正确的状态。通过在您需要覆盖和实现的 keyUp 方法中将其设置为 IDLE 来重置状态。

@Override
public boolean keyUp(InputEvent event, int keycode) {
    moveState = PlayerMoveState.IDLE;
}

最后,在你播放器的act方法中写一个简单的switch case块。

@Override
public void act(float delta) {
   super.act(delta);
   switch(moveState) {
      case RIGHT :
      // Move right by using whatever method you want.
      // Directly increasing x
      // Increase x according to velocity you have defined.
      // Use actions, little bit dangerous.
         break;
      case LEFT :
      // Move left by using whatever method you want.
         break;
      case IDLE :
      // Don't change x coordinate of your player.
         break;
      default :

         break;
   }
}

我不太确定 actor 是否专注于自身来处理 KeyUp/Down 事件,这就是为什么我会避免使用侦听器来移动 player。

另外,更改演员的位置不需要操作 - Actorclass 中有一个简单的 setPosition() 方法。您还可以使用 getX()getY() 方法来获取演员的当前位置。

我会做的是检查是否有 Key is down (by using Gdx.input 不是 lisetners) 并设置由某些定义的步骤修改的位置,例如:

//Actor class
final float STEP = 1f;

...

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

    if(Gdx.input.isKeyPressed(Keys.W))
        this.setPosition(getX(), getY() + STEP);
    if(Gdx.input.isKeyPressed(Keys.S))
        this.setPosition(getX(), getY() - STEP);
    if(Gdx.input.isKeyPressed(Keys.A))
        this.setPosition(getX() - STEP, getY());
    if(Gdx.input.isKeyPressed(Keys.D))
        this.setPosition(getX() + STEP, getY());
}

在每个渲染中调用 act() 方法(当然,如果您正在调用舞台的 act),因此移动将是连续的。