2007年08月30日

アニメーション

ここでのアニメーションとはスプライトアニメーションなどのことを指している。
以後と言うか、以前もアニメーションと書いていたらこのことを指して書いている。
MPEG や AVI などはムービーと呼んで区別している。
その区別が一般的かどうかは知らないが、私はそう区別している。

アニメーション機能は前々から吉里吉里に追加できたらなぁと思っていたのと、また別のところで作る機会があったので(それとは別になるが)ライブラリとして作ることにした。
アニメーションを再生するライブラリは過去に何度も作っているが、どれもイマイチ。
そこで今回は少しはマシにものに出来ればと思っている。
主にPC用もしくはある程度CPUパワーがあるもの用と考えているので柔軟なものにしたい。

とまあ、今からはじめるように書いているが、実はもうある程度作っていたりする。
で、まったく何もブログにまとめていないので書いていくことにした。

投稿者 Takenori : 23:31 | トラックバック

2007年08月31日

アニメーションのデータ構造

アニメーションでは座標情報などの変化する値を保持する必要がある。
このような情報はどのように保持するか。

最もシンプルなものは、フレームを基準とし、全てのフレームでコピー元と先の座標などのデータを持つ構造ではないだろうか。
各スプライトの前後関係は、単純にデータの並びで表現する。
このような構造であればフレーム間の依存性はなくなり、任意のフレームをすばやく再生(表示)できる。
描画するほうも特に何かを考慮する必要はなく、単純にコピー元と先の座標を参照してその通りに画像をコピーすれば期待した表示結果が得られる。
難点はフレーム間の粒度が固定されてしまうことだ。
つまり、保存されているフレームレート以外のレートで再生しても、表示の速度が変わるのみで間は補間されたりしない。
考慮することや処理することは少ないのでかなり非力なマシンでは有用かもしれないが、今だとこの形はあまり使おうとは思わない。シンプルで楽なんだけれども。

もう少し融通が利くようにするには、スプライトを基準としたデータ構造にする必要がある。上記の方式はフレームがスプライトを持っているが、そうではなくスプライトがフレームの情報を持つ形。
そして、アニメーションデータはこのスプライトの集合を持つ。
この形であれば、スプライト単位での操作も可能となる。

スプライトを基準とした場合、フレームをどのように保持するかによってデータ構造は幾通りか考えられる。
1. 最初に挙げたフレームを基準とした方法のように、全フレームで全座標情報を持たせる方法。
2. いくつかのフレームをキーフレームとして、間のフレームは補間によって位置を決める方法。
この2つ以外にも考えられるが、
1.は最初に挙げたものと同じような特徴がある。ただ、スプライトが基準となっているので補間しようと思えば補間出来る。
ただし、その場合は2番目のキーフレームで補間するのと大差ない上に、データ量が多くなってしまうのであまり意味はない。
では、それなりマシンパワーがあるのならキーフレーム方式にしてしまえばいいのかと言うと、別の問題がある。
アニメーションを作るツールだ。
使用するツールがキーフレーム方式で且つ、キーフレームの情報を直接取れるのであれば、キーフレーム方式はすんなり使える。
しかし、そうでない場合使えないとはいえないが、全てのフレームでデータを持つのと等しくなってしまう。
キーフレームで情報を持つといっても、最終的にはフレームごとに位置などの情報が割り出されるわけで、全てのフレームでデータを持つ方法の方はどのようなツールからでもデータを作りやすい。
まあ、キーフレーム方式で全てのフレームをキーフレームとした場合は、そのキーフレームの時間情報分データ量が多くなるのと、フレームの割り出しにオーバーヘッドが伴う程度なので、それが問題ないレベルであればキーフレーム方式にしてしまった方が両方に対応できていい。
(全てのフレームでデータを持つ場合、単純な配列のインデックスとしてフレームを割り出せるのに比べて、キーフレーム方式場合は各キーフレームの時間で検索する必要があり、その分フレームを割り出すのに時間がかかる。当然キーフレームの量が増えればその時間は増加する。)

スプライトを基準とした場合キーフレーム方式とするかどうか以外にも、座標などの変化する各値が独立した状態で値を持つか、全ての値をまとめて持つかの2通りの持ち方が考えられる。
当然のことながら、各値が独立した状態の方が柔軟性がある。
ただし、データ量の増加と処理時間の増加がある。
データ量の増加は、それほど生じない可能性もある。各値が独立していれば、変化しない値は1つだけ値を持てばよい。これが全ての値をまとめて持つとなると、変化していない値も他の値が変化するのであれば保持しなければならない。
この事から一概に増加するとは言い切れない面もある。
処理時間は確実に増える。全ての値をまとめて持つ場合、フレームの検索は1度で済むが、独立していると、その種類の数だけ検索する必要がある。

