イベントを作る
今回は、畑を荒らす野良犬を退治する、というクエスト (イベント) を作ってみましょう。方針としては、老人に話しかけるとイベントが発生し、この状態で畑に行くと犬が出現します。犬を倒して老人に話しかけるとゲームクリア、という感じにしたいと思います。といってもそこまで新しいことはなくて、フラグの管理とイベントの処理をうまく連動させればいいだけです。スクリプトを以下のように書き換えてください。
チュートリアルシナリオ完成
localsave int g_Init = 0; // 主人公作成フラグ localsave int g_BoxOpen = 0; // 箱を開けたフラグ localsave int g_DogEvent = 0; // 犬イベントフラグ /* * 家のマップ関数 */ mapfunc House(){ // (中略) } /* * 町のマップ関数 */ mapfunc Town(){ void *civil = CreateChara(3, 1); // NPC 作成 PutChara(civil, 16, 16, 0, 2); // NPC 配置 // 毎回のロード処理 PutPlayer(); // 主人公を置く PlayMusic("Field.mid", 1); // BGM 再生 TransitMap(-1, 10); // 画面切り替え // メインループ while(1){ // 無限ループ PeekAllMessage(); // 必ず必要 // 家のドアに話しかけると中に入る if(Investigate(11, 12, 0, 1)){ PlaySound("Command.wav", 0); // サウンド再生 // ドアのチップを「開いたドア」に置き換える ReplaceObject(11, 12, 22, 23); RenderMap(0); // マップ描画 SetMap("House.qm"); // 移動先マップを設定 SetTransit(3, 11, 0, 1); // 移動先座標を設定 return; // マップ関数終了 } // 道の端に来たら隣のマップに移動 if(CheckRect2(0, 17, 0, 20)){ SetMap("Field.qm"); // 移動先マップを設定 SetTransit(30, -1, 0, 0); // 移動先座標を設定 return; // マップ関数終了 } // NPC と会話する if(SpeakChara(civil, 1)){ PlaySound("Command.wav", 0); // サウンド再生 ResetWindow(); // メッセージウィンドウ初期化 switch(g_DogEvent){ // 犬イベントフラグの値により分岐 case 0: // まだ始まっていない PushString("畑を野良犬が荒らしとるんじゃ。", 0x00e0e0e0, 1); PushString("ちょいと退治してきておくれ。", 0x00e0e0e0, 1); Message(); // メッセージ表示 PushString("\nそうじゃ、これを使うとよい。", 0x00e0e0e0, 1); DrawItem(0, 20, 2); // アイテム画像を表示 // ショートソードを入手 GiveCharaItem(GetCurrentChara(), 2, 1); Message(); // メッセージ表示 PushString("\nショートソードをもらいました。", 0x0080c0ff, 1); Message(); // メッセージ表示 g_DogEvent = 1; // フラグを立てる break; case 1: // 始まっている;まだ倒していない PushString("頼んだぞ!", 0x00e0e0e0, 1); Message(); // メッセージ表示 break; case 2: // 始まっている;倒してきた PushString("よくやった!", 0x00e0e0e0, 1); Message(); // メッセージ表示 PushString("\n\nこれでチュートリアルシナリオは終了です。", 0x00ff4040, 1); Message(); // メッセージ表示 BackToTitle(); // エンディング;タイトルに戻る } continue; // ループやり直し } NormalProcess(1); // RPG 処理 } } /* * 畑のマップ関数 */ mapfunc Field(){ void *dog = NULL; // 犬ポインタ if(g_DogEvent==1){ // 犬イベントフラグが 1 なら犬作成 dog = CreateChara(5, 5); // 犬作成 SetCharaGroup(dog, 2); // 犬の勢力を設定 PutChara(dog, 16, 16, 0, 2); // 犬配置 } // 毎回のロード処理 PutPlayer(); // 主人公を置く PlayMusic("Field.mid", 1); // BGM 再生 TransitMap(-1, 10); // 画面切り替え // メインループ while(1){ // 無限ループ PeekAllMessage(); // 必ず必要 // 道の端に来たら隣のマップに移動 if(CheckRect2(31, 17, 31, 20)){ SetMap("Town.qm"); // 移動先マップを設定 SetTransit(1, -1, 0, 2); // 移動先座標を設定 return; // マップ関数終了 } // 犬を倒したか調べる if(g_DogEvent==1 && !GetCharaStatus(dog, 5)){ PlayAnimation(15, 0); // しばらくアニメーションを回す ResetWindow(); // メッセージウィンドウ初期化 PushString("よし、倒したぞ!", 0x00c0ffc0, 1); Message(); // メッセージ表示 g_DogEvent = 2; // フラグを立てる continue; // ループやり直し } NormalProcess(1); // RPG 処理 } }
イベント解説
まず、この「犬イベント」を管理するための g_DogEvent というフラグを新しく用意します。フラグの値としては初めは 0 で、老人に話しかけると 1 になり、犬を倒すと 2 になる、という風に設計しましょう。このように、フラグの値とイベントの進行状況を確実に対応付けることが重要です。老人との会話の部分では、イベントの概要が説明され、ショートソードを主人公に渡しています。このときにフラグを 1 に設定します。フラグが 1 の状態で老人と会話すると「頼んだぞ!」とだけ表示されるようにしています。この状態で畑に行くと、フラグが 1 の時に犬のキャラクターを作成していることがわかります。戦闘を行うためには、犬を主人公と敵対する勢力に所属させなければならないので注意してください。フラグが 1 のとき、GetCharaStatus 関数を用いて、犬の HP が 0 になったかどうか調べています。論理演算子は使いこなせるようにしましょう。犬を倒すと、PlayAnimation 関数でしばらくアニメーションを再生します。これは、倒した直後でメッセージを表示すると、まだ犬のキャラチップが消えていないからです。倒したことを確認した後、フラグに 2 を立てます。そして老人と再び会話すると、メッセージを表示してタイトルに戻ると、こういった流れになります。
実行してみる
イベントはしっかり流れましたか?イベントの途中でセーブやロードを行ってみて、フラグの値がしっかりと保存されていることも確認してみてください。以上でチュートリアルシナリオは完成とします。ここまでの内容が理解できたら、サンプルシナリオを自力で解読してみてください。なお、チュートリアルのおまけとして、次のページでタイトル画面などのカスタマイズについて説明します。