アクションRPG Day4 アニメーション

f:id:naosim:20181010064547p:plain

前回はプレイヤーを表示しました

naosim.hatenablog.jp

ただ動かした時にアニメーションがなかったので今回はそれを追加します
アニメーションを追加ためにクマが「右方向に歩く絵」と「左方向に歩く絵」が必要なので、プレイヤーの画像を変更しました

http://jsrun.it/assets/W/0/B/U/W0BU0.png

preloadで読み込む画像の変更

プレイヤーの画像を変更します

this.load.spritesheet('player', 'http://jsrun.it/assets/W/0/B/U/W0BU0.png', { frameWidth: 32, frameHeight: 32 });

Player.create()でアニメーションを定義する

class Player {
  ...
  create() {
    this.sprite = this.scene.physics.add.sprite(32, 32, 'player');

    // ここにアニメーションの設定を追加する    
  }
  ...
}

上記のコメントの部分に下記の4つのアニメーションを追加します

  • 右向きに立ってる絵
  • 左向きに立ってる絵
  • 右向きに歩いている絵
  • 左向きに歩いている絵

右向きに立ってる絵

this.scene.anims.create({
  key: 'turn-right',
  frames: [ { key: 'player', frame: 4 } ],
  frameRate: 20
});

this.scene.anims.createのドキュメントはこれ
Phaser 3 API Documentation - Class: AnimationManager
引数: AnimationConfig
keyには適当な名前をつける
frameに渡す整数は画像をframeWidthとframeHeightで分割した状態で左上から数えた数
今回の画像の場合、右向きの絵は左から5番目で数値はゼロオリジンなので4を指定する

左向きに立ってる絵

考え方は右向きと同じ

this.scene.anims.create({
  key: 'turn-left',
  frames: [ { key: 'player', frame: 3 } ],
  frameRate: 20
});

右向きに歩いている絵

this.scene.anims.create({
  key: 'right',
  frames:this.scene.anims.generateFrameNumbers('player', { frames:[ 5, 4, 6, 4] }),
  frameRate: 10,
  repeat: -1
});

framesの指定でgenerateFrameNumbersを使う
generateFrameNumbers

framesで指定した順番に絵をアニメーション表示してくれる
このメソッドが何を返してるのかが気になったので、戻り値をログ出力してみたらこんなオブジェクトを返してた

[
  {key: "player", frame: 5},
  {key: "player", frame: 4},
  {key: "player", frame: 6},
  {key: "player", frame: 4}
]

要するにただのファクトリメソッドみたいw

frames: [5, 4, 6, 4].map(v => ({key:'player', frame: v}))

これでええやん
まぁいいや

左向きに歩いている絵

ほぼ一緒

this.scene.anims.create({
  key: 'left',
  frames:this.scene.anims.generateFrameNumbers('player', { frames:[2, 3, 1, 3] }),
  frameRate: 10,
  repeat: -1
});

createメソッドの最終形

class Player {
  ... 
  create() {
    this.sprite = this.scene.physics.add.sprite(32, 32, 'player');
    this.lastDirection = 'right';
    
    this.scene.anims.create({
      key: 'turn-right',
      frames: [ { key: 'player', frame: 4 } ],
      frameRate: 20
    });

    this.scene.anims.create({
      key: 'turn-left',
      frames: [ { key: 'player', frame: 3 } ],
      frameRate: 20
    });

    this.scene.anims.create({
      key: 'right',
      frames:this.scene.anims.generateFrameNumbers('player', { frames:[ 5, 4, 6, 4] }),
      frameRate: 10,
      repeat: -1
    });

    this.scene.anims.create({
      key: 'left',
      frames:this.scene.anims.generateFrameNumbers('player', { frames:[ 2, 3, 1, 3] }),
      frameRate: 10,
      repeat: -1
    });
  }

  ...
}

Player.update()でアニメーションを設定する

先ほど定義したアニメーションを動作に合わせて設定します

update () {
  if (this.cursors.left.isDown) {
    this.sprite.setVelocityX(-160);
    // 左向きに歩くアニメ
    this.sprite.anims.play('left', true);
    this.lastDirection = 'left';
  } else if (this.cursors.right.isDown) {
    this.sprite.setVelocityX(160);
    // 左向きに歩くアニメ
    this.sprite.anims.play('right', true);
    this.lastDirection = 'right';
  } else {
    this.sprite.setVelocityX(0);
    this.sprite.anims.play(this.lastDirection && this.lastDirection == 'left' ? 'turn-left' : 'turn-right');
  }

  if (this.cursors.up.isDown) {
    this.sprite.setVelocityY(-160);
  } else if(this.cursors.down.isDown) {
    this.sprite.setVelocityY(160);
  } else {
    this.sprite.setVelocityY(0);
  }
}

アニメーションを再生するplayメソッドの仕様はこれ
play(key [, ignoreIfPlaying] [, startFrame]) 今の実装ではupdateが呼ばれるたびに毎回playメソッドをコールするので、playメソッドの第2引数のignoreIfPlayingをtrueにしておきます
そうしないと例えば右ボタンを押してる時はupdateのたびに右・右・右...と実行されるので、画面上は右に歩くアニメの1フーレム目がずーっと表示されることになり、歩く感じになってくれません
ここらへんをフレームワークで吸収してくれるのは助かるなぁ

以上

jsdo.it

プレイヤーが左右に歩くアニメーションができました
次回は壁の衝突判定をやります