ゲームはプログラムで作られていますよね。
その上、昔は容量が少なかったり便利な命令(関数)がなかったりと、様々な制約がありましたが、その中で面白いゲームがたくさん生まれてきました。
ファミコン時代まで遡れば特に厳しかったのは容量制限でしょう。初期は24KBから、後期は512KBのカセットが主流でしたので、グラフィックがゲームプレイ体験の大きな手がかりとなることから、多くのプログラマーが涙したことでしょう。
そんな制約の中で面白いゲームを作るには、プログラミングの驚くべき効率化テクニックがあったわけです。当時はゲーム制作者によりCPUのバグやブラウン管の特性を含めた仕様の隅々まで解析され、高速点滅により一度に表示できるオブジェクト数を増やしたり、設計者の想定を越えたスピードで画面をスクロールさせたりと、涙ぐましい努力の上にハードの限界を越えた表現を実現していたのです。
この辺りの図式は、ユーザーにより高度な表現が日々模索されていくAfter Effectsでも似たようなところを感じていて、ソフトの仕様や新たなプログラムの動作を知るワクワク感は確かに、ゲーム解析のように他者のテクニックを学び続ける今に通ずるのかなと、ここでアウトプットしてみます。
ゲームの有名な制限を振り返る
容量の削減としては、画像や音の使い回しが主流です。
任天堂のファミコンソフト「スーパーマリオブラザーズ」では、
- 「雲」と「草」は同じ画像を流用
- クリボーは1枚絵の反転で歩きを表現
- 色パレット切替で色違いキャラを量産
http://shadeco.video/5fv3
として画像容量を削減したり…
- 土管に入るSEとマリオが小さくなるSEは同じ
- ノコノコを踏んだ時のSEとマリオが泳ぐ時のSEは同じ
- ゴール時のファンファーレは速度変更しキノコを取った時のSEに流用
と言われており、音源でさえ容量を切り詰めて切り詰めて、ゲーム全体を40KBというカセットに収めています。
その“メモリ減らし”のおかげで
「これでブロックがあと3個は置ける」とか言って
よろこんだりしていました(笑)。
任天堂:社長が訊く「スーパーマリオ25周年」/『スーパーマリオ』生みの親たち 篇 / 5.”メモリ減らし”のためにより
そんな興味深いゲーム制作から生まれたテクニックから、After Effectsでのプログラミングに取り入れられるアイディアを探ってみます。
- 状態異常
- キャラクターモーション
- 色パレット切替
の3つを、映像制作時のプロジェクトファイルに応用すると面白いテクニックとして実践してみます。
1.状態異常
まずは状態異常です。チェックボックスによる不透明度のコントロールと、優先順位の設定方法を学びます。
家庭用PCでのセーブデータ改造が流行り始めた頃、ゲームを逆アセンブラ(解析)していた際に、面白いテクニックとして「2進数を活用し、コンピュータにも人間にも読みやすいステータス管理」をしているのに出会いました。
2進数での興味深いステータス管理
例えば、キャラクターのステータスがマイナスとなる状態異常が下記の8つあるとしましょう。
毒 | |
麻痺 | |
沈黙 | |
眠り | |
暗闇 | |
混乱 | |
ゾンビ | |
気絶 |
これは8bitの2進数、1つで管理します。8bitあれば2の8乗(2×2×2×2×2×2×2×2)、つまり最大255まで数えられるので簡単だと思われますが、ここに画期的なテクニックが使われます。
8bitにどう当てはめるかというと…
状態 | 値(2進数) |
---|---|
毒 | 0000 0001 |
麻痺 | 0000 0010 |
沈黙 | 0000 0100 |
眠り | 0000 1000 |
暗闇 | 0001 0000 |
混乱 | 0010 0000 |
ゾンビ | 0100 0000 |
気絶 | 1000 0000 |
このように、1桁ずつをON OFFスイッチに見立てて管理するのです。
この管理方法の利点は、人間が読みやすい点です。ステータス異常が重なった場合も、混乱しません。
毒で麻痺で沈黙状態という、実際なら救急搬送レベルの状態異常は
0000 0111
で管理出来てしまいます。非常にスマートですよね。After Effectsで似たような考え方は、チェックボックスです。8つのチェックボックスの内、該当の状態異常をチェックしているのと同じです。
テクニック
この状態異常を実際にチェックボックスで実現したいと思います。
デフォルトとなるキャラクターの立ち絵と、8つのステータス異常画像を用意しました。まぁ、ゾンビだけピッタリのイメージが思いつきませんでしたが、気を取り直していきましょう。
今回は「ゆるドラシルゲーム用素材ユニット」を素材としてお借りしました。
アニメーション途中でステータス異常を変化させたいので、各ステータス異常画像の不透明度エクスプレッションから該当チェックボックスへリンクさせます。
エクスプレッションの記述にはピックウィップを使うと便利です。エクスプレッションエディターの渦巻マークをドラッグすると、ドラッグ先のプロパティを式の状態でエクスプレッションに記述できます。
上記画像の状態でマウスを離すと、麻痺レイヤーの不透明度に「thisComp.layer(“[ctrl]キャラクター”).effect(“麻痺”)(“チェックボックス”)」と手打ちせず入力できます。
そしてエクスプレッションですが、チェックボックスがOFF=「0」、ON=「1」という数値が引っ張れますので、100倍すれば不透明度を0か100にできますね。
状態異常レイヤーのエクスプレッションは全て上記画像の「毒」「暗闇」レイヤー同様、最後に「*100」を追加して完成です。
こうしてタイムライン上に全ての状態異常状態をあらかじめ並べておき、キャラクターレイヤーのチェックボックスがONなら該当ステータス異常の不透明度を100に、OFFなら0に、という具合でグラフィックを表現します。
もう少しこだわってみる
こだわりとしては、麻痺の時は動きを止め、眠りor気絶の時は倒れ状態にしたいので、立ち絵も切り替えたいですね。状態異常同様、倒れ状態の絵も用意し、該当状態異常時に不透明度を0か100で切り替えます。
一旦、状態異常とキャラの立ち絵を一覧に整理すると下記のとおりです。
キャラクターの立ち絵の優先度としては、
立ち<麻痺で停止<眠りor気絶で倒れ
でいいでしょう。
麻痺か眠りか気絶の場合には立ち絵を不透明度0に、麻痺時なら眠りか気絶の場合に停止した立ち絵を不透明度0に、それ以外は立ち絵の不透明度を100にしたいと思います。
具体的なエクスプレッションの一例は下記です。
倒れキャラクターの不透明度エクスプレッション
a=thisComp.layer("[ctrl]キャラクター").effect("眠り")("チェックボックス");
b=thisComp.layer("[ctrl]キャラクター").effect("気絶")("チェックボックス");
if((a==1)||(b==1)){
100;
}else{
0;
}
今回は3行目のif文を簡潔にするため、1,2行目で比較対象のチェックボックスを変数「a」「b」に代入しました。もちろんこれはお好みですが、if文の記述に集中するため、長いプロパティは変数化することをオススメします。
3行目の解説としては「||」は「もしくは(or)」という意味なので、「眠り」か「気絶」どちらかのチェックボックスがONなら不透明度100に、となります。立ち状態でもどちらかの状態異常になれば最優先で倒れキャラクターが表示されます。
停止キャラクターの不透明度エクスプレッション
a=thisComp.layer("[ctrl]キャラクター").effect("麻痺")("チェックボックス");
b=thisComp.layer("[ctrl]キャラクター").effect("眠り")("チェックボックス");
c=thisComp.layer("[ctrl]キャラクター").effect("気絶")("チェックボックス");
if((a==1)&&(b==0)&&(c==0)){
100;
}else{
0;
}
こちらは「麻痺状態であれば停止キャラクターを表示」としたいところですが、これでは眠り・気絶状態と麻痺状態が重なると「停止キャラクターと倒れキャラクターが同時に表示」されてしまいます。
先程、立ち<麻痺で停止<眠りor気絶で倒れ という立ち絵の優先順位を決めた意味がこの問題の回避です。
4行目のif文「&&」は「かつ(and)」という意味なので、「麻痺」のチェックボックスがONで、かつ「眠り」と「気絶」のチェックボックスがOFFなら不透明度100に、となります。
立ちキャラクターの不透明度エクスプレッション
a=thisComp.layer("[ctrl]キャラクター").effect("眠り")("チェックボックス");
b=thisComp.layer("[ctrl]キャラクター").effect("気絶")("チェックボックス");
c=thisComp.layer("[ctrl]キャラクター").effect("麻痺")("チェックボックス");
if(a+b+c==0){
100;
}else{
0;
}
今回通常の立ち絵は、立ち<麻痺で停止<眠りor気絶で倒れ という立ち絵の優先順位として最低に設定しました。なので他の立ち絵が選ばれていなければようやく不透明度を100にします。
そして、先程も触れたように、チェックボックスがOFF=「0」、ON=「1」という数値が引っ張れますので、4行目のif文では趣向を変えて「3つのチェックボックスを全て足し算し、0であれば3つともOFF(0)であるとみなし、不透明度を100にします。
「眠り」「気絶」「麻痺」チェックボックスに1つでもONがあれば、4行目のa+b+cが1以上となりますので、「停止キャラクター」か「倒れキャラクター」が優先して表示されます。
完成品
これで複合した状態異常も8つあるチェックボックスで簡単に調整できるようになりました。
自キャラだけだと寂しかったので敵キャラも追加しましたが、無視してください。
もちろんチェックボックスにキーフレームを追加し、任意のタイミングで任意の状態異常にすることができます。例えば人アイコンの右上にアイコンをコロコロ変えて表示する場合などに応用できるかと思います。
2.キャラクターモーション
次にキャラクターモーションです。タイムリマップの任意の秒数を呼び出す方法を学びます。
例えばアクションゲームであれば、パンチボタンを押したら、任意のタイミングでパンチという決まったモーションが再生されます。
After Effectsで言えば、モーションをコンポジション化しておき、任意のタイミングでコンポジションを切り替えるというイメージです。ただしコンポジションを任意のタイミングで切り替えるのは難しいので、タイムリマップで指定タイミングで指定秒数から再生してみます。
モーション素材を用意する
今回は「デフォルトの立ち」「物理攻撃」「魔法攻撃」の3つのモーションを用意しました。12fpsで1モーション2秒ずつ配置します。キャラクターはまた「ゆるドラシルゲーム用素材ユニット」をお借りします。
テストなのでエフェクトは簡単にシェイプレイヤーで描きました。ここで1つのモーションはきっかり2秒ずつにしている点に注目して下さい。1モーション何秒でもいいですが、エクスプレッションで呼び出す際に、「モーション番号×1つのモーション長さ」とすることで、0秒~、2秒~、4秒~と再生開始秒数が一定間隔となりますので、極端に短いモーションであっても次のモーションは2秒の刻みで配置しておいてください。
つまり1モーションで例えば5秒かかる大技を使いたい場合は、他のモーションも一律で5秒おきにタイムラインへ配置しておいて下さい。
テクニック
1つのコンポジションに、立ち、攻撃モーションを並べておいて、タイムリマップで該当のモーション時間を再生させることで実現できます。
そして何番目のモーションを再生するかのキーフレームを設定するための「スライダー制御」エフェクトを適用し、「モーション番号」とリネームします。タイムリマップに適用する下記のエクスプレッションで、モーション番号のスライダーをトリガーにします。
「モーション番号」のスライダーを読み取り、例えば「1」キーフレーム以降が0~1.9秒(つまりデフォルトの立ち状態)が再生され、「2」キーフレーム以降は2~3.9秒(物理攻撃モーション)が再生されるようにします。
var dur=2;//1モーションの長さ秒;
var nearKey=effect("モーション番号")(1).nearestKey(time);
var motionIndex=(time<nearKey.time)?nearKey.index-1:nearKey.index;
if(motionIndex>0){
var motionKey=effect("モーション番号")(1).key(motionIndex);
var d=motionKey*dur-dur;
var nowframe=timeToFrames(time+inPoint)-timeToFrames(motionKey.time);
valueAtTime(framesToTime(nowframe)%dur)+d;
} else {
0
}
1行目の「dur」で何秒おきにモーションを配置したかを秒で設定します。これで「モーション番号」で指定したモーションとタイムリマップの再生開始秒を一致させます。今回は1モーション2秒なので、「dur=2;」です。
続いて2行目、
nearKey=effect("モーション番号")(1).nearestKey(time);
キーフレームと連動させたいので「.nearestKey(time)」で「モーション番号」スライダーの現在の時間に一番近いキーフレームを検知します。そのため、一番近いキーフレームは、キーフレームとキーフレームの中間で入れ替わるので、3行目で整えます。
motionIndex=(time<nearKey.time)?nearKey.index-1:nearKey.index;
次のキーフレームがある時間までは1つ前のキーフレーム、キーフレーム以降にはその次のキーフレームを変数「motionIndex」に入れ、2行目の「nearKey」をキーフレーム丁度で切り替わるように整えます。
最後に、
if(motionIndex>0){
var motionKey = effect("モーション番号")(1).key(motionIndex);
var d=motionKey*dur-dur;
var nowframe=timeToFrames(time+inPoint)-timeToFrames(motionKey.time);
valueAtTime(framesToTime(nowframe)%dur)+d;
} else {
0
}
「motionKey」がn個目のキーフレームの値を格納する変数、「d」がモーション番号に相当するタイムリマップの開始時間を格納する変数、「nowframe」で秒数ではなく現在のフレーム数に変換し、続く「valueAtTime(framesToTime(nowframe)%dur)+d;」で「モーション番号」のキーに相当するモーションを再生するようになります。
完成品
このように任意のタイミングでモーションの再生が必要な場合などに、モーションパターンを登録したコンポジションを用意し、タイムリマップのエクスプレッションでモーションを選べるようにするテクニックです。
3.色パレット切替
最後はパレットのアイディアです。色の設定を一カ所にまとめ、紐付いたオブジェクトの色を一括変更する方法を学びます。
ファミコンでの画像の管理方法は、ドット絵と色管理用のパレットを別に管理していました。この管理法の利点は、パレットを切り替えるだけで、色違いキャラを作ることが出来る点です。
モーショングラフィックスに限らず、動画内に使用する色は限られます。ロゴやコーポレートカラー、またはカテゴリとしてまとめられるシーンを数色でグルーピングすることが多いからです。
色もエクスプレッションを使えば一括管理できることから、このパレットでの色管理を自身のaepに取り入れてみましょう。
パレット一箇所に動画内の色を登録しておく
例えば、ロゴが変わりコーポレートカラー変更で動画は引き続き使いたい場合や、動画内に何度も出てくるカテゴリカラーが修正となった場合は、いくつものレイヤーの色を変えなくてはなりません。大抵は泣きながら一つ一つ修正していくのですが、初めから一つのパレットを参照しておけば、パレット側の色を変えるだけで、その色が適用されるレイヤー全ての色を変更できます。
テクニック
ポイントはエクスプレッションを仕込めるプロパティの見極めです。シェイプレイヤーは「塗り」というプロパティがエクスプレッション適用可能なプロパティなので、そのままパレットを参照すれば済みます。
対してテキストレイヤー、平面レイヤーは、色を指定するプロパティにエクスプレッションを適用できません。
テキストの色は[文字パネル]での設定、
平面レイヤーは[プロジェクトパネル]に作られたソースの色設定と、
エクスプレッションを仕込めない箇所で色を設定しなければなりません。
この場合は色を変更するエフェクト(「塗り」や「色かぶり補正」など)、もしくはレイヤースタイルの「カラーオーバーレイ」を適用→色プロパティに対してエクスプレッションを適用という一手間で解決できます。
パレットの準備
大元となるパレットは、パレットコンポジションとしてアクセスしやすいところに置いておくか、タイムライン上にヌルや調整レイヤーを準備し、「カラー制御」エフェクトを適用したパレットレイヤーとして配置しておくのが扱いやすいでしょう。
さらにエクスプレッションのコピペを分かりやすくするテクニックとして、参照するコンポジション名やレイヤー名、エフェクト名を連番など分かりやすい名称にしておくと、色のリンク作業自体の効率化が図れます。
例ではヌルオブジェクトを作成し、パレットレイヤーにしました。
パレットへのリンク付け
あとは用意したパレットの該当カラーへ、参照先のカラーをエクスプレッションで次々とリンク付けしていくだけです。
これで色を修正したい場合は、パレットレイヤーの「カラー制御」エフェクトで一気に修正できるようになりました。
パレットの色を好きなように変えてみましょう。
このように一箇所で色の変更が一括管理できるようになります。
デメリット
デメリットとしてはパレット適用したいレイヤーが増えれば増えるほど、リンクさせるエクスプレッションのコピペ作業が増えますので、全てのプロジェクトで躍起になって徹底する必要はありません。またプロジェクトファイルが複雑になってからパレット管理への切り替えは大変な手間になります。
色修正の可能性が見えていればこのテクニックを使い、そうでなければ使わないと、最終的に効率的なのはどちらかを制作開始時に判断しなければなりません。
また、差し色にここだけは違う色…と一部分でもパレットとリンクしない色を使用した場合、修正時に一括変更から漏れて混乱するので、覚えておける範囲で行うか、リンクを徹底するか注意したいところです。
プログラムで制作環境を拡張する
このように異なる分野で培われたプログラミングテクニックでも、一部分を抜き出せば映像表現の仕事効率を大きく上げる可能性を秘めています。
是非、他業種で培われたノウハウにも触れてみる機会を設けてみましょう。
中でも取り分けゲームのプログラムは、グラフィックを扱うAfter Effects作業への応用がイメージしやすいものでした。
他にも、HTMLに続くcssなども、配置やアニメーションへのプログラム的な考え方を取り入れるのに参考になるところが多く、モーショングラフィックスで活用場面の多い円グラフ、棒グラフ、折れ線グラフなどをただ動かすのではなく、そのグラフアニメーションで表現したいことへ注目させるヒントが得られることでしょう。
分野が異なる場合でも、売れているツールはどこが使いやすく、どう見やすく、如何にして動画制作に取り入れられそうかというアイディアを模索するのも、ただ効率化をイメージするだけでなく、手間だからと敬遠していた映像表現をモノにする手掛かりになるのではと思います。
この記事へのコメントはありません。