今まで作ったアニメーション再生ライブラリは以上のデータ構造の組み合わせのいずれかになっていた。
ただし、最大限に柔軟性のある方式は選択したことがない。
そして今回はその方法で行こうと思っている。
つまり、スプライトがフレームを持ち、フレームはキーフレーム方式で、各値は独立している形。
少し重いかもと思わないでもないが、CPU速いし余裕だろう。

ani_dat_struct.png

投稿者 Takenori : 00:14 | トラックバック

2007年09月01日

範囲外のデータの取り扱い

各値を独立して保持する場合、全ての値の最初と最後のキーフレームの時間を合わせるか、範囲外の値の取り扱いについて考えておく必要がある。
全ての値の最初と最後のキーフレームの時間を合わせても良いが、範囲外の値の取り扱い方法を数種類決めておいたほうがいろいろと便利だ。
範囲外と言うのは、最初のキーフレームより前の時間と最後のキーフレームより後の時間のこと。
これらの時間の値を取得しようとした時、どのような値が得られるようにするか。

最も簡単なのは既定値を返すこと。( リセット )
他には……
端の値を返す。( コンスタント )
キーフレームを保持している区間を繰り返すような値を返す。( リピート )
キーフレームを保持している区間が折り返し再生されるような値を返す。( ミラー )
後、端の2値の変化傾向を継続するなども考えられるが、最大値や最小値などを考慮しないといけなくなるのと、大したメリットもなさそうなのでいらないかな。

と言うことで、範囲外の値はリセットとコンスタント、リピート、ミラーの4種類から選択できるようにすることにした。

投稿者 Takenori : 21:31 | トラックバック

データ構造、実装よりの話

データをどのように保持するかは少し前に書いた通りだけど、今回はもう少し実装よりの話。
時間と値の pair を vector に入れればいいと言えばいいんだけれど、それだけだと扱い辛い。
そこで少しラップする。

単純に1つのクラスで全部やってしまっても良いが、エンベロープとチャンネルの2段階に分けた。
エンベロープは時間と値のペアをコンテナに保持し、時間での検索や挿入などの操作を行うクラス。
チャンネルはエンベロープを継承し、範囲外の値の扱いや補間を行う。
つまり、チャンネルを通してアクセスすれば、任意の時間の値が取得できるのに対して、エンベロープでは存在するキーフレームの時間の値しか取得できない。

なぜ分けたかと言うと、直感的に…… と言う面もあるが、補間が必要ない値も扱うため。
値や時間はテンプレートを使って任意の型が設定できるようにしてある。

補間の必要がない値は、例えばラベルやマーカーなどと呼ばれるフレームに付ける名前のようなもの。
これらは瞬時値で、特定のフレームにしか値は存在しない。
このような値はエンベロープで保持すればいい。

補間方法は、とりあえず離散と線形補間だけ作った。
たぶん、スプライン系の補間も追加するが、なくてもいいので後にした。
離散は、次のキーフレームまで直前のキーフレームの値を維持するもの。
跳び跳びで移動するようなもの以外に、離散的な値しかないものを扱うのにも使う。
例えば、ブレンド方法などは数種類の中から選択するもので、種類と種類の間を補間することは出来ない。
また、画像データそのものも離散的な値。チャンネルに画像データを入れておけば、パラパラ漫画と言うかムービーと言うかそのようなものが表現できる。

この2つのクラスがあれば、アニメーションする値についてはほとんど事足りるはず。

投稿者 Takenori : 22:21 | トラックバック

2007年09月13日

親子関係

3Dであれば親子関係は必須とも言えるが、2Dの場合はなくても何とかなる。
でも、あったほうが都合の良い場面も多い。
再生側のみに限って言うのなら、子は親の座標系に展開してしまえば、結果的に表示される内容に変わりはない上に効率的 ( 座標の変換などが省かれる ) になる。
ただ、実行時に子の入れ替えなどが出来なくなる。
と言う事で、親子関係は入れようと思う。
ただ、厳密には親子関係というよりも入れ子というような形にする予定。
親子関係だと、何かスプライトがあって、それに他のスプライトが子の形で追従するというイメージだけど、考えているのは何か塊として動く子を入れられるというもの。
グループ化などで作られる塊のようなイメージ。

