2020-09-14

[101] 一枚絵をスクロール - アニメーション

Bevy ゲームエンジン

  ちょうど100回目の記事……と思ったのですが、今後はBevy関連の記事が増えていくように思ったので、100回目に当たる記事はBevyのページにしました。
  今回は簡単なアニメーションコードの解説をしたいと思います。

add_system

  指定した関数を.system()でSystem型に変更し、stageに追加します。stageはScheduleによって順に関数を実行していく仕組みであり、Scheduleとはstageの集合で、Bevyアプリにてframe毎に1回ずつ実行されます。簡単に言ってしまえばadd_systemにて追加された関数は、フレームごとに1回ずつ処理されることになります。ゲームやアニメの「1コマ」ごとにさせたい処理を追加するということです。前の記事でも書きましたが「ここまでは土台」とありますが、これは今回の記事でのメインのコードではなく、コード自体を動かすのに必要なコードのため、詳細には触れていません。

TextureAtlas

  複数の画像を結合し効率化する仕組み。Bevyのドキュメントにはまだこの解説は書かれていませんが、恐らく実際も近い解説になると予測されます。

add_startup_systemとadd_system

  全体の構造を見ると、このコードは「setup関数」を定義しadd_startup_systemにてstartup system(アプリ起動時に1度だけ実行される)に追加、「animate_sprite_system関数」を定義しadd_systemにてstage(フレーム毎に1回ずつ処理を行う)に追加しています。
  不思議なのはsetup関数もanimate_sprite_system関数も定義こそされていますが、引数を受け取っていません。.system()によってSystem型に変更され引数として渡されているだけで、なぜか動いています。Rustの基礎を終えたばかりでこのコードを目にした方は(あるいはこの手のコードを始めて見られる方も含め)面食らうかと思います。
  これはBevyがECSであることと深く関わりのあることで、恐らく結構大掛かりな解説になり(加えて私自身も丁寧に説明できるほどには十分に理解しているわけではないため)、適切な解説ページを見つけたらご紹介したいと考えています。
  登録された関数は、それが使われる際に適切な引数が与えられ、適切な対象に対し、適切なタイミングで実行されます。最初に実行されるsetup関数にて各設定処理が行われ、その後フレームごとにanimate_sprite_systemが実行されます。animate_sprite_systemは毎回forにてtimer.finishedでfrom_secondsで設定した秒数が経過しているかをチェックし、その都度、indexをずらすことでfrom_gridで分割した画像を順にずらしながら表示しています。

sprite.index = ((sprite.index as usize + 1) % texture_atlas.textures.len()) as u32;

は、分割数で割った余り(%)を返すことでリピート表示を実現しています。7分割であるなら、7で割った余りである0~6のindex値が返ることになります。

コード解説記事は今後も

  私自身、現在は手探りでやっています。本当はもう少し深く解説できるところまで分析するのも手なのでしょうが、今は一通り全体像を把握しておきたいので、ドキュメントのない今は、分かる範囲で進めていきたいと考えています。チリも積もればで、細かい技術情報を少しずつ理解しながら近々簡単なゲームでも作れるところまで行ければと期待しています。Godotレベルのわかりやすいドキュメントの充実まではまだまだ時間がかかるかと思いますし、そもそもRustがGodotより簡単に扱える日は来ないようにも思うので、わからないままにコードの分析を続けていくのもいい勉強になるのではとも思っています。