1

学校で大きなプロジェクトがあり、libGDX を使用して Pixel Platformer ゲームを開発しています。

ほとんどの部分で ECS を使用していますが、プレーヤーの状態または少なくとも攻撃の状態を区別できないため、プレーヤーのアニメーションのレンダリングに問題がありました。

プレイヤー状態クラス

ちょっとお見せしましょう、だから私はこの「動き」の状態を持っています:

public enum PlayerState implements State<PlayerAgent> {

Idle(){
    @Override
    public void update(PlayerAgent agent) {
        agent.moveOnGround();
        if(!agent.isTouchingGround) {
            if (agent.body.getLinearVelocity().y < -0.05)
                agent.stateMachine.changeState(Falling);
            else
                agent.stateMachine.changeState(Jumping);
        }else{
            if (agent.body.getLinearVelocity().x != 0)
                agent.stateMachine.changeState(Walking);
        }
    }
},

Walking() {
    @Override
    public void update(PlayerAgent agent) {
        agent.moveOnGround();
        if(!agent.isTouchingGround) {
            if (agent.body.getLinearVelocity().y < -0.05)
                agent.stateMachine.changeState(Falling);
            else
                agent.stateMachine.changeState(Jumping);
        }else{
            if (agent.body.getLinearVelocity().x == 0)
                agent.stateMachine.changeState(Idle);
        }
    }
},

Jumping() {
    @Override
    public void enter(PlayerAgent agent) {
    }

    @Override
    public void update(PlayerAgent agent) {
        agent.moveOnAir();
        if (agent.body.getLinearVelocity().y < 0)
            agent.stateMachine.changeState(Falling);
        /* else if (agent.jumpOnAir())
            agent.stateMachine.changeState(DoubleJumping);*/
    }
},

DoubleJumping () {
    @Override
    public void update(PlayerAgent agent) {
        agent.moveOnAir();
        if (agent.body.getLinearVelocity().y < 0)
            agent.stateMachine.changeState(Falling);
    }
},

Falling() {

    @Override
    public void update(PlayerAgent agent) {
        agent.moveOnAir();
        if (agent.isTouchingGround) {
            agent.stateMachine.changeState(Idle);
        } else {
            if (agent.stateMachine.getPreviousState() != DoubleJumping) {
                if (agent.jumpOnAir())
                    agent.stateMachine.changeState(DoubleJumping);
            }
        }
    }
};

@Override
public void enter(PlayerAgent agent) {
    // System.out.println(this.toString());
}

@Override
public void update(PlayerAgent agent) {

}

@Override
public void exit(PlayerAgent agent) {
    agent.timer = 0.0f;
}

@Override
public boolean onMessage(PlayerAgent agent, Telegram telegram) {
    return false;
}
}

Player Animations Enum

ただし、プレーヤーのアニメーションには少なくとも次の状態が必要です。

public enum PlayerAnimations {

 Idle, Walking, Jumping, DoubleJumping, Falling, Attack, JumpAttack, FallingAttack, FallAttack, Hit, Die;

}

このパックされたテクスチャには、さらに多くのものがあります: Player Animations Atlas

PlayerAgent クラス:

public class PlayerAgent implements Updateable {

    private Entity player;

    protected Body body;
    private TransformComponent transform;
    SensorCollisionComponent sensors;

    protected static StateMachine<PlayerAgent, PlayerState>  stateMachine;

    public boolean isTouchingGround = true;
    public boolean isTouchingWallLeft = false;
    public boolean isTouchingWallRight = false;

    public static float timer = 0.0f;

    public PlayerAgent(Entity player) {
        this.player = player;
        body = player.getComponent(B2dBodyComponent.class).body;
        transform = player.getComponent(TransformComponent.class);
        sensors = player.getComponent(SensorCollisionComponent.class);

        stateMachine = new DefaultStateMachine<PlayerAgent, PlayerState>(this, PlayerState.Idle);
    }