ただ、アニメの中にグループとして存在するような形ではなく、アニメの中に他のアニメへの参照を持っているような形にする。
コピーか参照かの違いとも言える。
再生する側からしたら、どちらでもほとんど違いはないので、参照のみにしてしまった方が楽。
ただ、参照だと再帰に気を遣う必要がある。
自己参照や間接的に自分を参照している場合、無限ループに陥るのでそれをチェックしないといけない。
で、少し考え中なのが何段階まで許可するか、もしくはまったく許可しないか。
再帰は、まったく同じ位置に描くと意味がないので、位置を移動させたり、縮小などして再帰する。
そうすると、収束する段階が存在するから、そこで打ち切れるのが理想 ( 同じ位置に描いても、拡大と縮小を繰り返しても収束する(変化がなくなる)段階は存在するはず ) 。
でも、そこまでするのは大変なので、再帰限度を設定しそこで打ち切るようにする形にしようと考えている ( 完全に禁止にするかもしれないけど )。

そもそも、親子関係があるとどうなるかとか書いてなかったけど、まあいいか。
一般的なものということで。

アニメでも表現できるが、コマアニメと複数のスプライトをまとめたものを特別扱いするかどうかも考え中。
単純に時間軸方向に並べたものと、時間固定で並べたものってだけなのだが。
少しだけ効率的に扱えるってだけだけど、特別扱いすることにしよう。

投稿者 Takenori : 00:56 | トラックバック

テキストファイルフォーマット

ファイルフォーマットは、テキスト形式とバイナリ形式を考えている。
テキスト形式はほぼ決めていて、XML 形式にしようと思っている。
SVG + SMIL を参考にしているが、だいぶ違う形と言うか全然違う形になる予定。
同じところは単に数値列がセミコロン区切りなぐらいかも。
はじめはカンマ区切りにしようと思っていたが、カンマだとドット見分けづらいかと思って SVG + SMIL にならってセミコロンにした。
見比べるとどっちもどっちなのだが。( "0,1,2,3.4,5" "0;1;2;3.4;5" )

投稿者 Takenori : 22:35 | トラックバック

2007年09月14日

バイナリファイルフォーマット

バイナリファイルフォーマットは、読み取り専用のフォーマットとして考えている。
編集などは考慮せず、実行時に効率的に再生できるようにあらかじめ必要なデータを生成しておく。
また、画像などのデータもまとめてしまうことを考えている。
バラバラでも良いけど、固まっていたほうが取り扱いが楽なので、一つにまとめる。
これは動的読み込みのことも考えてこのようにしようと思っている。

投稿者 Takenori : 10:46 | トラックバック

読み込みタイミング

今まで作ったアニメーションライブラリでは、あらかじめ全ての画像が読み込まれていることが前提としてあったが、今回は動的な読み込みも考慮しようと思っている。
ただ、アニメーションの移動データなどは最初に読み込んでしまう予定。

読み込みタイミングとして考えているのは3つ。
最初にすべての画像を読み込んでしまう形。
必要になったその時に画像を読み込む形。
少し先のフレームまで画像を先読みする形。

大体は最初に全て読み込んでしまえば事足りると思う。
デバッグ時などは必要になったその時に画像を読み込む形でも問題ない。
少し先のフレームまで画像を先読みする形があると、大量の画像を使うアニメーションが実現できる。
そして、これはあることが実現できる可能性に気付いたのでこうした。
それは、アルファ付きムービー。
アニメでは、通常の画像とアルファ画像を別に指定できることも考えている。

圧縮効率は悪くなるが、ムービーはアニメーションで表現できる ( 変化する箇所のみをアニメで作れば事情は変わるが )。
動的に読み込む機能も持たせれば、ほとんどムービーと同じように再生できる。
圧縮効率の面で劣るため、どの程度利用範囲があるかはわからないが、専用のフォーマット ( と言っても実態はモーションJPEGやPNG ) があると言うのは悪くない。
また、ムービーの場合、位置などは変化しないため、これを特別扱いすれば効率的に再生出来る。
コマアニメを特別扱いすることにした理由にはこのこともある。

投稿者 Takenori : 10:57 | トラックバック

2007年09月15日

データ作成のためのツール

アニメーションを再生するためのライブラリだけがあっても何の意味もなく、そのアニメーションを作るアプリケーションが必要です。
このようなアプリケーションは独自か汎用になるわけですが、今回は両方に対応出来たらなと思っています。
でも、主体は独自ツールです。
独自ツールであれば、組み込む機能を最大限利用できます。
ただ、ツール開発にかなり時間がかかってしまうのが難点です。
その上、汎用ツールよりも使い勝手が劣ることが多いです。
そういった意味では汎用のツールからデータを持ってこれるのは強いです。
ここで言う汎用のツールとは、Adobe After Effects、Adobe Flash、Macromedia(Adobe) Director などです。って、全部 Adobe か。
他に Sprite Studio などもありますね。

