コマンド処理とは?
例えば、プレイヤーが看板に向かってコマンドキーを押したらメッセージを表示するとか、箱に向かってコマンドキーを押したら何かアイテムを入手するとか、そういった動作を実現するものがコマンド処理です。これはとてもよく使う手法ですのでよく覚えておいてください。今回のレッスンでは、前回作成したスクリプトを改造し、電気スタンドに話しかけると宿屋イベントを実行、箱に話しかけると薬草を入手、というコマンド処理を行ってみます。前回のスクリプトを以下のように変更します。白い文字の部分は前回と同じ箇所です。
プレイヤーのコマンドを処理する
localsave int g_Init = 0; // 主人公作成フラグ localsave int g_BoxOpen = 0; // 箱を開けたフラグ /* * 家のマップ関数 */ mapfunc House(){ // 主人公を作成 (初回のみ) if(!g_Init){ void *ruki = CreateChara(1, 3); // キャラ作成 RegisterChara(1, ruki); // キャラ登録 SetCharaGroup(ruki, 1); // 所属勢力の設定 SetCurrentChara(ruki); // 操作対象に設定 SetTransit(3, 3, 0, 3); // 初めに置く場所を設定 g_Init = 1; // フラグを立てる } // 箱を既に開けていれば「閉じた箱」のチップを「開いた箱」に置き換える if(g_BoxOpen) ReplaceObject(14, 2, 7, 8); // 毎回のロード処理 PutPlayer(); // 主人公を置く PlayMusic("House.mid", 1); // BGM 再生 TransitMap(-1, 10); // 画面切り替え // メインループ while(1){ // 無限ループ PeekAllMessage(); // 必ず必要 // スタンドに話しかけると宿屋イベントを実行 if(Investigate(8, 1, 0, -1)){ PlaySound("Command.wav", 0); // サウンド再生 RenderMap(0); // マップ描画 // 宿屋イベント ExecuteInn("さて、どうするかな", "Inn.wav", 0, 1, 0); continue; // ループやり直し } // 箱に話しかけると… if(Investigate(14, 2, 0, 1)){ PlaySound("Command.wav", 0); // サウンド再生 ResetWindow(); // メッセージウィンドウ初期化 if(g_BoxOpen){ // 既に空けていたときの処理 RenderMap(0); // マップ描画 // メッセージ設定 PushString("箱は空っぽだ。", 0x00ff8000, 1); Message(); // メッセージ表示 }else{ // まだ空けていないときの処理 // 「閉じた箱」のチップを「開いた箱」に置き換える ReplaceObject(14, 2, 7, 8); RenderMap(0); // マップ描画 // メッセージ設定 PushString("薬草を3個手に入れた!", 0x0080ff80, 1); DrawItem(0, 20, 1); // アイテム画像を表示 GiveCharaItem(GetCurrentChara(), 1, 3); Message(); // メッセージ表示 g_BoxOpen = 1; // フラグを立てる } continue; // ループやり直し } NormalProcess(1); // RPG 処理 } }
コマンドのキャッチ
まず、メインループ中の「スタンドに話しかけると〜」の部分を見てください。今、プレイヤーがスタンドに話しかけたら宿屋イベントを発生させたいわけです。そのためにはまず、プレイヤーが「スタンドに向かってコマンドを実行したかどうか」調べなければなりません。このようなコマンドの実行には Investigate 関数を使います。ここで、スタンドにはどの方向からでも話しかけられるようにしたいので、Investigate 関数の第 4 引数を -1 としていることに注意してください。Investigate 関数の戻り値が 1 だった場合に、目的の処理を行えばいいことになります。コマンドをキャッチしたら、効果音の再生とマップ描画を行います。いずれの処理も必ずしも必要なものではありませんが、効果音は演出のために再生するといいですね。マップの描画ですが、NormalProcess 関数による通常処理では、FPS やコンパス、ミニステータスが表示されています。これらの余分なものを消すために、メッセージを表示する前などには RenderMap 関数を呼ぶといいのです (気にしないのなら省略してもいいですが)。そしてやっと目的の処理である宿屋イベントを実行します。これでひとつのコマンド処理が終わったわけですが、コマンド処理の後にはメインループの初めに戻るために continue 関数を実行するのが好ましいです。覚えておいてください。
コマンド処理+フラグ処理
次に、箱に話しかけたらアイテム入手、というコマンド処理を行いたいわけですが、一度箱を開けたらそれ以降はアイテムを入手できないようにしないといけません。このため、再び localsave 記憶クラスで g_BoxOpen というフラグを作っています。なお、localsave や globalsave といった、保存記憶クラスの変数を追加したり削除したりすると、実行時に「"〜.qs" が壊れています」というメッセージが表示されることがあります。このように、フラグの追加をするとセーブデータが使えなくなる、ということをよく覚えておいてください。さて、次の Investigate 関数ですが、箱に対しては正面からのみコマンドを受け付けるようにします。で、コマンドをキャッチしたらフラグを調べてメッセージを分岐しています。初めて開けた場合は GiveCharaItem 関数でアイテムをキャラクターに与えます。なお、この関数はキャラクターの持ち物が一杯だと 0 を返しますので、実際にはそのようなエラー処理もしっかり行いましょう。箱を開けたとき、RenderMap 関数でマップを描画する前に、ReplaceObject 関数で箱のチップを「開いた箱」に置き換えましょう。アイテムを与えたらフラグを立てて完了です。なお、マップをロードしたときに、それ以前に箱が開かれていた場合はここでチップを置き換える作業も大切です。
実行してみる
早速実行してみましたか?スクリプトが長くなってきましたが、ひとつひとつ見ていけば特に難しいことはないはずです。次は、家の中から出てみたり家に入ったりと、複数のマップ間を移動する方法について解説します。