前回までで敵やウインドウの配置など、グラフィック系が扱えるようになりましたので、次に戦闘の流れを考えてみます。
簡単な流れとしては、
という感じになります。ただ、自分を攻撃できたり、毒で死んだり、時間切れになったり、という要素がからんでくると複雑になります。
作るときは無限ループを組み込んでおき、戦闘終了条件を満たしたら、ループを抜けるという作りにすると、楽でしょう。コメントだけで書くと下のようになります。
/* 例 */ void battle(){ /* 戦闘開始時の処理 */ while(1){ /* 味方の攻撃 */ /* 敵が全滅したか? したら、break */ /* 敵の攻撃 */ /* 味方が全滅したか? したら、break */ } /* 戦闘終了時の処理 */ }
とりあえず攻撃コマンドのみで作ってみる場合はこれでも雰囲気がつかめますが、もっと複雑な流れに対応させる場合はループ内にswitch文を配置するといいでしょう。
/* 例 */ void battle(){ int end_flag = 0; /* 0:戦闘継続 1:戦闘終了 */ /* バトルの進行制御。実際に作るときは列挙体を作っておくことをおすすめします。 */ int step = 0; /* 0:コマンド選択 1:敵/味方の攻撃処理 2:戦闘中イベント処理 */ /* 戦闘開始時の処理 */ while(end_flag == 0){ switch(step){ case 0: /* コマンド選択 */ step = 1; break; case 1: /* 敵/味方の攻撃処理 */ step = 2; break; case 2: /* 戦闘中イベント処理 */ step = 0; break; default: break; } /* かならず、0,1,2の順に流れるのであれば、switchブロック内でstepを設定する必要はなく、 */ /* switchブロック外でstep++するなり、forループにするなりすればよい。 */ /* 柔軟性を求めるのであれば、switchブロック内で条件に応じてstepを設定するようにする。 */ /* 戦闘終了条件判定処理(敵/味方のHPなどチェック) */ } /* 戦闘終了時の処理 */ }
バトルの進行はEnterキーを押すなど、一般にキー入力によって進んでいきますので、キー入力イベントキャッチ処理は外に出しておき、コマンド選択処理関数など各関数から呼び出すようにしておくと楽になります。
/* 例 */ /* イベントループ */ int event_loop(){ SDL_Event event; int iReturn; int iLoopEnd = 0; while(iLoopEnd == 0){ if(SDL_PollEvent(&event)){ switch(event.type){ case SDL_KEYDOWN: iLoopEnd = 1; iReturn = event.key.keysym.sym; break; default: break; } } SDL_Delay(1); } return iReturn; } /* コマンド選択 void command(){ int end_flag = 0; /* カーソルの初期表示 */ while(end_flag == 0){ switch(event_loop()){ case SDLK_UP: /* 上キーを押したときの動き */ /* 上キーを押したときの動きを記述する */ break; case SDLK_DOWN: /* 下キーを押したときの動き */ /* 下キーを押したときの動きを記述する */ break; case SDLK_RETURN: /* エンターキーを押したときの動き */ /* エンターキーを押したときの動きを記述する */ break; } SDL_Delay(10); } }
end_flagに0以外をセットすればループを抜けることができるので、コマンド確定した時に抜けるようにします。
こんな感じで処理を入れていけば、戦闘画面ができます。
以下、簡単に作ってみた例
戦闘開始
コマンド選択ステップ
攻撃対象選択ステップ
敵/味方の攻撃ステップ1 味方の攻撃
敵/味方の攻撃ステップ2 敵の攻撃
敵/味方の攻撃ステップ3 敵を倒したときの処理