今回は状態(ステータス)を表示するウインドウを追加してみます。RPGにおいては、このステータスをどのようにするか、言いかえればキャラクタの状態をどのような要素で表現するか、はかなり重要な問題ですね。とりあえず、今回は大枠だけを決めて表示してみましょう。後ほど、戦闘シーンなどを作りながらどんなパラメータを用意するか、決定して行く事にします。
まず、主人公にはいくつかの「能力」を設定しその能力を基に実際にゲームに影響を与える「状態」を決めていきます。能力には、体力、筋力、魔力、敏捷性があり、その能力で最大生命力、最大精神力、攻撃力、守備力、耐魔力といった状態を決める事にしました。具体的に、能力が状態にどのような影響を与えるかは、今後ゲームバランスを見ながら少しずつ決めていきましょう。
それから、今回のRPGでは「レベル」はありません。一定の経験値に達すると階段状にレベルが上がっていくのではなく、経験を積むと少しずつ能力を向上していくようにします。経験は戦闘経験と魔法経験を設定し、戦闘や魔法の使用を通して能力が向上していくようにしましょう。
パラメータの大枠が出来たので、これらのパラメータに適当な値を入れてとりあえず表示してみます。パラメータは、ゲーム構造体gameのメンバにしておくと保存処理などがしやすくなりますね。このパラメータは、画面の右上に224×316ピクセルのウインドウを配置しこの中に表示する事にしました。
実際の表示処理は、ステータスウインドウのWM_PAINTメッセージへの応答という形で行うので、パラメータを更新した時はステータスウインドウを再描画すれば現在のステータスが表示される事になります。ただ、状態と能力をひとつの画面で表示するのは表示領域の大きさが足りず無理ですから、下の方にボタンを配置してこのボタンで状態/能力の表示を切り替えるようにしましょう。そのためには、game構造体に現在の表示状態を示す変数vStateを追加して、これが0なら状態、1なら能力を表示するようにします。この処理は、ボタンがクリックされるたびにステータスウインドウに送られてくるWM_COMMANDへの応答でvStateとボタンのテキストを変更すれば良いですね。
case WM_COMMAND: /* 状態/能力ボタン */ SetFocus(hwMain); /* フォーカスをメインウインドウに戻す */ if (game.vState==0) { /* 現在状態表示 */ game.vState=1; /* 能力表示に切り替え */ SetWindowText(hwBt,"状 態"); } else { /* 現在能力表示 */ game.vState=0; /* 状態表示に切り替え */ SetWindowText(hwBt,"能 力"); } InvalidateRect(hwState,NULL,FALSE); UpdateWindow(hwState); /* 再描画 */ break;
最初にフォーカスをメインウインドウに設定しなおしているのは、キー入力処理でフォーカスがメインウインドウになければ入力を無視するようにしてある(これをしないと他のアプリの操作中にキーを入力しても反応してしまう)からです。フォーカスを戻さないと、一度ボタンをクリックすると以降は移動やリターンキー入力が無視されてしまいます。
描画処理の時は、まずgame.vStateを見て状態/能力どちらを表示するか決めます。後は、DrawTextで位置を決めながら描くだけですね。今回は。フォントサイズを24にして一行を高さ32ピクセルで描いてみました。
hdc=BeginPaint(hwnd,&ps); FillRect(hdc,&rec1,GetStockObject(BLACK_BRUSH)); SelectObject(hdc,hState); /* テキスト描画の設定 */ SetTextColor(hdc,0x00ffffff); SetBkMode(hdc,TRANSPARENT); if (game.vState==0) { /* 状態表示 */ DrawText(hdc,"生命力",-1,&recT1,DT_SINGLELINE|DT_VCENTER); wsprintf(lpszBuf,"%3d",game.life); DrawText(hdc,lpszBuf,-1,&recT2,DT_SINGLELINE|DT_VCENTER); DrawText(hdc,"/",-1,&recT3,DT_SINGLELINE|DT_VCENTER); wsprintf(lpszBuf,"%3d",game.mlife); DrawText(hdc,lpszBuf,-1,&recT4,DT_SINGLELINE|DT_VCENTER); recT1.top=40; /* 表示位置設定 */ recT1.bottom=72; recT2.top=40; recT2.bottom=72; recT3.top=40; recT3.bottom=72; recT4.top=40; recT4.bottom=72; DrawText(hdc,"精神力",-1,&recT1,DT_SINGLELINE|DT_VCENTER); wsprintf(lpszBuf,"%3d",game.sp); DrawText(hdc,lpszBuf,-1,&recT2,DT_SINGLELINE|DT_VCENTER); DrawText(hdc,"/",-1,&recT3,DT_SINGLELINE|DT_VCENTER); wsprintf(lpszBuf,"%3d",game.msp); DrawText(hdc,lpszBuf,-1,&recT4,DT_SINGLELINE|DT_VCENTER); ・ ・ 以下略 ・ ・ } else { recT1.top=8; recT1.bottom=40; recT2.top=8; recT2.bottom=40; DrawText(hdc,"体力",-1,&recT1,DT_SINGLELINE|DT_VCENTER); wsprintf(lpszBuf,"%3d",game.vit); DrawText(hdc,lpszBuf,-1,&recT2,DT_SINGLELINE|DT_VCENTER); ・ ・ 以下略 ・ ・ } EndPaint(hwnd,&ps);
ステータス表示も追加され、見た目はかなりRPGらしくなってきました。これから、いよいよ戦闘、そしてイベントといったRPGの「本質」に迫って行くことになります。