技を追加してみよう


 今回は、とにかく技を追加してみよう、 ということで開発キットに付属のケンのソースを改造してみたいと思います。 CBで新たなセルをつくるとなるとサンプルの作成が面倒なので有り合わせのセルを使うことにします。

 追加するのはいわゆる乱舞系の技です。乱舞はセルの使い回しが多いので作るのが楽なうえ、 見せかたによっては非常に見栄えのする技になります。ではいってみましょう。

セルを登録する

 実際にはセルを使い回すだけなので、セルを登録する必要はないのですが、 説明のために登録してみます。

 セルを登録するにはデータと一対一に対応したセルIDを用意しなければなりません。 「ACTION.H」をエディタで読み込みます。すると

/*..........  キャラ固有セルのID定義  ..........*/

#define  CELL_直立攻撃A0	130
#define  CELL_直立攻撃A1	131
#define  CELL_直立攻撃A2	132
....
....
....


と書かれている箇所が見つかると思います。「#define」はシンボルの定義に使われるプリプロセッサ命令です。 上の場合、「CELL_直立攻撃A0」という文字列をプログラム中で使うとコンパイル時に130に置き換わります。
 「#define」の用途は色々ありますが、主に「ただの数字に意味を持たせたい時」 「複数の箇所で同じ数値を用いる時」に使います。

 プログラム中で130という数字が出てきた時、この130はいったい何を意味しているのか、 ぱっと見にはわかりにくいと思います。そこで130という数字を使わずに、「CELL_直立攻撃A0」というシンボルを使い、 どんな意味の数字を使っているかをわかりやすくしています。

 また、セルIDとセルデータの割り当てを変更した場合。 「直立攻撃A0」のセルをID130から140に変更した場合、 シンボルを使っていないとセルIDとして使っている130だけを全て140に書き換えなければなりません。 シンボルを使っていれば
#define  CELL_直立攻撃A0	130
               ↓
#define  CELL_直立攻撃A0	140
と、ここを書き換えてコンパイルしなおすだけで済みます。


 さて、新たにセルを登録したいわけですからあいているセルIDを使うことになります。 どのセルIDが使えるのかは開発ドキュメントを参照してください。 せっかくなので今回はβ2から拡張されたID256以降に割り当てることにします。

 セルID定義の最後に必要なシンボル定義を付け足します。
....
....
#define  CELL_前後ジャンプ6	248
#define  CELL_超必殺00		256
#define  CELL_超必殺01		257
#define  CELL_超必殺02		258
#define  CELL_超必殺03		259
#define  CELL_超必殺04		260
#define  CELL_超必殺05		261
#define  CELL_超必殺06		262
#define  CELL_超必殺07		263
#define  CELL_超必殺08		264
#define  CELL_超必殺09		265
#define  CELL_超必殺10		266
#define  CELL_超必殺11		267
#define  CELL_超必殺12		268
#define  CELL_超必殺13		269
#define  CELL_超必殺14		270
#define  CELL_超必殺15		271
#define  CELL_超必殺16		272
#define  CELL_超必殺17		273
#define  CELL_超必殺18		274
#define  CELL_超必殺19		275
#define  CELL_超必殺20		276

/*..........  キャラ固有ボイスのID定義  ..........*/