Flash は一応ファイルフォーマットが公開されていますし、Director はプラグインと Lingo スクリプトを使えばデータを取れます。
After Effects はよく知りませんが、使っていると聞いたことがあるので、何かしらデータを取る方法があるのでしょう。
Sprite Studio は全然知りません。
この中で Director については、実際にプラグインを作ったことがあるので、対応することはそんなに大変ではないですが、Director が高いのでそこがネックです ( 誰か下さいな(笑) )。
Flash はもう一度ライセンスをよく読んで考えないとまずそうです。
他は要調査ですね。まあ、自分は使わないので、調査する可能性は薄いですが。
ツール自体も高いですし。

上記のツール以外に 3D 用のツールも使えなくはないです。
板ポリにテクスチャ貼ったのを作るようにすれば良いわけですから。
で、その候補ですが FBX に対応すればほとんどのツールから持ってこれると思っています ( 希望的観測 )。
FBX は SDK が公開されているので、それを利用すればデータを取れます。
FBX Info Viewer とか、なにげに作ってたりしますしね。
後、気まぐれで Light Wave 3D にも対応するかもしれません。
理由は単純で、以前コンバーターを作ったことがあるからです。

と言うことで、現実的な線は、独自ツール、Flash、Light Wave 3D、FBX ですかね。
ああ、SVG + SMIL もあるか。
まあ、独自ツールと Light Wave 3D 以外はだいぶ望み薄ですが、そんなことを考えています。

投稿者 Takenori : 21:23 | トラックバック

2007年09月16日

演出とかを組む話

なんか演出に関する話題が周りであったようなので、その辺りの話について。

まずは昔話から。
最初に働き始めた職場では、はじめからアニメはツールで作って、プログラマは呼ぶだけという形になっていました。
なので、私は特にその形について違和感はなく、そういうものと認識していました。
しばらくして私にアニメーション周りをデザインする機会が与えられ、その時にもアニメはデザイナーが作って、プログラマは呼ぶだけと言う形が好ましいと言われました。
そして、そのような作りにしました。

プログラマが演出に立ち入る必要性がある時は、以下のようなケースがあると思います。
・ツールで作ったら莫大なパターンが必要な時
・ツールで実現できない演出を組む時
・インタラクティブ性を必要とする時

莫大なパターンと言っても、パターンと言う言葉が指すようにそこには規則性があります。
最初はこのパターンについては特に考えていませんでしたが、次第にこの問題を解決できればさらに効率化できるのではないかと思うようになりました。
このようなアニメーションで、気付いているパターンは2つ。
実体の差し替えとオフセットです。
実体の差し替えは、単に絵が違うだけのようなものを指しています。
オフセットは、アニメーションの開始位置が違ったり、拡大率が違ったり、反転していたりと言うようなものです。
最初はこれをまずツールで汎用スプライトを作れるようにして、プログラム側からその汎用スプライトの中身を指定してやることで実現しようとしていました。
オフセットは、入れ子もしくは親子関係が出来れば、この汎用スプライトにアニメを入れることで実現できます。
そして、その時は汎用のツールでアニメーションを作っていました。
なのでプラグインを作ってから実機で再生できるように持って行こうとしていたのですが…… 開発期間の問題で実現しませんでした。

改めて考えればこれはもっと簡単な方法で実現できることがわかりました。
単にスプライトに識別のための情報を付与してやれば良いのです。
識別のための情報があれば、アニメーションを再生するプログラム側で一工夫してやるだけでこの問題は解決できます ( 識別のための情報は、以下タグと呼ぶことにします ) 。

アニメーションを描画する時、いわゆる Draw( frame ) と言うようなメソッドを実装してやればよいのでしょうか?
私ははじめそのように考え、その通りに実装していました。
ですが、今はそのようには実装していません。
代わりに traverse と言うメソッドを実装しています。
traverse メソッドにはフレームと関数オブジェクトを指定してやり、そのフレームにインスタンスのあるスプライトすべてを順に、渡された関数オブジェクトにスプライトの情報を渡して呼び出します。
もし差し替えたいスプライトがあるのなら、そのスプライトにタグを設定し、この関数オブジェクト内でそのタグに出会った時に別のスプライトを描画してやれば済みます。
特に何もする必要がない時は、単に描画するだけの関数オブジェクトを渡します。
関数オブジェクトでは、再帰的に traverse をコールすることも可能なので、入れ子になったアニメーションも実現できます。
また、アニメーションのデータは描画すること以外にも使えます。
代表的な例は当たり判定です。
関数オブジェクトを判定用のものにすれば、容易に実現できます。
この場合、タグの値はマスクを意識して設定しておきます。
当り判定は、すべてのスプライトを対象として欲しい状況よりも、特定のスプライトのみを対象としたい場合が多いです。
この場合、当たり判定用の関数オブジェクトがマスク値を保持できるようにしておき、それによってマスクすることで対象を見分けることが可能です ( 例えば、マスク値が 0x0F なら 1~15までのタグ値を持つものにのみヒットする ) 。
アクションやシューティングじゃないので当たり判定なんて使わないかと言うと、マウスでのクリックやタッチスクリーンで触れられた時などに、どのスプライトがクリックされた ( 触られた ) かを見分けたい場面などでも使えます。
そうすれば、メニューなどはある程度アニメーションで組めます。

