前回 はかなり趣味に走ってしまい、「急に難易度上がった」「サンプル長っ!」などのご意見もいただき、ちょっとペースを戻したいとおもいます。
※ タイトルも短くしましたw
今回は、RPG などでよくみる、ポップアップ式の選択メニューを表示する関数を作成してみました。改造し易いようめっちゃシンプルなやつ。
ゲームのタイトル画面とか、ゲームオーバー時のコンティニュー時とか、アドベンチャーゲームの会話とか、RPG に限らずちょこまかと利用する機会があるかとおもいます。
今回のサンプル動画
今回のソースコード
今回の実装のメインは RPG_MENU 関数のため、ソースコードのメイン部分はこの関数を呼び出して、結果を表示しているだけです。以下の部分。
拡張案
基本的な機能しか実装していませんので、いろんな拡張の方向性があります。
例えば表示する項目が多い場合、2列や3列など、複数列で表示するメニューがあると便利かもしれません。表示部分を拡張して、カーソルの動きに左右を追加すれば実装できそうです。
枠に使うキャラクター文字が関数にそのまま記述されている(ハードコードされている)ので、それを変えるだけで枠の見た目を変えられます。同様にカーソルも。最もお手軽な改造かもしれません。
また今回は通常のコンソールに表示しているので、元にゲーム側でコンソールを使用している場合に、その表示を壊してしまうかもしれません。
これには対応方法が2つあって、まず1つは、テキストスクリーンに表示するバージョンを用意すればokです。今は表示に PRINT
命令 (省略形は?
) を使っているので、これを TPRINT
に置き換えるだけで実装できます。表示するスクリーンIDをグローバル変数、もしくは引数で指定できるよう実装するのが良いでしょう。
もう1つの実装方法として、表示する前に、現在の表示内容をバックアップしておく、つまり文字変数などにいったん保持しておく方法があります。メニューを消す際に、保存しておいた元の表示内容でメニューを上書きすれば元通り、という訳です。
また細かい機能として、メニュー項目の「ディセーブル」つまり一時的な無効化の機能もあると便利かもしれません。例えばゲームをセーブできない場面では、メニューの「セーブ」項目が灰色で表示され、選択ボタンに反応しない、などです。
より高度な拡張案
今回のメニューは、いわゆる「モーダル」な実装になっています。例えばアクションゲームを実行中に今回のメニューを呼び出すと、裏のアクションゲームは止まってしまいます。
メニューを表示している間もゲームを止めたくない、いわゆる「モードレス」なメニューの実装は、今回のようにお手軽ではなく、ゲームの実行エンジンに組み込む感じになります。少なくともゲームのメインループからのフック、つまり呼び出しを何らかの手段で実装する必要があります。
今回のサンプルの作り方から大きく逸脱するので、この「モードレス」なメニューに関してはまた別の機会に実装してみましょう。
今回の関数
今回のサンプルで作成&利用している関数に関して プチコン4 公式リファレンス にあわせたカタチで説明してみます。
LIST_WIDTH
LIST_WIDTH(文字列の配列)
文字列の配列を検査し、最も長い配列の文字数を返す。
引数:
文字列の配列: 検査対象となる
返値:
配列中で最も長い配列の文字数
例:
R=LIST_WIDTH(["str1","str2"])
MENU$[]=["str1","str2","str3"]: R=LIST_WIDTH([MENU$)
RPG_MENU
RPG_MENU(X座標,Y座標,文字列の配列,カーソル初期位置)
シンプルなRPG風のメニューを出し、入力待ちをする。
引数:
X座標: メニューの表示位置 (X座標) の数値
Y座標: メニューの表示位置 (Y座標) の数値
文字列の配列: 表示するメニュー項目
カーソル初期位置: カーソルの初期位置を指定する数値 (1が最初のアイテム)
返値:
選択したアイテムの番号 (1が最初のアイテム)
キャンセルした場合には負の値になる
例:
MENU$[]=["str1","str2","str3"]: R=RPG_MENU(4,4,MENU$,1)
というわけで
内容を軽くすると言ったけど、軽すぎかな?などと思いつつ。ただ、これくらい単機能のほうがわかりやすいかな?とも思う次第です。
今後、今回ご紹介した関数、もしくはその拡張を利用したコードをご紹介することもあると思います。プログラミングは蓄積や、それによる手抜きも大事ですからね!
それではまた。