#define  PCM_必殺技S1		110
....
....

 使用するセルIDを決めたらセルデータの登録です。今度は「ACTION.C」を読み込みます。 ソースの先頭部分にセル登録がならんでいますね。この部分の一番後ろにでも付け足しましょう。 セル登録の第一引き数はセルID、第二引き数はセルデータアドレス(CBでつけたセルの名前に「&」をつけたもの)です。
  ....
  ....
  セル登録( CELL_前後ジャンプ6	, &cell_前後J6		);
  セル登録( CELL_超必殺00	, &cell_垂直J0		);
  セル登録( CELL_超必殺01	, &cell_アッパー0	);
  セル登録( CELL_超必殺02	, &cell_アッパー1	);
  セル登録( CELL_超必殺03	, &cell_アッパー2	);
  セル登録( CELL_超必殺04	, &cell_キック0		);
  セル登録( CELL_超必殺05	, &cell_キック1		);
  セル登録( CELL_超必殺06	, &cell_回転足払い0	);
  セル登録( CELL_超必殺07	, &cell_回転足払い1	);
  セル登録( CELL_超必殺08	, &cell_回転足払い2	);
  セル登録( CELL_超必殺09	, &cell_回転足払い3	);
  セル登録( CELL_超必殺10	, &cell_回転足払い4	);
  セル登録( CELL_超必殺11	, &cell_旋風脚3		);
  セル登録( CELL_超必殺12	, &cell_旋風脚2		);
  セル登録( CELL_超必殺13	, &cell_旋風脚1		);
  セル登録( CELL_超必殺14	, &cell_旋風脚0		);
  セル登録( CELL_超必殺15	, &cell_昇龍拳0		);
  セル登録( CELL_超必殺16	, &cell_昇龍拳1		);
  セル登録( CELL_超必殺17	, &cell_昇龍拳2		);
  セル登録( CELL_超必殺18	, &cell_昇龍拳3		);
  セル登録( CELL_超必殺19	, &cell_昇龍拳4		);
  セル登録( CELL_超必殺20	, &cell_昇龍拳5		);
  
  /*..........  完了  ..........*/
  
  キャラクター登録完了();
}

動作IDの登録

 SFXVIは基本的に動作IDに登録された関数しか呼び出されないので、 新しい技を追加するにはIDを割り当て、登録しなければいけません。 動作IDは番号によって用途が決まっているので、考慮して決めます。 今回は動作IDを20にします。

 セルIDの時と同様にシンボルを定義します。
#define  ACT_乱舞	20
このような一行をACTION.Hの適当な位置に付け加えます。

 関数のプロトタイプ宣言も行なわなければならないので、新技の関数名を「乱舞」と決め、 戻り値、引き数の情報をACTION.Hに記述します。 プロトタイプ宣言とは、関数の引き数などの情報をあらかじめコンパイラに通知しておくことです。 そうすることでコンパイル時に関数の使用法の間違いをチェックすることが出来ます。
/*..........  キャラ固有動作関数のプロトタイプ宣言  ..........*/
という箇所がACTION.H内にありますから、その最後に付け足します。
void  乱舞(int,int);
 実際に関数を登録するのはACTION.Cです。 初期化()関数内で各動作関数を登録しているので乱舞()も同様に登録します。
  動作登録( ACT_乱舞		, 乱舞			);
 これで、下準備は完了です。あとは関数の実体を作成するだけです。

動作関数の作成

 動作関数は実行時に自分のハンドラと相手のハンドラの二つを引き数として受け取ります。 ハンドラとはキャラのステータスを示すデータの集まりを指し示しているものです。 これを利用することで自分や相手の状態を参照したり書き換えたり出来るのです。

 関数の引き数リストとプロトタイプ宣言は同じでなければなりません。
void  乱舞(int p1,int p2)
{
  ....
  ....
}
p1は自分の、p2は相手のキャラハンドラを表しています。 よって、キャラハンドラを引き数にもつ関数、 例えば「身体X位置()」なら引き数をp1にすることで自分のX座標を、 p2なら相手のX座標を得ることが出来ます。

 動作関数で最も重要なのはカウンタです。システムで用意されたカウンタの値を見て、 動作内容を変えていくのが関数の基本になります。

 カウンタはキャラごとにひとつずつ用意されています。 このカウンタを扱うための関数がいくつか用意されています。

