B-Magaスマートフォン専用ページを表示B-Maga初心者向けのプログラミングについての情報や、フリーゲームの情報など、お知らせしていくブログです。プログラムの投稿の受付や、そのプログラムの公開などもやる予定です。氏=-=-=-=-=-=-=-=-=-=-今回のプログラム作成中にプチコン4が出ました。今回はまだ3号だけですが、もう少しお付き合い下さいw今回はコマンド入力ゲームです。メニューやメッセージは第三回でやったので、今回はRPGのキモである、素早さや力などの能力値を組み合わせた、戦闘部分を作りましょう。思い出したのが「週刊少年ジャンプ」の読者コーナーでやった「JBSクエスト」です。これは100の数値を早さ・力・身の守り・体力(HP)に分配したキャラを読者が投稿し、編集部が作ったプログラムで戦わせるもので、その方法を頂きました。実際の配分は人による操作と自動どちらでも可能にしました。★1.まず左の青いキャラクター(以下「左」)の名前を下画面で聞いてくるので、入力して「決定」を押して下さい。2.次にキャラの能力値の決め方を聞いてきます。自分で決めるなら「はい」を押して下さい。自動で決める「いいえ」だと5番まで飛びます。3.外見を聞いてくるので、十字ボタンの左右で選び、Aボタンで決定して下さい。4.次に能力値の振り分けです。十字ボタンの上下で4つの能力値を選び(3で選んだキャラがカーソル替わり)、左右で数を±してAボタンで決定して下さい。残りがゼロでなく残っていても、Aボタンが作動します。5.右の赤いキャラクター(以下「右」)も、2~4を繰り返します。6.左右のキャラクターが現れ、一方が勝つまでオートバトルを続けます。今回の様に二者が交互に攻めるゲームは、「ドラクエ1」「ポケモン」の他、オセロや野球もそうですね。初心者だとどうしても、自分側と敵側でそれぞれ処理を作ってしまいますが、それでは似た処理を二つ書くので無駄が増えます。今回は以下の方法でコンパクトにまとめました。名前や能力値を配列変数で定義し、左を添字[0]、右を[1]にします。攻撃する側(「攻撃側」と呼ぶ)の配列添字(今回もSを使っています)が例えば0だとすると、攻撃を受ける側(「防御側」と呼びます)あるいは次に攻撃側となる相手は、「S=1-S」とすれば、0と1が逆転します(実際に脳内で暗算してみて下さい)実はこれ「!S」と書けばいいのです!(「!」は数学的には否定の意味があります。AとBが同じでないは「A!=B」でしたね)これなら見えやすいので、相手のS番号をいちいち別の変数に代入しなくても、そのまま[!S]と書いて平気ですね。キャラの姿は第三回でも使った、30種類のRPG調スプライトです。配置方法は、簡単なゲームだとGAME2みたいに正面姿だけですが、折角RPGも作りやすいぐらいポーズの多い3号なので、「FF」等でおなじみ左右お見合いにしました。★1行のCHR$(10)は制御文字と言って、文字を出すのでなく、文字以外の他の操作をする文字コードで(例えば画面クリアはプチコンではCLSですが、昔のマイコンはCHR$(12)を使っていました)、19行で使います。2行では左右に使う配列を定義。能力値名の最後「のこり」は、厳密には能力値でなく、後述の振り分けに使いますが、一緒にした方が便利なのでこうしました。4行で左右のスプライト、5行でグラフィックとBG背景を定義しています。GIを作りました(機能は後述)。11~12行のゲーム開始ボタン処理はこれまでと同じですが、上記の通りBG文字を使わないので、代わりにBG背景をフラッシュさせています。13~72行にFOR~NEXTという処理がありますが、これでS番号の0と1つまり左右を並べて処理しています。この記述は他の場所でも出てきます。入力は古い高級言語だとINPUT命令がありますが、規定に合わない入力(数を入力するのに文字を入れたなど)をするとレイアウトが乱れるなどの欠点があります。今回は時間がなかったのでDIALOGを使いました。DIALOGはVisualBASICのMsgBoxによく似た命令で、3DSの下画面(BIGではTV画面)に、プチコンの文字より綺麗な字とレイアウトでメッセージを出します。命令でなく関数として使うと文字列入力が出来、字数制限も簡単です(今回はリストの通り8文字まで。8文字なのかは第五回参照)ところが文字を入力せず右の「戻る」を押すと、文字数ゼロで確定してしまうので、その時は17行で「ちゃんと入れろ!」とエラーを出して、18行のUNTILで再入力させています。DIALOGはアルファベットと数字しか入力できないのが欠点で(DIALOGによる入力文字を、ファイル名に使う為だと思われます)、これが不満だと思う方は、INPUTで作り直してみて下さい。次に19行でまたDIALOGを使い、各種設定をプレイヤーが決めるか、CPUが自動で決めるかを選びます。「はい」を選ぶと、DIALOGが返す値は-1ではないので、29行にジャンプします。★まずSK_ILL[S,I]の4項目全てにゼロが出ない様、1を入れておきます。残りの96は変数Aに入れておきます。先のSK_ILL[S,4]は、ここでは使っていません。能力値の割り振りは、4項目全部一つずつ乱数で入れると平均化しそうなので、23行のRND(10)+1で変数Bに1~10を代入し、Bを4項目のどれかに入れています。A>B」を入れています。27行は前述のスプライトキャラの先頭番号をS_CHR[S]に代入しています。演出によって姿を変える時は、このS_CHR[S]に一定の数を加えます。★ここからはプレイヤーが設定する処理です。COL8は、左右で青と赤それぞれの色を先に代入しておきます。34行で最初に496番の姿を出して、SPOFSで表示しています。37~42行は第三回のメニュー選択部分と似ていて、十字ボタンの左右を操作するたび、管理番号を±20ずらして次の姿を出し、番号がその範囲を超えたら、反対側の番号に戻しています。格ゲーなど最近のゲームでキャラを選ぶシステムと同じですね。15をかけているので、パッと押しただけでは反応しないかも知れません。★47~49行で操作表示を書いています。50行から、SK_ILL[S,4]だけ96を入れて残りは1から始まるのは、20行と同じです。54行の変数Yは、カーソルと能力の位置。カーソルは前述通りマイキャラを使うが、6倍では大きいのでSPSCALEで2倍にしています。55~68行が十字ボタンを使った割り振り。コンシューマーゲームでは「ウィザードリィ」のキャラ作成で有名ですね。57~60行が上下ボタンによるカーソル移動で、カーソルは動きの有無に関わらず68行で表示。57~60行が左右ボタンによる増減です。ANDの右は「それ以上そっちの方向に動かすと限界なので、もう動かせない様にするか」の判定です。66行では現在割り振った能力値を出しているが、@STATUSと同じレイアウトが使えないので、ここだけ違う配置で表示しています。これを68行でAボタンが押されるまで行います。ELSEIFは次回説明します。★スプライトを、75行でS_CHR[S]を基準に左右それぞれ相手を向く方向にし、76行で4段階の足踏みをさせ、77行で画面の外から中に動かしています。78行のGIは上部の名前表示です。左右の表示を終えたら、80行のWAKUでメッセージ枠を出し、81行で左右の早さSK_ILL[S,0]で乱数を作り、高い値が出た方から82行で「先手を取った」と表示します。81行の「S=(A<B)」という処理は次回説明します。左右の能力値を掛け合わせて、攻撃が成功か失敗か出すわけですが、掛け合わせ方にも何種類かあります。「能力値でサイコロを振る計算をする(能力値が16ならRND(8)x2回とか」は処理が複雑なので使わず、今回は攻撃側の攻撃力だけ「能力値をそのまま使う」、他は「能力値で乱数を作る」としました。SPANIM命令を使う時、S番号に対して「S-.5」という計算が何か所かで出てきます(プログラム言語では少数点の左のゼロを略していいので、「.5」は「0.5」の意味)。この計算をすると左がS番号0なので「-0.5」、右が「+0.5」と、ゼロに対し左右対称な値となります。攻撃や防御の時、これと「SPANIM..."XY+"」(この記述は前回勉強しましたね)を使って、左右どちらも向かい合ったり遠ざかったりの動きに使っています。84~86行は攻撃判定の準備です。MES参照)、約1秒たってからスプライトが動きます。87~91行で命中判定です。攻撃側と防御側の早さ(SK_ILL[S,0])で乱数を作り、防御側が大きかったら、89~90行で「かわした動き」を行います。89行は前述の「S-.5」で、攻撃側が迫ると同時に防御側をバックさせています。攻撃側の力(SK_ILL[S,1])から、防御側の身の守り(SK_ILL[!S,1])で乱数を作ったものを引き、代入先の変数Aがダメージです。ゼロ以下だったら敵が硬くてノーダメージですが、これだと双方の力と身の守りが微妙な場合、いつまでも決着がつきません。そこでこの場合94行でA=RND(2)すなわち0か1にし、「ドラクエ」の様に時々ダメージ1を出しています。すると最悪でも相手の体力をジワジワ消耗する上、体力が一桁という微妙な状況で死闘も発生します。ダメージ1以上なら95~101行でダメージ有りの処理。95行で防御側の体力(SK_ILL[!S,3])からAを引きます。体力表示がマイナスだとおかしいので、96行でSK_ILL[!S,3]がゼロ未満になったら、ゼロに変えています。@STATUSで能力値を再表示し、SPANIMは前回も説明した「"C"で透明と#WHITEを交互表示」、つまり初期のドラクエのように防御側が点滅します。ダメージ1未満なら103~104行でダメージ無しの処理。防御側はSPANIMで軽く上にジャンプさせました。最後に107行で「S=!S」として、攻守を入れ替えています。攻撃側が二回攻められるルールがあるなら、この処理をしなければ、同じ側が繰り返し攻撃側となります。★82行で変数WNに2を入れ、83行のREPEATからバトルを開始します。終了条件を入れる位置は「バトル中に防御側が負けた」か「最後のUNTIL」どちらかですが、今回は終了条件が前者しか無いので、101行で防御側の体力が1未満になったら、WNに攻撃側のS番号を入れ、108行のUNTILで「WNが0か1になった」らバトル終了と判断しています。109~113行が決着の演出です。109行のBGMPLAYは4と5番、110行のBEEPは88と89番で音の雰囲気が似ていたので、左右どちらが勝ったかで変数WNつまり0か1をプラスして、左右でサウンドを変えています。113行のSPCHRでも同じことをしていますが、これはS番号が!WNつまり負けた側です。S番号がWNが勝った側ですね。一度プレイするかの選択画面も、前述のDIALOGを使っています。両者の能力値を表示S番号の変数がSでなくS2なのは、@STATUSを呼ぶ前にSを使っているので、ここで同じ変数Sを使うと、処理がおかしくなる論理バグを起こすからです。FORMAT$関数については第五回でも書きましたが、書式が複雑なのでここでは略します。枠線を描く第三回の流用ですが、バトル開始前の一回しか使っていません。第三回では青でしたが、左の色とまぎらわしいので紺色にしました。枠線内の4行を全部消し、新たな表示に備えます。この4行はファミコン時代のRPGなどを多数調べて決めました。枠線内に文章を表示WAKUで描いた枠線に、L$のメッセージを出します。短い文章で右端にはみ出さない事が判ったので、長さチェックはせず、また表示文章の行数高さを扱う変数WYに+1して、次に表示する文章の位置処理の無駄を省きました。この処理と同時に、サウンドやウェイトを使う事が多いので、同時に処理できるようにしました。LBは0以上だとその音色のBEEPを出します。LWは1以上だとそのFPSのWAITで待ちます。代入された0~8に応じたRGB関数の値を返す第五回の流用。これで左のS番号0はCOL8(1)つまり青、右のS番号1はCOL8(2)つまり赤を出します。GPUTCHRで最後に色が付いた文字を出すテキストとBG以外で大きな字を手っ取り早く出すにはGPUTCHRですが、座標が小さなグラフィック単位だったり、目立たせるために背後に色を付けておくのが面倒なので、これを作りました。字を表示する座標の左上ですが、値はグラフィック単位でなくテキスト単位つまり横50x縦30です。後述の文字拡大を使っても、ここの座標は1倍角基準です。ゲームに必要な画面を一端クリアこれも以前と同じだが、毎回ゲームの内容に応じて、リセットする要素や方法を変えています。次回はまたまた「予習・復習3:条件判断とジャンプ命令」です)★今回の教材プログラムは、サーバにアップしてありますので、サーバからダウンロードしてご覧下さい。:BP54Q33J(連載が進んで新しい教材プログラムが追加されると、公開キーも変わります。:上の教材プログラムの見出しをご覧下さい。=-=-=-=-=-=-=-=-=-=-※次の更新は、レトロゲーレビューの予定です。|Seesaaブログ。