ゲームで使えそうなアニメ管理クラスを作ろう(2D)

むぉ・・・また忙しくってきた・・・
毎日眠いね・・・チクショー!!

あー,そういや携帯を新しいのに替えた.
Naoにとって,これは意外と大ニュース.なぜなら,以前の機種はP203だったから.
なにしろ4年も使ってたからにゃー・・・
メールはおろか,「漢字」も使えなかったからにゃー・・・
画面に10桁までしか表示できなかったから,11桁の携帯の電話番号は表示しきれなかったぜ.
おかげで,「ソレ,テレビのリモコン?」とか「うわ,トランシーバーだ!」とか馬鹿にされずに済むー!!


さて,今回はゲームで使うアニメーション用のクラスを設計しましょ.
最初は,「アニメなんかキャラに制御させとけば? わざわざクラスにしなくていいじゃん?」
とか思ってたけど,キャラの制御といっしょにアニメの制御を書こうとすると,これが意外とめんどくさいのなんの.
しかも見づらくなるし,バグは出るしで・・・(T_T)

じゃ.仕様を考えまひょ.
とりあえず,アニメはスクリプトで管理したいにゃー・・・(後々楽だから)



[ スクリプト仕様 ]

[Anim ID]
アニメID指定コマンド
「ID」に番号を書くことでアニメを指定します.
番号は1〜63まで使用できます.0は使用しません.
(うーん,格ゲーには少ない気もするけど,プログラムで簡単に拡張できるからいいか)

sprite time x y flag
スプライト表示コマンド
「sprite」に表示したいスプライトの番号を指定します.
「time」spriteを何フレームの間表示するかを決めます.
「x」「y」スプライトを基準点からずらして表示するためのオフセットを指定します.
「flag」左右反転などのフラグを指定します.

LOOP
ループ指定コマンド
「LOOP」と記述があるアニメは,ループします.
すなわち,最後のスプライトを表示し終えた後,自動的にアニメの先頭に制御が戻ります.

例:
[anim 1] ;歩きアニメ(自動ループ)
LOOP
0 4 0 0 0
1 4 0 0 0
0 4 0 0 0
2 4 0 0 0

[anim 2] ;ジャンプアニメ(自動ループ)
LOOP
4 2 0 0 0
5 2 0 0 0

[anim 3] ;攻撃アニメ 
6 2 0 0 0
7 4 0 0 0
8 2 0 0 0



[ アニメ制御クラス仕様 ]

アニメデータ読込み
アニメデータとは,スクリプト記述したテキストです.(現段階では)

アニメ変更機能
アニメIDを指定することで,アニメーションを変更します.

アニメ実行機能
1フレームに1度呼び出すことで,アニメ処理を行います.

各種データ取得
取得できるデータには,「スプライト番号」「オフセット値」「フラグ値」「アニメが完了したか?」「現在のアニメID」 くらいでいいかな?
ちなみに,アニメにループ指定がある場合は,「アニメが完了したか?」は常にTRUEを返します.


んで,実際に設計.

アニメロード用クラス
アニメロード用のクラスをインタフェースを共通可しておくことで,後で「バイナリから読み込もー」と思ったときに クラスを入れ替えるだけ簡単に変更できます.

-AnimLoaderクラス-


一応これで,スクリプトを読み込むことはできますが,エラーチェックを全くしてないので, 間違いのあるスクリプトは読み込めません.エラー処理はちゃんとしましょうね.


アニメを実際に実行するクラスです.内部にAnimLoaderクラスを持っていて,AnimLoaderに一旦 アニメデータを読み込ませ,そこから必要なデータをコピーします.


アニメ再生用クラス

-AnimPlayerクラス-

これの使い方としては, とりあえず,キャラクタのクラスにAnimPlayerを持たせます.(今回は AnimPlayer m_Anim ; と宣言). その後はこんな感じです.

[ 初期化部分 ]
 
m_Anim.LoadAnimFile( "filename" );

[ 1フレームに1度呼ばれるキャラクタ制御部分 ]
void Character::MoveProc()
{
  m_Anim.DoAnim(); // つまりここも1フレームに1度呼ばれます.

  if ( .... )
  {

  }
  else if (....)
    m_Anim.ChangeAnim( ANIM_JUMP ); // ChangeAnim を使ってアニメを変更します.
  } 
  else if (....)
  {
    if ( m_Anim.IsComplete() ) // アニメが完了したら・・・みたいな使い方もできます.
    {
      ChangeState();
    }
  }


  //---- 表示するスプライトを指定します.
  patnum  = m_Anim.GetPatnum();
  offsetx = m_Anim.GetX();
  offsety = m_Anim.GetY();
  flag    = m_Anim.GetFlag();
}


みたいな感じで勝手にアニメやってくれるので,プログラマが気にする部分は,ChangeAnim() の使いどころと, IsComplete()を使って,他の状態に遷移したりするところぐらいかなー・・・



・・・実は,これには重要な問題点があるのよね.
シューティングとかアクションみたいに, 同じキャラが複数つくられる場合,同じ Code データが重複するので無駄が多くなってしまいますねぇ.
それに,シューティングでは頻繁にキャラの変更が起きる場合,ファイルを読み直さないと他のキャラとして扱うことができないので, 時間的にもイケてない仕様になってしまいました.
(まぁ,格ゲーみたいに,キャラ変更が頻繁に起きない場合とかには問題ないんだけどね.)

というわけで,次回は Code を共通化させることで,この問題を解決してみたいにゃー・・
(多分 static なメンバ変数とかにするだけだろうにゃー・・・)



<< Back to Diary...