Search code examples
javalibgdxspriteactorscene2d

Moving a sprite (Actor?) in Libgdx using Scene2D


I've been trying to learn scene2d and I'm having trouble getting a sprite/Actor to move when a key is held down. I've tried a few different methods but I can't seem to figure it out. This is the code I currently have, which moves the actor everytime i press the key but not when it is held down.

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);
    }


}

Solution

  • I'm not really sure if actor has a focus on itself to handle KeyUp/Down events and that's why I would avoid using listeners to move player.

    Also changing the actor's position does not need actions - there is a simple setPosition() method in Actor class. You have also getX() and getY() methods to get current position of actor.

    What would i do would be to check if any Key is down (by using Gdx.input not lisetners) and set position modified by some defined step like:

    //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());
    }
    

    the act() method is called in every render (if you are calling stage's act of course) so the movement will be continuous.