javalibgdx2dentity-component-system

libgdx ashley - How do I control a player the proper way (ECS framework)?


What I have tried In the option 1, I created PlayerControlled classes to control a player (It's working properly). But I don't want the way I control a player like this, I have doubt it is not the proper way.

// Option 1
class PlayerComponent implements Component {
     // player data here
}

class PlayerSystem extends IteratingSystem {
     // player logic here
}

class PlayerControlledComponent implements Component{
     // Player entity
}
class PlayerControlledSystem extends IteratingSystem {
     // Keyboard Input
     // Player entity
}

// Option 2
engine.getSystem(PlayerSystem.class).attack()

// Option 3
class PlayerController {

     PlayerConroller(Player player) {

     }

} 

Both option 1 & 2 are tested and working, option 3 is just an idea.

Question


Solution

  • I use a three layer approach: (pseudo code)

    Layer 1:

    Some class that handles the raw input coming from InputProcessor libgdx class like this:

    public interface InputHandlerIF {
        void walk(int playerId, Vector2 direction);
        void jump();
        .....
    }
    
    
    class RawInputHandler implements InputProcessor {
    
        private InputHandlerIF listener;
        private Vector2 direction;
        onKeyDown(int keycode) {
            if(keycode == W) {
                direction = valueToWalkForward;
                listener.walk(playerId, direction);
            }
        }
    }
    

    So all raw input coming from libgdx framework is handled and translated to an actual game command like: walk, shoot, castSpell, etc. This layer allows you to filter input before it gets passed to the InputHandlerIFs: F.e. controller number in a local multi-player game.

    Layer 2:

    Then I have this a kind of command handler system which receives the commands:

    public class InputHandlerSystem extends EntitySystem implements InputHandlerIF {
        public walk(int playerId, Vector2 direction) {
            positionComponents.getForPlayer(playerId).direction = direction;
        }
    }
    

    The systems knows all positionComponents of the player(s) and updates the values accordingly.

    Layer 3:

    PlayerMovementSystem which also knows the positionComponents and updates the players position (x and y) based on the time delta and positionComponent.direction value.

    class PlayerMovementSystem extends IteratingSystem {
        update(float delta) {
            ... update player position
        }
    }
    

    Setup would look like this:

    Engine engine = new Engine();
    InputHandlerSystem ihs = new InputHandlerSystem();
    RawInputHandler rih = RawInputHandler();
    rih.registerListener(ihs);
    engine.addSystem(ihs);
    enigne.addSystem(new PlayerMovementSystem());