で、残りの2つ。
・ツールで実現できない演出を組む時
・インタラクティブ性を必要とする時
ですが、これまではこのことについて特に何とかしようと考えたことはありませんでした。
そもそも、インタラクティブ性はそのためにプログラムがあると思えますので。
ただ、ある程度のパターン化は可能だと思います。
パターン化が可能であれば、それらをあらかじめ作っておくことでツールへその指定を持っていくことが可能です。
でも、今回もこのことについては積極的に取り組もうとは今のところ考えていません。
そして最後。
ツールで実現できない演出については、独自ツールで解決していく方向を目指しています。
つまり、最初はプログラムで組まれたものであっても、次回もしくはそれ以降はツールで対応しパラメータを設定してやることで、アニメ呼び出しで一発にするということです。
こういうことは汎用のツールでは難しいです。

アニメをツールで作ってプログラムもしくはスクリプトでアニメ呼ぶだけと言うのはかなり楽です。
ツールで見ながら調整し、出来たものを呼べばいいだけなので、プログラムで微調整しながら何度も何度も確認、調整して行くよりも遥かに楽です。
使えばわかりますが、プログラムで何とかしようと言う気がかなり失せます。
ですが、このような環境がないところが多いのも事実のようです。
実際に Excel や Word で指示された位置へプログラムで表示するように組んでいたこともあります。かなりやってられない気分でしたが、このような環境を構築する工数がなく、とにかく日々忙しさに忙殺されていました。
また、聞いた話ですが座標などのデータを紙で手渡されて、それを組み込んでいくところもあるようです。
そして、もうひとつの問題がツールのコストです。
Director、Flash、After Effects はかなり高いです。
デザイナーさんが使うのなら問題ないと思いますが、プログラマにまで行き渡るようにするとそれなりにコストがかかります。

このような状況を打破する方法はひとつ。
自分で両方作ってしまえっ!です。
ツールと再生ライブラリがあればやってられない状況は回避できます。
汎用的に作っていれば、ポーティングもしやすいはずです。

で、実際にどのくらいかかるの?って話ですが、独自ツールを作り出すと底なし沼にはまっていきます。
それなりに使えるレベルにするのには1ヶ月ぐらいは見ておいたほうが良いと思います。
再生ライブラリは、すぐに出来ます。
アニメファイルが再生しやすいように設計されたバイナリフォーマットであれば、2日もあれば再生できるようになります。
汎用ツールはその調査にかなりの時間をとられます。
一度作ったことがあればまだしも、初めてとなると大変です。
この調査の時間はどれぐらいかかるとは言いづらいですね。
まあ、はじめは多難な道であることは間違いないです。

と言うようなことが、このアニメーションライブラリを作り始めて、作っている時 ( 今 ) の話ですね。
で、その後の話。
完成したらどうしようと思っているかです。
再生ライブラリやファイルフォーマット、コンバーターなどはBSDライセンスで配布します。
ツールについてはフリー版とシェアウェア版を作ろうと考えています。
とは言っても、フリー版は今開発で使っているものよりも高機能なものを目指しています。
つまり、フリー版で何も問題なく作れるようなものです。
で、シェアウェア版は趣味の領域です。
少しは差別化しようとは思っていますが、シェアウェア版買ってくれないところで作業することも考え、フリー版でも普通に作れるようにしようと思っています。
じゃあ、何のためのシェアウェア版かと言うと、みんな買ってくれて他の仕事減らせてツールの充実に時間を使えたらいいなぁと言う無謀な期待を抱いているせいです。
みんな使うんだから少しずつお金出して誰かに任せられないかと言う道の模索でもあります。

投稿者 Takenori : 22:34 | トラックバック

2007年09月21日

リアルタイム - ツールの話

ある時デザイナーさんの言った一言で、私がツールを作る時いつも気を使うことがある。
それは「リアルタイム」ということ。

何かを作る時、編集(作成)→確認→修正(編集)→確認 を繰り返すので、この編集と確認、確認と編集の時間が短縮できればそれだけ効率が上がる。
出来れば、編集と同時に結果が見える方が良い。
例えば、HTML エディタなどで WYSIWYG なのと、テキストエディタで書いた後、ブラウザで確認するのでは効率が全然違う ( 関係ないけど、私は直接 HTML を書きたいタイプなので、ブラウザ表示結果、WYSIWYG エディタ、テキストエディタが同時に表示されている 3ペインのが好き ) 。