カウンタ初期設定( short c );
カウンタ初期設定2( int p , short c );
カウンタ維持( int p );
カウンタ設定( int p , short c );
 カウンタ初期設定()は動作関数の呼ばれた最初のサイクルに実行すると、 引き数の値でカウンタを初期化します。 2回目以降では、実行するたびにカウンタの値を1ずつ減らしていきます。 つまり、動作関数はこの関数を基本につくることになります。

 カウンタ初期設定2()はカウンタ操作の相手を指定出来ること以外は同じ機能を持っています。 相手の動作関数を記述する(例えばくらい動作)とき以外に使うことはないでしょう。

 カウンタ維持()はそれを実行した次のサイクルでのカウンタデクリメントを行なわなくさせます。 つまり、次のサイクルでもカウンタの値は同じになります。これは、ある条件が満たされるまで、 同じ処理を繰り返させたい時などに使います。 例えばスーパーコンボを出した時、一瞬画面が暗転し気集中処理が行なわれます。 気集中処理の間は、自分を動かすことは避けたいのでカウンタ維持()を使って、 気集中処理の終わるのを待ちます。
 間違っても勝手に相手のカウンタを維持してはいけません。

 カウンタ設定()は名前の通り、カウンタの値を自由に変更するための関数です。 利用法は様々です。注意しなければならないのは、カウンタの値を変更しても、 その値を参照するのは次のサイクルになるということです。 カウンタに40を設定したとしても次のサイクルでは39になります。 以外と見落としやすいことなので注意しましょう。


 カウンタが動作の基本になっていることはわかったと思います。 それ以外の重要な要素をあげてみます。

 攻撃動作に必要なことは、

セル表示
最多ヒット数設定
キャラクタ移動
攻撃ポイント設定
ヒット情報
攻撃完了処理

だいたいこんなことです。

 セル表示については特に説明はいらないと思います。しかし、これはかなり重要です。 いくら絵がうまくても、表示タイミングが悪ければだいなしになってしまいます。

 最多ヒット数設定は攻撃動作に必要不可欠です。いくら攻撃ポイントを設定しても、 最多ヒット数が0なら攻撃は当たりません。普通、攻撃動作関数の最初のサイクルで設定します。
 最多ヒット数で設定した値は相手に当たるかガードされるかすると減りますが、 空振りした時は変化しません。
 コンピュータキャラは、最多ヒット数が0になったときが技の隙であると判断し、 反撃するようになっています。しかし、空振りすると最多ヒット数は変わりませんから、 目の前で空振りしても反撃してきません。
 これを防ぐため、最後の攻撃ポイント設定の次のサイクルで強制的に 最多ヒット数を0にするのが好ましいといえます。
 最多ヒット数が残ったままだと、技の隙の部分を当て身されることにもなりますから 忘れずに実行しましょう。

 キャラクタ移動はセル表示タイミングと同じくらい、見た目の良さに影響します。 自然な動きを表現することを心がけましょう。落下運動は重力を感じられるように。 突進技は加速度が感じられるように。

 攻撃ポイント設定についても特に説明は必要ないと思います。 ただ、特別な技でもない限り、攻撃ポイントを設定している時間は短めにした方がいいでしょう。 というのも、攻撃というものは動きでダメージを与えるものであって、 止まっているものに触れてもダメージを受けるはずはないのですから。

 ヒット情報は、ダメージ、削り、気絶ダメージなど様々な要素からなっています。 この値の設定は非常に重要ですから、何度もプレイして吟味する必要があるでしょう。

 攻撃完了処理は特に難しいことではありません。所定の関数を呼び出すだけです。 これを呼び出すことでシステムに動作の完了を伝えることが出来ます。 また、カウンタの値に関係無く呼び出すことが出来ます。

 ここまでで、攻撃動作関数制作の準備は整ったことと思います。 自信があれば、一人でプログラムを組んでみるといいでしょう。 それほど難しいことではないはずです。

 そんなわけで実は今回はこれで終わりなのです。 本当なら実際にプログラムを組むところまで書きたかったのですが、 文章が長くなってきたので、断念しました。

 続きは次回までお待ちください。

ひとつ前にもどるトップページにもどる次にすすむ