    @Override
    public void update(float deltaTime) {
        isTouchingGround = (sensors.numFoot > 0);
        isTouchingWallLeft = (sensors.numLeftWall > 0);
        isTouchingWallRight = (sensors.numRightWall > 0);

        stateMachine.update();

        if (!KeyboardController.left && !KeyboardController.right)
            body.setLinearVelocity(MathUtils.lerp(body.getLinearVelocity().x, 0, 0.2f), body.getLinearVelocity().y);

    }


    public static PlayerState getCurrentState(){
        return stateMachine.getCurrentState();
    }
    public static PlayerState getLastState(){
        return stateMachine.getPreviousState();
    }
    public static boolean isInState(PlayerState state){
        return stateMachine.isInState(state);
    }

    public boolean moveOnGround() {
        if (KeyboardController.left) {
            body.setLinearVelocity(MathUtils.lerp(body.getLinearVelocity().x, -3f, 0.1f), body.getLinearVelocity().y);
            transform.flipX = true;
        }
        if (KeyboardController.right){
            body.setLinearVelocity(MathUtils.lerp(body.getLinearVelocity().x, 3f, 0.1f), body.getLinearVelocity().y);
            transform.flipX = false;
        }
        if (KeyboardController.up) {
            body.applyLinearImpulse(0, 2.7f, body.getWorldCenter().x, body.getWorldCenter().y, true);
            KeyboardController.up = false;
        }
            return (KeyboardController.left || KeyboardController.right);
    }

    public boolean moveOnAir(){
        if (KeyboardController.left){
            body.setLinearVelocity(MathUtils.lerp(body.getLinearVelocity().x, -1.5f, 0.1f), body.getLinearVelocity().y);
            transform.flipX = true;
        }if (KeyboardController.right){
            transform.flipX = false;
            body.setLinearVelocity(MathUtils.lerp(body.getLinearVelocity().x, 1.5f, 0.1f), body.getLinearVelocity().y);
        }
            return (KeyboardController.left || KeyboardController.right);
    }

    public boolean jumpOnAir(){
        if (KeyboardController.up) {
            body.applyLinearImpulse(0, 2.5f, body.getWorldCenter().x, body.getWorldCenter().y, true);
            KeyboardController.up = false;
            return true;
        }
        return false;
    }

}

アニメーション コード

プレーヤーを処理する AnimationSystem のコード:

PlayerComponent pc = pm.get(entity);
                if (pc.attacking) {

                    switch (PlayerAgent.getCurrentState()) {
                        case Idle:
                        case Walking:
                            if(PlayerAgent.getLastState() == PlayerState.Falling) {
                                key = PlayerAnimations.FallAttack.ordinal();
                                if(ani.animations.get(key).isAnimationFinished(PlayerAgent.timer)) pc.attacking = false;
                            }else
                                key = PlayerAnimations.Attack.ordinal();
                            break;
                        case Jumping:
                        case DoubleJumping:
                            key = PlayerAnimations.JumpAttack.ordinal();
                            break;
                        case Falling:
                            key = PlayerAnimations.FallingAttack.ordinal();
                            break;
                        default:
                            key = PlayerAnimations.Idle.ordinal();
                            break;
                    }
                } else {
                    switch (PlayerAgent.getCurrentState()) {
                        case Idle:
                            key = PlayerAnimations.Idle.ordinal();
                            break;
                        case Walking:
                            key = PlayerAnimations.Walking.ordinal();
                            break;
                        case Jumping:
                            key = PlayerAnimations.Jumping.ordinal();
                            break;
                        case DoubleJumping:
                            key = PlayerAnimations.DoubleJumping.ordinal();
                            break;
                        case Falling:
                            key = PlayerAnimations.Falling.ordinal();
                            break;
                        default:
                            key = PlayerAnimations.Idle.ordinal();
                            break;
                    }

                }
                PlayerAgent.timer += deltaTime;
            }

Grounded -> Idle, Walking のような状態の中に状態を持たせることを考えていました。しかし、プレイヤーを AttackStates にする方法はまだわかりません。

4

1 に答える 1