このようなことをあまり考えていないツールだと、連動すべきデータが連動せずに、なぜか更新ボタンを押さないと結果が反映されないとかいう結果になってしまう。
完全に同期を取るのが難しいって場合もあるんだけど、そこは何とかして欲しいし、自分は何とかしたい。

ここまではまあ実現しやすい話だけど、確認→修正(編集)の短縮は少し難しい。
ゲームを実行していて、おかしな部分を発見したら、ゲームをその場で止めて、その画面上で直接編集するというようなこと。
VC を使っていて、初めてエディットコンティニューを見た時、「えっ、そんなん出来るんですか?」と吉本新喜劇ばりに思った。
設計が複雑になることは想像できるが、ゲームの方が実現しやすいことのようにも思う。
少なくとも、実行時にデータのリロードが出来て、変更したデータをある程度見たい場面で反映できるといいなと思う。
デバッグモードで直接その付近に飛べるようにしたり、やたらセーブしまくって近くのセーブポイントから見るよりも効率的にしたい。
まあ、まだまだ妄想だけれど。

投稿者 Takenori : 23:13 | トラックバック

演出パターンカタログ

演出のパターンカタログが出来ないかと前から思っている。
「○○のあそこみたいな演出」的な表現をすることが時々ある。
また、似たような演出というのはよく目にする。
それらをカタログ化できれば便利ではないだろうか?
整理されたDBがあり、ビデオでどんな感じか見ることが出来れば、それだけでもかなり便利なように思う。

また、アニメーションのエディタなどでテンプレートとして利用でき、対象を設定していくだけで同じようなものが出来るとすれば、かなり省力化できるのではないだろうか?
素人が適当に作ってもそれっぽくなり、知っている人が使えばより効率化できる。

まず、カタログとしてまとめるのが面倒臭いが、そういうのが出来ればいいなぁと密かに思っている ( おもいっきり書いてしまってるが )。

投稿者 Takenori : 23:43 | トラックバック

2007年10月02日

動的再読み込み

画像データへは直接参照を保持するのではなく、画像データのプロクシの参照を保持するようにしています。
これは読み込みタイミングをずらせるようにするためです。
つまり、アクセスされた時に初めて画像を読み込むようにしたり、いらなくなった時に開放したりするためです。

以前書いたように、アニメーションデータは描画時などの必要時に参照されるのみで、他との関連は薄くなっています。
そのため、次のフレームに切り替わった瞬間に別のデータになっていても問題ありません。
ただ、どのファイルのどのアニメーションの何フレーム目かを保持しているオブジェクトは存在するはずなので、アニメーションにも画像同様プロクシが必要となります。

このような構造になっていれば、データが変更された時に、現在プロクシが保持しているデータを破棄する方法を提供することで、実行時に変更されたデータを反映することが出来るようになります。
これが出来れば、ゲーム実行中におかしな画像やアニメに気付いた時、修正した後、即座にその修正を確認できます。

上記の方法によって修正の確認を出来るのは良いのですが、どのデータを修正したら良いのかを調べる手間を軽減する手段が提供されていれば、もっと早く修正できるはずです。
これはさほど難しいことではなく、現在描画されているのがどのファイルのどのアニメーションの何フレーム目かを外部へ伝える機能があれば事足ります ( ShellExecute などで他アプリの引数にそれを渡すだけで十分です )。
さらにツール側で、指定されたファイルの指定されたアニメーションの指定されたフレームを開く機構が用意されていれば、もっと楽です。

これらが出来たなら、ゲーム実行中におかしな画像やアニメに気付いた時、ゲームで何らかの操作をしてアニメ編集ツールを起動。
データを修正して保存。
ゲーム側で画像とアニメの開放とリロード実行。
とすることで、確認→修正→確認がすばやく出来るようになります。

ということで、これぐらいは実現出来る機能を実装したいと考えています。

投稿者 Takenori : 20:15 | トラックバック

2007年10月03日

周辺を実装中

アニメーションのコア部分は以前書いたエンベロープとチャンネルがあればほとんど出来たようなものです。
でも、それだけではアニメーションを表示することは出来ません。
アニメーションを表示するためにはその周辺にいろいろと必要です。
ということで、現在はツールとともにその周辺を実装しています。
UI 周り以外のソースコードは共用される予定なので、ツールが出来れば、再生用のライブラリも出来たようなものです。

ラフなコンポーネント図は一応描いてますが、整理していないので文章のみで概要を。

・アニメーションコア
データを保持し、トラバース出来るだけ。

・レンダラー
トラバースへ渡すオブジェクトが描画する先。
レンダラを切り替えることで、異なる方法での描画にも対応する。

・タイムキーパー/スケジューラ
時間を管理するコンポーネント。
周期、もしくは単発で指定時間に通知してくれる。
時間と通知オブジェクトを渡すことで、イベントをスケジューリングし、時間になると通知オブジェクトの通知メソッドがコールされる。
どのような処理をするかは通知オブジェクト次第。
時間は、リファレンスクロックを取得するオブジェクトを設定することで、他とある程度同期を取れるようにする。
VBlank を基準とするゲームで使用されない ( VBlank ごとに通知メソッドをコールするぐらいか ) と思われるが、ツールでは使う。
ムービー再生エンジンでは必須 ( 今回はアニメなので関係ないが )。

・ストレージ/ストリーム
データ取得元を抽象化する。
ストレージへパスを渡すことでストリームが得られるので、そのストリームから読み込みを行う。

・画像リポジトリ
名前、もしくはキーで画像を取得できる。
キャッシュメカニズム ( 開放タイミングをどうするか ) に悩み中。

・アニメーションリポジトリ
名前、もしくはキーでアニメーションを取得できる。

現状は以上のような感じ。
変わる可能性もある。

なんか、コアよりも周りのが大変。

投稿者 Takenori : 15:37 | トラックバック

2007年11月09日

スプライトアニメツールの進み具合

Theora のデコードに現を抜かして結構時間が経ってしまった。
で、ツールの開発に戻るかなぁと思ったら、すごい忘れててびっくり。
なんか、クラス多いなぁ、てか、こんなに作ってた? と。
そして、ブログにも書いていない。
思い出したので、まとめておく。

ウィンドウは、SDI + タグスタイル。
1枚の画像から矩形を切り出して、それをスプライトとして使えるように、UV切り取り画面がある。
画像1枚が、1個のスプライトでもいいんだけど、2の累乗制限があったり、切り取れた方が良い場合もあるので、UV切り取り機能は付けることにした。
ウィンドウに画像をドロップしていくと、画像が追加されていく。
追加された画像は、左端にツリーで表示されているので、その画像をダブルクリックするとUV切り取り用のタブが開く。
ここで、矩形を切り出していく。
ここまでは出来ていて、次は XML ファイルへ切り取った矩形 ( 以降セルと言う ) の情報を書き出そうとしていた。
と言うことで、続き。

セル情報を XML ファイルへ書き出す部分の実装は出来た。
ただ、文字コードは Shift JIS のまま。
文字コードは UTF-8 にしたいので、変換する必要がある。
ICU を使ってみたいとは思うものの、mlang.dll で十分と言えば十分。
とりあえずは、mlang.dll を使って、Shift JIS <-> UTF-8 を作った。
次は、XML ファイルへ書き出す時にきちんと文字コード変換するようにした後、読み込みに対応する。
XML ファイルの読み込みには、expat を使う予定。

投稿者 Takenori : 23:39 | トラックバック

2007年12月24日

スプライトアニメツールを急ぐ

特に使う予定はなかったので、ちんたら作っていたら急に必要になってきて少し焦り中。
そこで、当初の予定よりも機能を削り、簡易版を先に仕上げることにした。
簡易版といっても、普通に使えるレベルで、何もないよりは遥かにマシなもの。
後、予定してなかった機能も要りそうなので追加予定。

投稿者 Takenori : 22:26 | トラックバック

2007年12月31日

テンプレートでバイナリ増大中

2日で実行ファイルが 1MB も大きくなった。
ソースコードはあまり増えていない。
テンプレートによって肥大した。
どのような処理かというと画像のコピー部分。
演算として、通常(アルファ)、覆い焼き(リニア)、焼き込み(リニア)、乗算、スクリーン、オーバーレイ、ハードライト、ソフトライト、覆い焼きカラー、焼き込みカラー、比較(明)、比較(暗)、差の絶対値、除外の14種類をサポートしていて、これらが関数オブジェクトになっている。
で、矩形コピーは、回転の有無、拡大縮小の有無、透過の有無で分かれている。
さらに、回転と拡大縮小の時には、近傍点とバイリニアで分かれている。
他に、不透明として扱うのと、マスク(アルファだけコピー)、置換マップがあって、上記のものほどではないが分かれている。

それでこれらがテンプレートとして書かれているということで、分岐されている分大量にコードが生成されて、実行ファイルが大きくなることに。
そして、末端の処理となる演算用の関数オブジェクトの MMX 版と SSE2 版を作ろうとしているのだが、これをやるとさらに3倍になることが予想される。
つまり、画像コピー部分だけで 3MB。
でかい。
現状、すべて C++ Builder で作っているが、イントリンシックの MMX を使うために、画像コピー処理部分は DLL にして VC に持っていこうと考えている。
なので、VC の最適化で少しサイズが縮んでくれないかなぁと少し期待。
でかいことには変わりないんだろうけど。

まあ、最近はネットワークも速いし、数 MB 程度なら気にならないかな。
と自分を納得させ中。

投稿者 Takenori : 01:50 | トラックバック

2008年03月24日

簡易版の再生

スプライトアニメツールの簡易版が制限付きながらも使えるようになっていたので、それを渡してアニメを作ってもらった。
そのため、そのデータを再生できるようにする必要が生じた。
はじめは、ツールに画像書き出し機能をつけたのでそれでいいかと思っていたけど、容量が結構大きくなってしまうので、アニメを直接再生できるようにすることにした ( 完全に透明な部分はカットして、オフセットと画像のリストを吐くようにしていたが、それでもやはり容量は大きくなってしまった ) 。
それで、ちょっと悩む部分が出てきたので少し整理することにした。

問題は画像の解放タイミング。
画像ファイルはバックグラウンドで非同期読み込みできるようにしつつ、アニメの特定フレーム描画時に描画対象画像が読み込まれていなかったら、読み込んでから描画するようにしている。
バックグラウンドでの読み込みは、任意のタイミングで指定アニメ、もしくは指定アニメの特定フレームで行えるようにする。
各アニメが使う画像は、その画像が初めて使われるフレームと最後に使われるフレームを保持しており、初めて使われるフレーム番号が小さい順にソートして保持している。
指定アニメで読み込み要求があった場合、このリストの順で読み込みを行う。
指定アニメの特定フレームの場合は、単に画像へアクセスするだけのファンクタを作ればよい。
ここまでは特に難しいことはないが、問題は解放。
解放は、指定したアニメが使用している画像を対象とするか、全て解放してしまうかの2種類用意している。
アニメが1つだけであれば、特に気にすることなく解放してしまえばよい。
問題はアニメが2つ以上あって、1つの画像が複数のアニメから参照されている場合。
最初は、単純なリファレンスカウント方式で解放を管理すればいいかと思ったが、よくよく考えればそれではまずい。

バックグラウンドでの読み込みと間に合わなかった時の読み込みが重複するとカウンタが多く進んでしまう。
バックグラウンドでの読み込みに任せてしまうか、間に合わずに読み込んだ時にリストから消すとつじつまは合うが、いくつか難点がある。
バックグラウンドでの読み込みに任せてしまう場合は、先読み指定しなかったときに困る ( いつまでたっても画像が読み込まれない ) と思ったけど、間に合っていなかったらバックグラウンドでの読み込みに依頼して待つと言う方法があるか。ただ、その場合リストに既にあった場合は結局重複してしまうので、あるかどうか調べないといけない。
リストから消すのは、リストをたどるコストがもったいない。
でも、使われる画像の数なんてしれてるか。
数百個も行かないだろうから、リストをたどってもそれほど時間はかからないか。
先読み要求を覚えておいて、もし出ていない状態でアニメの描画要求があったら、まず先読み要求を出すことで、先読み要求が出ていない状態をなくす。
間に合っていない時は、その画像をリストの先頭に持って行って早めに読み込んでもらうようにする。
そして、読み込みが完了するのを待つ。
こうすることで整合性は取れるか。
それに、呼び出し側の作りにもよるが間に合わないことはレアケースだと思う。
基本的には読み込みを意識させないためにバックグラウンドで読み込むので、ギリギリで読み込み依頼出すような作り方はしない ( と言うかそうしたら意味ない ) 。
後、間に合わなかった場合、スレッド間でロックが多く発生して重くなりそうだから、その辺りは良く考えないといけない。

他に考慮すべきことは、読み込み容量の上限と自動解放。
アニメをストリーミング再生する場合にそれらの制御が必要。
自動解放は単純に画像が最後に使われるフレームは持っているから、そのフレームを描画し終わったら解放してしまえばいいだけ。
読み込み容量の上限は、読み込み済みサイズを加算しながら読んで、上限を超える時は一時停止。
解放が呼ばれたタイミングで再開すればいい。

ただ、今回に限って言えば、画像データはそんなにないので、最初に一度全部読んだら最後まで持っていても問題ないし、その方が安全。
とりあえずは同期読み込みで最初に読んでしまうようにしておくか。
今までは全部この形の作りだったし。

しかし、シームレスローディングとはいろいろと厄介だな。
完全にプログラマ依存で、事前に容量計算して、読み込むタイミングと解放タイミングを考慮して作るような形なら、ライブラリ部分は簡単か。
基本的には事前に見積もって作るようにするべきだから、そういう作りでもいいと言えばいい。
まあ、この辺りはもう少し練った方が良さそう。

投稿者 Takenori : 18:38 | トラックバック

 
Total : Today : Yesterday :