2019年03月18日

プチコンゲームプログラミング講座~第五回「二進数と10進数と16進数」

文 プチ太郎 氏
=-=-=-=-=-=-=-=-=-=-
 今回はサンプルゲームを一回お休みして、プログラムやコンピュータ技術の基本について、復習をしたいと思います。自分でゲームを作った事がある人にとっては、え?またそんな所から戻って説明?と思いたくなるものです。しかしこれまで連載を続けて来て、サンプルゲームの後に説明をするより、「ここは先に基礎を説明しておいた方が、短く収まる!」という所が多数出てきました。そこで連載も板についてきたので、今回これをやる事にしました。
 この連載をどれだけのレベルの初心者が、どれだけ熱心に読んでいるかも、直接見えないのですが(ツイッターで第四回の告知にふぁぼが10以上付いたのは見ました…w)、もしそんな初心者がいたら、今回説明している事と、これまでの連載を見比べてみて下さい。わからなかった事が、わかるかも知れません。
 サンプルプログラムはゲームでなく、一画面の小さなものが多数登場します。ある程度の長さがあるプログラムはサーバに入れましたが、特に短いものは入っていないので、画面を見て打ち込んでみて下さい。

★ 二進数と10進数と16進数の基本 ★
 数の数え方の基本はどうか? そう聞かれた時の人間の基本的な答えは、「何もないとゼロ。1、2、3…と増えて、9から区切りがつけて10。で100、1000…」ですね。
 しかし電気を使う機械は、電気が通らない「0」か電気が通る「1」の2段階しか判りません(これをビットと言います)でも2つ並べると00,01,10,11の4段階が判ります。3桁にすると000,001,010…110,111の8段階。4桁で16段階。人間が使えるくらい便利な段階にすると、最低でも8桁、つまり00000000から11111111までの256段階が必要となりました(これをバイトと言います)これが二進数です。
 皆さんが遊んでいるTVゲームの中にも、出てくる値が2のべき乗倍か、8の倍数になっているものが多数あります。ゲームで遊んだり、動画や本を見てみましょう。「選べるキャラが4種類」「最大8個」「16分の1の確率で発生」「32歩動くと発生」「64面でループする」…これは機械語でプログラムを作る場合、こうした倍数が一番コンパクトにまとまるからです。8の倍数では他にも48、128、192、4096など、どこかでよく見る数字があります。これらは丸暗記必須ではないが、掛け算の九九のように覚えておくと、プログラム作りが一段楽になります。
 しかし二進数と10進数では桁上がりの基準が違い、対応がわかりにくい。そこで10進数で使う0~9の他に、アルファベットのA~Fを加えて16個としました。これが16進数です。
 また数の数え方は、1からが基本と思う人も多いと思いますが、実はコンピュータでは0から数えた方が便利です。以下のプログラムを実行してみましょう。

k05mod.jpg

(短いプログラムなので、サーバ登録なし)
 右の数字が必ず、0から同じ番号までの繰り返しですね? このMODは関数のように見えますが、「+-*/」と同じ計算記号で、割り算の割った数でなく余りを出します。ゲームによくある「n回ごとに繰り返し」処理は
IF 繰り返しの基本となる数(タイマーと呼びます)==n THEN 処理実行:タイマー=0
と書くより、この
タイマー=(タイマー+1) MOD n
IF (タイマー MOD 実行タイミングの数値)==0 THEN 処理実行
を使う方が、コンパクトです。

★ さまざまな機能の説明の準備 ★

ex1.jpg

 二進数・10進数・16進数を表に並べてみました。16進数がコンパクトなのが判ると思います。あともう一つ、覚えてほしい事があります。条件判断文で出てくるANDとORは、数学や英語を勉強すれば出てくるので、本来の意味が「どっちも」「どちらか一つでも」なのは、プログラムをやる人の歳なら判りますね。では二進数の計算「00101001 AND 01100101」や「00101001 OR 01100101」は答えられますか? いきなり見せられても出来ないが、縦に並べれば簡単です。つまりANDは「どっちも1の時だけ1」、ORは「どちらか1なら1」を返すのです。
00101001
AND 01100101
------
00100001
00101001
OR 01100101
------
01101101

★ 進数の変換方法 ★
 二進数と16進数はそのままプログラム上に書いても、ちゃんと数として識別されないので、変換方法も書きましょう。少し昔のパソコンだと、前述のMODなども使って複雑な計算をしたが、プチコン3号の強力な命令は、これも簡単に出来ます。

k05bin.jpg
(短いプログラムなので、サーバ登録なし)

 10進数以外から10進数への変換がVAL関数です。これは画像にある通り、数字の書式をした文字列を、本当の数にして返しますが、頭に"&B"(バイナリのB)を付ければ二進数、"&H"(ヘックス=ラテン語で「6」)を付ければ16進数と理解し、10進数を返します。逆に数からBIN$関数は二進数、HEX$関数は16進数を返します。関数に$が付いている通り、返すのは数字型でなく文字型です。

★ ビット単位での応用1:BUTTON関数 ★
 ここでこんなプログラムを用意しました(ここでは進数変換にFORMAT$関数を使っていますが、書式が難しいので説明は略します。各自で調べて下さい)実行してボタンを押してみましょう。表示される三種類の数が変わりますが、何を意味するか、もう判りますね? BUTTON関数は何も押さないとゼロで、押されたボタンのビットだけ1にします。なおZLとZRは拡張パッドを付けないと判定されません。

ex2.jpg

k05but.jpg
(短いプログラムなので、サーバ登録なし)

 前回書いた「IF BUTTONの値==値」の「他のボタンを押さず、この値のボタンだけ押した」は、どれか1つのビットだけ判定し、ボタンを複数押すと無効です。「IF (BUTTONの値 AND 値)」の「他のボタンを押しているにかかわらず、この値のボタンも押した」は、判断の対象としているビットのそれぞれを判定し、複数押しても有効です。前述したANDを使ったビット演算と同じです。

★ ビット単位での応用2:SPCOLで当たり判定 ★
 次は前回のシューティングゲームでも使った、SPCOLによる当たり判定の復習です。赤いキャラ(S番号0)は十字ボタンで、青いキャラ(S番号1)は丸ボタンで動きます(ボタン判定の動かし方がまだ教えていない方法ですが、これは後日やります)どちらも動かして緑のキャラ(S番号2)と重なると音が出ますが、黄色のキャラ(S番号3)と重なっても音が出ません。
k05spc.jpg
(ファイル名「K05SPC」)

 SPCOLはパラメータの省略方法が何種類もあり複雑ですが、ここではパラメータが3つの「SPCOL S番号,スプライト拡大でも当たり判定を同期するか(見やすくするために拡大しています),マスク」で定義しています、4つのキャラのマスクのビットは、リストにある通り二進数で書いていて、同じ位置に1と1があるキャラだけ、当たりとなって音が出ます。ここの0と1を変えると、当たり判定の組み合わせも変わります。ビット単位での使用は、この他にもSPDEF命令でも使っていますが、これは後日、スプライト全般の説明の時にお話ししましょう。

★ アスキーコードへの応用 ★

k05asc.jpg
(短いプログラムなので、サーバ登録なし)

 上の画像のプログラムを実行すると、16x16=256字が並びます。少し昔のパソコンはこれだけあれば、人間が見やすい文字に対応できました。これをアスキーコードと言います。文字が8x8ドット単位で作られているという事にも注目しましょう。プチコン3号より古い方がわかりやすいので、ここではPC-8001とプチコンmkIIのアスキーコード表も見てみましょう。32番(スペース「 」)から95番(アンダーバー「_」)まで見ると、プチコン3号のスプライトとBGで出せる、文字とコード番号に対応していますね?ゲームに使える大きな字は、この対応する番号のBGを使っています。

asc_pc.jpg

asc_p2.jpg

k05bg.jpg

 ひらがな等も出る現代のコンピュータは、これだけでは足りないので、文字コードの数がもっと多くなっています。プチコン3号も65536種類あり、ギリシャ文字や、途中のバージョンから追加された漢字用の美咲フォントもここに入っています。

★ 色への応用1:RGB関数 ★
 色の基本はR(RED=赤)G(GREEN=緑)B(BLUE=青)だという事も、プログラムが出来る人なら大体知っていると思います。色の指定がプチコン3号ではテキストのみ数字で、その他はRGB(0~255,0~255,0~255)のためわかりにくく(高性能機の宣伝にある「1600万色」というのは、この256x256x256=16777216の事)、後から#REDなどの定数リテラルが追加されました。
 昔のパソコンや、初代プチコンのスプライトとBGでは、8種か16種あるカラー番号に対して別の値を変えると、画面上のその色全てを瞬間的に変える、「パレット」という機能がありました。しかしプチコン3号ではこれが廃止され、グラフィックページや画面に描かれている基本的なキャラに対し、SPCOLOR命令・RGB関数・定数リテラルで色を指定すると、指定した光の三原色だけ色が抜かれる(暗くなる)という仕様になってしまいました。スプライトで全体的に白っぽいキャラが多いのは、それで使いやすくする為です。
 定数リテラルの数を直接表示してみると、例えば「? #YELLOW」だと「-460800」と表示されます。これはプチコン3号の数値が32ビットで、左端1ビットはマイナスかの符号に使っているからです(つまり数は31ビットで±2147483647の範囲です)「? HEX$(#YELLOW)」だと「FFF8F800」と表示するが、これは左から2バイト区切りで「スプライトで使う透明の濃度=FF」「赤(R)の濃度=F8」「緑(G)の濃度=F8」「青(B)の濃度=00」の4つが並んでいる訳です。RGB関数で言う「RGB(透明度,赤濃度,緑濃度,青濃度)」です。

★ 色への応用2:8種の数で色を出すDEF ★
 このDEFを使うと、0~7の数を入れれば、PC-8001など昔のマイクロソフト系マイコンでお馴染みの、8色のカラーコードを返します。ただし0は透明でなく黒なので注意。

ex3.jpg

k05f8.jpg
(ファイル名「K05F8」)

★ 色への応用3:16種の数で色を出すDEF ★
 プチコン3号の16色カラーは大体この表の通りですが、全てが規則的ではありません。RGB濃度は00とFFの他に、中間の80(10進数で128)などを加え、約16種類になっています(実際には微妙に違う濃度も使われています)定数リテラルを使う場合、文字用は#の後にテキストのTが付き、グラフィック・スプライト・BG用はTが付かないので注意しましょう。そしてこの色指定にRGB関数や定数リテラルを使わず、テキスト同様に0~15の数字で使いたい!という人は、こちらを使って下さい。「パックマン」や「ドラクエ」みたいに同じキャラを色違いで出すなら、この2つのDEFは便利です。

ex4.jpg
k05f16.jpg
(ファイル名「K05F16」)

★ 色への応用4:白黒キャラを16進数に圧縮する ★
 プチコン3号には文字のデザインを変えるFONTDEF命令があり、1ドットに0000~FFFFの4バイト(使い方はプチコン3号のヘルプをご覧ください)x横8ドットx縦8ドットの文字列で編集を行いますが、グラフィックでもこれと似た事が出来ます。以下を実行してみましょう。
k05t2.jpg
(ファイル名「K05T2」)

 グラフィックによるキャラクタが出てきましたが、これはドットが「なし・なし・ある・なし」なら0010→2、「ある・ある・ある・なし」なら1110→Eと、16進数で出来るだけコンパクトにしています。これだと8x8ドットのキャラは16進数で16文字つまり8バイトにまとまります。ただし色が0(一般に透明か黒)か1(一般に白)しか使えないので、描く時に色をつけるか、白黒で描いてSPCOLORなどの命令で色をつける必要があります。

★ 色への応用5:16色キャラを16進数に圧縮する ★
 こちらは色を増やして、0~Fの16種類の文字列で16色を格納、つまり1ドット1バイトです。それだと人の姿を描くにはまだ足りず、面倒さをはぶくためもあり、文字列に"*"を入れると輪郭線の黒、"."で何も描かない空白、"■"で肌色のRGB(256,192,128)が出る様にしてあります。
k05t16.jpg
(ファイル名「K05T16」)

 上記のプログラムは、GPAGE命令を使ってGRP4(グラフィックページの4番)に書けばスプライト、GRP5に書けばBGが簡単に作れます。ただしプログラムに入る、つまりリストが改行ありだと40字程、オプションで改行なしにしても100字程が限界なので、それより大きく複雑なグラフィックの場合、ペイントツールで描いた方がいいでしょう。
 こうしてグラフィック機能で文字キャラクタを変えて、ゲームに使うキャラを、当時としては細かく描ける様にする機能を、PCG(Programmed Character Generator=プログラム式キャラクタ生成)と言います。プチコンmkIIではCHRSET命令でスプライトやBGだけでなく、文字もPCG編集出来る様になっており、文字のドットも白黒二色でなく、16色フルに変えられました。

(第六回につづく 次回はまたサンプルゲームに戻ります。アクションゲームを予定しています)

★今回の教材プログラムは一部を除き、サーバにアップしてありますので、サーバからダウンロードしてご覧下さい。
公開キー  :7ZNYX3Z4(連載が進んで新しい教材プログラムが追加されると、公開キーも変わります。この公開キーでダウンロード出来ない場合は、連載の一番新しい回の公開キーをご利用下さい)
プロジェクト:KOZA
ファイル名 :上の教材プログラムの見出しをご覧下さい。
=-=-=-=-=-=-=-=-=-=-
次の更新は、3月21日、『URAURA! Game Review』の予定です。お楽しみに!

2019年02月18日

プチコンゲームプログラミング講座~第四回「シューティングゲームを作ろう」

文 プチ太郎 氏
=-=-=-=-=-=-=-=-=-=-
 やっとそれらしい中規模ゲームまで行きましたが、アクションゲームの王道であるシューティングゲーム(以下STG)が出ていませんでしたね。STGと言っても固定画面、縦スクロール、横スクロール、全方向などいろいろあります。縦STGはプチコンのサンプルゲームでGAME4がありますが、今回はGAME4と違う、縦スクロールSTGを作りましょう!

教材プログラム 4 「クセヴィオウス」(ファイル名「KOZA04」)

koz04_s1.jpg

★ ゲームの内容と説明 ★
 ゲーム名は、いい名前が思いつかなかったもので…wあと本来こうしたゲームは沢山の敵・地上物・爆弾・ボスキャラがいますが、今回もプログラムや説明文が肥大化するので見合わせました。と言っても改造・追加しやすいよう作ってあるので、今後これにさらに追加したサンプルゲームを発表できるかも知れません。
 今回から動かすキャラが非常に増えたため、これまでの連載で少しだけ使ったスプライトや配列変数を、沢山使っています。スプライトをゲームで使うためには、ただ表示させたりキャラを変えるだけでなく、「現在どのスプライトキャラがどこでどんな状況になっているか」常時管理・判定しなければいけません。それにはSPVAR関数やOUTオプションの方法もあるんですが、ここではスプライトと同じ条件で配列変数を設定する方法です。
 一般にスプライト管理番号はゼロから始まり、1,2…と増えていく。配列の添字もゼロから1,2…そう!スプライトと配列で、番号を一致させてしまえばいいのです。これが初心者には簡単でいいと思います。ここではこれを「S番号」と書きますが、連載での便宜上のもので、プチコンユーザやプログラマーで広く使われている訳ではありません。
 ヘビゲームでは動きが簡単なので、キャラを16ドットずつ動かしましたが、今回は微妙なズレが生死を分けるSTGなので、1ドット単位の移動や当たり判定です。

koz04_p1.jpg

★ プログラムの説明1:初期設定とメインループ ★
 まずS番号は、何番から何番までどのキャラに使うか決める事が重要です。全部の配置を実数にすると修正が面倒なので、各キャラの数を自機(変数A_MAX)・自弾(同じくB)・敵(C)・敵弾(D)で設定して、各キャラのS番号の最初(●_s)と最後(●_E)を求めています。ちと面倒に見えるが、紙に書いて計算して行くなどして、それぞれのS番号を復習してみましょう。その下のFORループを使った8~10行は、キャラの種類ごとの初期設定です。9行目のSPCOLの「8,16」は、当たり判定の範囲を横8ドットx縦16ドットに変えるという意味です。
 S番号で使う配列は以下の通り。あまり使っていない配列もありますが、将来プログラムを拡張しやすくするためです。
・SS[i]→キャラの状態(ステータスのS)
・SX[i],SY[i]→縦横の座標
・SVX[i],SVY[i]→移動方向(ベクトルのV)
@INIT1 リプレイ時の初期設定
@INIT2 ミスした後の初期設定
 自機のデザインは、現代型縦シューにふさわしいデザインが三種類あったので、22行でRND関数により、三種類をランダムに出してみました。S番号[0]は前述通り自機の初期設定です。OPは当時のナムコゲーを真似てみました。24行で字を出した後、変数OPをゼロにして、短時間で演奏終了するBGMPLAY 4を流しています。次の@LOOPでOPがゼロ(まだ1になってない)かつBGMCHKがゼロ(BGMが終わって聞こえなくなった)ら、OPのフラグを1にして先の字を消し、エンドレスのBGMPLAY 25を演奏します。
@LOOP メインループ
 28行目は本来ゲームに必要ありませんが、学習用に入れてみました。自機がスタートする毎に、左上に出る変数CNは、WAITが1進むたびに蓄積するカウントが表示されます。また以前ちょっと書いた、OUTという予約語が登場しています。これは通常の命令が「命令語 パラメータ1,パラメータ2,パラメータ3…」と書く所を、「命令語 パラメータ1 OUT パラメータ2,パラメータ3…」と書くと、パラメータ1(この場合はBG0番)のパラメータ2やパラメータ3の今の値が読み込める…というものです。使える所しか使えないオプションですが、うまく使えば便利です。ここで読み込んだ値はBG0のX座標とY座標で、これを右に表示しています。これでスタート時からどこまで進んだかが判るでしょう。「どこまで進んだら、どこでどんなザコ敵やボスキャラが出てくるか」は、この数値で判定すればいい訳です。自機の当たり判定は@ATARIの結果、SS[0]が1なら@DEADに★行きます。

★ プログラムの説明2:定義済み処理(メインキャラ) ★
 STGやアクションゲームのキャラの処理は、一般に4つか5つ。「自機」「自機の攻撃手段(ここでは弾)」「敵」「敵の攻撃手段」「特殊なキャラ(ボスなど)」です。今回特殊なキャラはいないので4つとなります。
@LOOPでの自機移動のタイミング
 @JIKIから@TEKITAMAまで4種類のキャラを、順番にGOSUBで呼び出します。S番号が複数ある時の処理は前述したが、「GOSUBで呼ぶ前の@LOOPにFORを書く」「GOSUBで呼んだ後の各処理にFORを書く」のうち、今回は前者を使っています。
@JIKI 自機
 自機は1キャラだけなのでFORは使いません。基本はヘビゲームと同じで、十字ボタンの方向に動くだけですが、違う点はBUTTON関数の取得です。以前の「IF BUTTONの値==値」だと「他のボタンを押さず、この値のボタンだけ押した」ですが、今回の「IF (BUTTONの値 AND 値)」だと「他のボタンを押しているにかかわらず、この値のボタンも押した」になります。これだと右と上どちらも押したと判定すれば、右上に進めます。この辺は次回説明します。
 STGではここから下、自機以外は動かし方の基本が同じです。
1.画面に出ていない(このプログラムではSS[i]が-1)なら、条件によっては画面に出す。
2.現在画面に出ていて、敵や味方に当たったり、画面の端に入っていたら、必要に応じて消えた処理をする。
3.でなければ座標を進め、新たな座標のキャラを表示する。
@JIKITAMA 自弾
 49行から新規出現処理。SS[i]が-1かつBUTTON()関数でAボタンが押されていると、自機の座標変数などを自弾に移し、発射音を出します。変数S_Tは、一発撃つとしばらくカウントをとって時間待ちをする連射間隔用です(値の変え方は後述)。58行から出現ずみの処理。59行では自弾が画面上まで行ったら、@S_LOSTで消しています。60行では1ドット上に進めて、SPOFSで表示し直しています。
自弾が敵に当たった時の処理
 ここから当たり判定の説明です。文字(CHRCHK)・グラフィック(GSPOIT)・BG(BGGET)は「その座標に何が描かれているか」だけでいいが、スプライトは各自がバラバラに動くので、似た命令が使えません。当たり判定は「SPHITSP式」「座標式」の二種類のうち、ここでは前者を使っています。
 SPCOLはこの処理に必ず必要な命令で、当たり判定を出したい双方のスプライトに、同じマスク(16進数で同じ場所のビットに1を入れる)を設定します。今回は「自弾が敵に当たった」の判定用に、一番右の"00000001"だけ使っています。この辺は複雑なので次回説明します。マスクを0に戻している処理があるのは、爆発中もマスクに当たり判定があると、余計に当たってしまうバグの防止です。
 63~68行が当たり判定のメイン処理で、SPHITSP(当てられたか判定したいS番号,当たってきたS番号の最初,当たってきたS番号の最後)関数の結果をSHに入れます。これが当たってないと-1、当たったらそのS番号を返すので、64行から当たった時の処理をします。65~66行でスプライトを爆発のアニメーションに変え、SS[SH]に-1より小さな値を入れて、爆風表示中はこのS番号で新規出現しないようにしています。
@TEKI 敵
 74行から新規出現処理。SS[i]が-1で、かつ64分の1の確率で出しています。出現位置(SX,SY)は上、移動は左右(SVX)がどっちか斜めで、下(SVY)は2ドット。79~80行は前述の爆発中の時間待ち処理で、SS[i]が-1になるまで+1し続けています。現在出現中のフラグは現在、SS[i]を0にしているが、1や2でも動く様になっています。これは何種類も敵を出した時、出現条件や移動方法の違いを「ELSEIF SS[i]==…」で区別するためです。82行は@JIKITAMAと同じで画面外に行った時の消滅処理、 85~86行で移動と当たり判定をしています。
@TEKITAMA 敵弾
 敵弾は「敵の処理中に出す」「敵弾の処理中に出す」の二種類あり、今回は後者つまりここでなく@TEKIの87~88行でやっています。S2で敵弾のS変数をランダムに出し「OPが1(OPが終わっている)」「SS[S2]が-1」「発射元の敵が画面内の一定の座標か」「もう一度乱数で確率を出す」の条件に会えば、敵Sの位置から敵弾S2を出現させます。出現していたら下に3ドットずつ移動。@S_LOSTや@ATARIは後述します。

koz04_s2.jpg

★ プログラムの説明3:定義済み処理(その他) ★
@ATARI 座標式の当たり判定
 座標式は「インベーダー」の砲台やUFOのように、キャラの数や存在位置が限られていると、処理が簡単という長所があります。ここでは自機の[0]とGOSUBで呼び出す前のS番号で、縦座標と横座標の差を求め、どちらも15未満だったら自機に当たったので、SS[0]に「死亡フラグ」を立てています。ABS関数は本来「絶対値」を出すもので、数にマイナスがあると無条件で除去しますが、このように座標による当たり判定には最適です。
@S_LOST 特定のスプライトを画面から消す
 変数S2に入ったS番号をSPOFSで画面外左上にやり、SS[i]を-1にして、画面上も変数上も消します。
@RESET ゲームに必要な画面を一端クリア
 110行はヘビゲームと同じ。111行はS番号全て@S_LOSTで消しています。BGOFSはBYから15を引いた、つまり背景の下から15行目までBGをずらす処理。BGANIMは順に「0=BG0番の」「"XY"=座標を」「-600=600fps(10秒間)を一気になく徐々に」「0,0=BG座標0,0まで変えて」「0=無限に繰り変えす」という処理です。SPANIMやBGANIMは、こうして無限に同じことを繰り返す処理が可能で、同じ働きをする別の命令(ここではBGOFS)を使うと、ピタリと止まります。
@SCR 「DEF JI」を使って、スコアやハイスコアを表示
DEF JI LX,LY,L$ BGを使って文字列を表示
@DEAD ミスおよびゲームオーバー
 127~128行は@JIKITAMAと割と同じです。129行ではまたOUTを使ってBG座標を取得し、すぐOUT無しのBGOFSで実行して、BGANIMを止めています。アクションゲームは三回死ぬとゲームオーバーが基本なので、@INIT1でZAN=3と設定し、130行でマイナス1して、ZANがまだゼロでなければ@INIT2に戻り、でなければゲームオーバーです。

koz04_p2.jpg.jpg

@MAP 背景のDATAを読み込んでBGの0番に描く
 一度しか使わないが行数が多く、全部前に置くとリストが見にくい場合は、このようにサブルーチンにして後ろに置きます。
 変数BYは地形に使うBGの縦長さで、BGSCREEN命令で0番BGのサイズを変えています。140行は第二回で説明した、各画面表示要素の高さ設定で、これがそのままだったり設定を間違えると、例えば地上物の下を飛行機がくぐったりしますwそこでFORループでBGの0(背景)を16、1を12、2を8、3(文字表示)を4の高さに設定しています。(ただし1と2は現時点で未使用)。GPRIOも第二回にあった通り。
 141行はBG0をまず全部森(103番)で埋めていますが、ゼビウスのように最初と最後の15行ずつは森にしているので、森の一行下である15を変数Yに入れ、一行描くたびに155行でYを増やしています。
 142~157行はいよいよ、BGに不規則なBGキャラを入れる方法です。プチコンのエディタを使い、BGSAVEで保存する方法もありますが、今回は「ドラクエ1」の街などのようにあまり広くないので、DATAで書いたものを読むという、簡単な方法です。
 READでA$を読み込み、このA$に一番最後の""(文字列長さゼロ)が入るまで(ここでは20行分)REPEATを続けます。FOR X=0 TO 24とMID$関数で、A$の0番目から24番目までの文字列を一つずつ求めてB$に代入します。そして147~152行で、このB$が何という文字列であるかで、BG番号をCに代入し、153行のBGPUTで書き込んでいます。実は146~153行は、配列を使うと短くなるので、できる人は考えてみて下さい。本当はゼビウスに似せたかったのですが、時間が間に合わず、HSPのサンプル用フリーゲームである「シューティングゲーム」の地形画像ファイルを参考にしました(^^;

★ プログラムの修正方法 ★
 処理が簡単なSTGは、パラメータ修正で難易度を変えやすい点も特徴です。最大数やスピードなど修正できる所を並べてみました。いろいろいぢって、一喜一憂してみて下さい。なお数は1以上でないと、エラーになるものがあります。

koz04_e1.jpg

(第五回につづく なお次回はサンプルゲームを一回お休みして、コンピュータには欠かせない二進数・10進数・16進数と、プログラミングへの応用についてお話します)
★今回の教材プログラムは、サーバにアップしてありますので、サーバからダウンロードしてご覧下さい。
公開キー  :D8EA4CD(連載が進んで新しい教材プログラムが追加されると、公開キーも変わります。この公開キーでダウンロード出来ない場合は、連載の一番新しい回の公開キーをご利用下さい)
プロジェクト:KOZA
ファイル名 :上の教材プログラムの見出しをご覧下さい。
=-=-=-=-=-=-=-=-=-=-
※次の更新は、2月21日、『レトロゲーレビュー』の予定です。お楽しみに!

2019年01月21日

プチコンゲームプログラミング講座~第三回「コマンド入力ゲームを作ろう」

文 プチ太郎 氏
=-=-=-=-=-=-=-=-=-=-
最初の三回がみんな、ボタンを押して進むプログラムだったので、ちょっと講座の速度が遅くなっちゃったかな。無理しない程度に、ペースを上げて行きましょう。
 反射神経にたよるプログラムが続いたので、ここでもう一つのTVゲームの代表格である、入力するまでコンピュータが待ち続けてくれるゲーム、つまり「コマンド入力ゲーム」を作ってみましょう。代表作にはシミュレーションゲーム(スタートレック、シムシティなど)やロールプレイングゲーム(ドラクエ、プチコンのGAME2など)がありますが、今回はアドベンチャーゲーム(以下、略す場合ADV)で行くことにしました。
 ADVと言っても、当初は「サガセ ココ」と入力したり、コマンド入力式になっても「みる」「うごかす」「なぐる」とコマンドが多かったり、遊びにくいものでした。しかし、今の場面から2~3の項目どれかを選択すれば、木の枝のように展開が分かれていって、バッドエンドやグッドエンドがある…というものなら、かなり簡単です。ADVではないが近年のゲームでは、「アイドルマスター」がこれでしたね。
 ここではRPGやギャルゲー、特に最近ソーシャルゲームで目にする機会も多い、キャラクターやメッセージが出る会話システムのサンプルゲームを紹介し、プログラムを見ていきましょう。
教材プログラム 3 「ミニアドベンチャーゲーム」(ファイル名「KOZA03」)

koz03_s1.jpg

★ ゲームの内容と説明 ★
 あなたは、手に入れればプログラミングが上手くなるという、伝説の宝石「プチコン」を探して、このスマイルブームの町に来た。町にはいろんな人も住んでいるが、モンスターもいるという。無事にプチコンをゲット出来るだろうか?
 先ほども話した通り、2~3のコマンドを選んでグッドエンドを目指すゲームです。また選ぶだけではつまらないので、誰かに会ったり中間目的のアイテムを入手したかなどの、いわゆる「フラグ」も使っています。
 ADVの進み方にもいろいろありますが、今回はスタート地点から枝分かれに進むという簡単なルートにしました。しかしいつかは奥まで行きつきます。一方通行で進めないと、ハマってラストまで行けない可能性があるので、一部を除きバック出来る様にしています。
 今回から急に270行以上の量となり、驚いた方もいると思いますが、ADVという事で、過半数がそれぞれの場面の会話に使われているだけです。実際にリストを見ると、同じような処理ばかり並んでいるのが判ります。
 なおBGMは、一部のシーンを除いて流れません。現代のプログラム技術では任意に流す事など簡単なのですが、今回いろいろあって開発時間が短く(言えない…コミケで三日間つぶした後、正月三が日で急遽仕上げたなんて…w)、実装のデバッグが間に合いませんでした。ゴメンネ!

★ プログラムの説明1:初期設定 ★
 2行:DIM 変数[数字(添字:ソエジと読む)]という記述があります。これは配列(はいれつ)変数と言って、中規模上のプログラムでは避けて通れない大事な要素なので、少し字数を使って説明します。同じような変数と処理を「変数A1の処理:変数A2の処理:変数A3の処理…」と並べると、大変な量になってしまいます。そこでDIMで角カッコの中の数字を定義すると、定義した数字の分だけ、それぞれが別の変数として使えます。例えば三つの似た変数を使いたいなら「DIM A[3]」と書くと、A[0]・A[1]・A[2]がそれぞれ変数として使えます(DIMは3、添字は0~2である点に注意!)これを全部似たような処理で使うなら、「FOR I=0 TO 2:変数A[I]の処理:NEXT」と書けば、三つ全部が一ヶ所でまとまります、配列は後日さらに説明したいと思います。
 7~11行:BGで背景を作っています。本当はシーンごとに独自のキャラと背景が必要ですが、容量の関係でとても無理でした。町並みは10行のBGSCALEで大きさを二倍にし、11行で231~245番の建物用のBGをランダムに並べています。
 12~17行:冒頭の説明で、13~16行で文章を書いています。WAKUとHABは後述。
koz03_p1.jpg

★ プログラムの説明3:定義済み処理 ★
 例によって同じ処理が何度も出てくる場合、いちいち個別に書いている面倒なので、ここで定義しています。これは初心者のプログラムの行数が増えてしまう原因の一つで、初心者で1000行をこえてしまうプログラムも、うまくまとめれば、300行以内に収まったりします。3はリストの一番下に入っていますが、プログラムの説明と学習という事で、2より先に3を紹介します。
@YESNO 後述のDEF MENUを使って「はい/いいえ」の二者択一
@MONSTER 怪物遭遇の共通処理
 二ヶ所のどちらから出て全く同じ演出ですが、これは一方で怪物に遭遇した時、同じ場所にまた来たか?と混乱させるためです。実は戦いのルーチンも簡単で、どちらから来ても同じ選択ですぐ勝敗が決まってしまいます。負けたら@END_BADに飛んでいます。本当はGOSUBやFORから、GOTOで外に飛び出すのはルール違反なんですが、このゲームではバッドエンドだとすぐプログラムが終わる(そこでGOSUBやFORに入っているというループ情報が消える)ので、そのまま飛ばしちゃっています。一方ではアイテムがゲットできるが、これは@1112で処理しています。
@KOKOMADE 「この先進めない」のメッセージ表示
DEF WAKU LX1,LY1,LX2,LY2 枠線を描く
 コマンド入力ゲームでおなじみメッセージ枠です。最初は文字キャラの枠線で描いたのですが、複雑になったので、GFILLの青で塗りつぶし、GBOXの白で枠を描きました。このため座標はグラフィック単位でなく文字単位で、またLX2とLY2は右端の座標でなく、枠の横長さと縦高さを指定します。
DEF MCLS 文字とグラフィックの画面クリア
 COLOR命令をいじっていますが、これはそのままCLSをすると、「COLOR #TWHITE,#TBLU
E」すなわち青地に白字で塗りつぶされてしまうので、一度ゼロ(透明色)の背景でCLSしてからCOLORを戻しています。
DEF HELLO LS 住人登場
 LSは会話に現れる住民の姿で、SPSETの0が中央の大きな姿、1が右下の台詞の横に出ます。スプライトキャラ番号は、プチコンに標準装備されている464~1176番から、正面から見た姿を使っています。また32番は以前説明した通り空白なので、LS=32だと何も出ない上、BEEP 40のシュパッという音も出ません。
DEF MES LA,LB,L$ メッセージ表示
 L$に台詞を入れると、徐々に言葉が表示されますが、Bボタンを押していると、徐々なく一気に進みます。またL$の中に"/"(スラッシュ)を入れると文章が改行します。LAが1だと、スペース以外では一文字ごとにBEEPで音を出して喋っているように、0だと無音でト書きのようになります。LBが1だとDEF HABを呼び出す、つまり次の会話や展開に進む前に、ボタンが押されるまで待ちます。余談ですが開発中のプチコンをバージョン3.6.3にアップグレードしていなかったので、ここの実装時のフリーズして焦りました(WAITを入れずにBEEPを繰り返すとフリーズする)。現在のプログラムはバージョン3.6.2でもフリーズせず動くようになっています。
DEF MENU(LN) 選択メニュー
 実は変数の宣言または初使用は、「DEFの外でするとDEFの外でも中でも同じだが、DEFの中で使うとDEFの中だけ有効」という特徴があります。このため選択メニューの項目名に使うDIM Q$[3]だけは、外で宣言しました。LNはその時に表示する項目で、例えばMENU(2)ならQ$[0]とQ$[1]の二つを選ぶメニューを出します。
 236~238行:Q$[]に入っている項目を全て調べ、一番長い文字数をLLに入れています。このLLを使って、DEF WAKUで描く横幅を決めて、項目を出します。今回は選ぶ項目が少ないので、項目は縦一列にしか並びません。
 241~247行:変数LQがプレイヤーの選ぶ結果で、LQが-1になっている限り、このREPEATが続きます。BUTTON()の帰り値をLBに入れ、LBが上か下なら指マーク(カーソル)を上下させ、LAがAボタンなら、その位置の指マークのY座標から、選んだ項目番号を決めます。
 248~251行は指マークをいろんな色で描き、ここを選んだ事を判りやすく表示しています。
 順番が前後しますが、DEFの後ろにカッコがついていますが、これはDEFで処理した変数を、DEFを呼び出した所に「RETURN 変数」を使って返すという処理です。つまりここでは前述のLQを返しています。
@LR 「左に行く」「右に行く」「戻る」のメニュー項目を代入する
DEF GETITEM L$ アイテムを入手のメッセージ表示
DEF HAB ボタンが押されるまで待つ
@BAD_END バッドエンド
 END命令を入れればプログラムは終わりますが、一番後に置いて、END命令がなくても終了にしています。
koz03_p2.jpg

★ プログラムの説明2:各場面での会話処理 ★
 ネタバレの意味もあるので、大切な所だけ解説します。それぞれのシーンは枝分かれという事で、トップを@1、次の分岐は@11と@12、その分岐は@12なら@121と@122…と関連づけています。
@111 若い男の家
 アイテムの入手で、一番変化がある場所です。ここではクリアに必要なアイテム(K$[0])とは別に、QFというミニクエストのフラグを設定しており、0=初対面時/1=クエスト依頼中/2=クエスト達成/3=達成の後の4種類を、IF命令とELSEIF命令を使った「多重分岐命令」で処理しています。
@1122 盗賊風の女性の家
 ここも独自の選択をしているが、一方を選ぶとバッドエンドになります。
@12 老人の家
 特に苦労もせず、重要アイテム(K$[1])をゲットできます。アイテムをゲットすると台詞が変わります。
@121 若い女の家
 @111から続くイベントです。QFが0=@111でクエストも起きてないので進展なし/1=クエスト依頼なのでQFを2にする/2か3=クエスト達成なのでその後のセリフと変わります。
koz03_s3.jpg

@1212 王様の家
 何か月かかってもクリア出来ない本格ADVではないので、グッドエンドは簡単に作りました。KF[0]とKF[1]とKF[2]を三つ掛けてゼロになる、つまりどれか一つでもフラグがまだゼロなら「三つ無いか」、そうでなければ三つとも持っているのでグッドエンドとなります。この時演出として「SPCHR 0,24」で王様の姿を宝石にしてみました。
@122 ジャンケン騎士の家
 ADVの中には理づくめだけでなく、運にたよらないとクリアできないゲームもあるので、ここで入れてみました。DEF MENUでジャンケンをし、勝敗結果で@KATI/@MAKE/@AIKOにそれぞれ飛ばしています。ジャンプ先はもっと簡単にも書けるのですが、わかり易さを考えてこうしました。
koz03_s2.jpg

★ 最後に ★
 B-Magaさんからは、学習しやすいミニゲームをと頼まれているのですが、今回はADVなら簡単だと思ったら、別の意味で単調かつ難しいゲームになってしまったような…私自身、プログラム講座を書くのは初めてで、試行錯誤してやっております。ご勘弁ください(汗)
 実はどれくらい苦労してグッドエンドまで行けるか、検討していないんですが(^^;、完成品で手づまりせず、グッドエンドに行ける事は確認済みです。ぜひ挑戦してみて下さい!
(第四回につづく 次回はまたアクションゲームに戻ります)
★今回の教材プログラムは、サーバにアップしてありますので、サーバからダウンロードしてご覧下さい。
公開キー  :KFDRXT3(連載が進んで新しい教材プログラムが追加されると、公開キーも変わります。この公開キーでダウンロード出来ない場合は、連載の一番新しい回の公開キーをご利用下さい)
プロジェクト:KOZA
ファイル名 :上の教材プログラムの見出しをご覧下さい。
=-=-=-=-=-=-=-=-=-=-
次の更新は、1月24日、『フリーゲームレビュー』の予定です。お楽しみに!

2018年12月17日

プチコンゲームプログラミング講座~第二回「ヘビゲームを作って、スプライトやBGも使ってみよう」

文 プチ太郎 氏
=-=-=-=-=-=-=-=-=-=-
 前回は書いた通り二本紹介予定でしたが、容量ミスで一本になってしまいました。今回はどうしようか、三回書いてこの内容であまり進んでいないのは気が引けたんですが、学習内容としても好みとしても外せないと考えて、二本目を載せます。ただ載せるだけでなく、当初はやはりテキストキャラのみでしたが、スプライトやBGなど多少考えた命令も入れて、自己解析してもらう事で、もう一段レベルの高い学習ができるようにしました。
教材プログラム 2 「ヘビゲーム」(ファイル名「KOZA02」)
KOZ02_S1.jpg

★ ゲームの概要 ★
 商業作品でも「バリケード」「トロン」などの類似作が出ていました。昔から初心者学習用ゲームの模範とされています。その理由は
1.動き続けるキャラがマイキャラしかいないので、プログラムが短く簡単。
2.高級言語の実行速度が遅かった時代にも、動かすキャラが少ないので、ゲームがじゅうぶん高速で楽しめた。
3.動いた後の体が障害物になるので、動いた距離に比例して難易度が高くなる。
4.エサや障害物も配置が単純なので、ゲームバランス調整や、改良してオリジナルゲームを作ることも簡単。
 ゲームの内容は…タイトル画面を見ればわかるので、パス!w

★ プログラムの説明 ★
 前回までは行番号順でしたが、プログラムの行数が長くなり、それだと文章の量も増えてしまうので、今回から処理内容ごとにも説明しています。また前回の説明と同じ部分のプログラム技術は略しています。

★ 初期設定 ★
@プログラムを起動した時、一度だけ設定に使う命令
 1行:GPRIOという命令が出ています。これは文字・グラフィック・スプライト・BGを使う時の、レイヤー(どの表示がどれから優先的に上から出てくるか)の命令で、プチコンの起動時のままでは、グラフィックが下に隠れてでなくなってしまうため、本来より上の位置である"0"に出しています。レイヤーについては後の連載でまた書きます。
 2行:3つの変数に数字を入れています。それぞれ「マイキャラの頭」「マイキャラの胴体としっぽ」「宝箱」のBG番号です。こうしたキャラを変える場合、キャラの番号に関する命令に、そのまま数字(例えば胴体なら「BGPUT…372」や「IF BGGET(…)==372」など)を入れておくと、後からキャラを変える時面倒なので、数字でなく変数にしてあります。
 順番がずれますがBGFILLは、指定した四角い範囲をBGで埋める(埋める=FILL。グラフィックのGFILLも同じ)命令です。パラメータは「BGFILL レイヤー番号,X座標1,Y座標1,X座標2,Y座標2,BG番号」です。これは背景が黒いのではつまらないので、目にやさしい緑の芝(103)で塗ってみましたが、一番下のスコア表示部も同じにすると見にくいので、BGのY座標で言う14行目を、茶色の床(573)で塗ってみました。
 SPSETはスプライトでは必ず最初に使う命令で、「スプライト管理番号の0番を使う。キャラクター番号はとりあえず0番にするよ」という意味。スプライトは必ず、SPSETを宣言しないと使えません。今回は頭に使っているだけで、当たり判定などを使うアクションゲームなどでの使い方は、後日解説しましょう。
@INIT1 ゲームを開始するたびに行う初期設定
 最初の変数はゲームスタート時のデータで、LVは1つまり1面から、BGMはBGM番号で0から始まります。
 今回からいきなりゲームが始まるのでなく、オープニングタイトルを入れてみました。ここではゲームの説明文を6行書いていますが、PRINTでは字が小さいので、ここでの表示専用のDEF SYMBOLを作りました。詳しくはDEF SYMBOLを見て下さい。
 また同時に使っている新命令として、READが登場しています。これは変数に入れたい中身を、DATAの後に書いておけば、「READ 変数」と書くことで、その中身が変数に入るという命令です。文章などのように、不規則なデータの並べ方をコンパクトに収めるのに便利です。読まれるDATAの位置は、プログラムの先頭から順番(この場合「FOR Y=0 TO 5」と繰り返しているので6回)に進みます。しかし一度読むと読み込みの位置は戻らず、READがあってもDATAが無いとエラーになるので、@INIT1を実行するたび、「RESTORE @INIT2」で、読み込み位置を@INIT2の先頭に戻しています。

KOZ02_P1.jpg

@INIT2 面クリアのたびに行う初期設定
・22行:DEF JIでスタートメッセージを出し、36行のDEF JIで消しています。36行で「" "*25」と言う書き方がありますが、これはその文字列をその回数という事で、ここではスペースを25字分、「"ABC"*3」なら「ABCABCABC」という文字列が使えます。
・23行:LV一回分につき5個ぶんの障害物をBG1番に置いていますが、同じBGだとつまらないので、プチコンに入っている、チェスの駒6種類を置いています。次の24行もよく似た記述ですが、こちらはLVと同じ数だけ、TKRつまり宝箱を置いています。それぞれの行で、何が同じで何が違うか、よく考えてみましょう。
・25行:同じ方法で頭を置いていますが、スタートしてすぐ障害物にぶつかると困るので、ちょっと変えています。まずRND関数による座標(変数はAXとAY)の配置を23・24行より小さくして、外周に絶対頭を置かない。次に置こうとする場所をBGGET関数で調べて、既に何か置かれている(BGコードがゼロでない)なら、UNTILでもどしてやり直す。この二点をクリアしたら、SPCOLORで色、SPCHRでスプライトのキャラ番号(ATM)、DEF ATAMAで座標AX,AYの位置に頭を出します。
・27~31行:@LOOPによく似ていますが、RND関数で0から3の乱数を出し、それに応じて、最初に進む方向(変数はVXとVY。Vはベクターつまり方向の意味)を決めています。
・33行:SPANIM命令で、頭のスプライトを規則的に変化させ、チカチカ点滅するようにしています。SPANIM命令はパラメーターがちょっと難しいので、後日また解説します。35行はボタンを押すまでゲームを開始せずに待っています。これはいきなり頭が動き始めると、プレイヤーが慌てている内に、ぶつかってゲームオーバーになるのをふせぐためです。最後に36行で、表示関係を準備中からゲーム中に変え、BGMを鳴らします。

★ メイン処理 ★
@LOOP 基本処理
・39~43行:おなじみ押ボタン処理です。44行では頭のある位置にBGで尻尾を描き、新たな移動先の座標NXとNYを求めて、45行で頭の表示と歩行音を出しています。
・46行:少し長いIF文は、NXとNYがフィールドの外に出たかを判定し、出たらもう@GAMEOVERに飛ばしています。普通ヘビゲームでは、周りに壁を描く事が多いのですが、BGでは25x15マスとヘビゲームにはやや小さく、しかも一番下はスコア表示に使います。このため壁を描かないようにして、少しでもフィールドを大きくしています。もちろん壁があったとしても、ヘビゲームでは大体ゲームオーバーにする事が多いですね。
・47~49行:変数Cに移動先のBGコードを入れ、それが変数TKRだったら@GETへ、ゼロでも32(どちらも、何も描かれていない空白表示で、BGで表示する空白は32を使っています。DEF JIも参照してください)でもなかったら、障害物なので@GAMEOVERへジャンプしています。そのどちらでもなかったら、移動先のNXとNYの座標を、頭の座標AXとAYに代入し、WAIT 16つまり4分の1秒ぐらい待って(ここを変えると、ゲームの速度が変わります)、@LOOPへ戻ります。

KOZ02_S2.jpg

@GET 宝箱の取得、および面クリアしたかの判定
 BEEPの7番は「マリオ」でコインを取ったような音がするので、金や価値のあるものを取った時は、この音色が定番でしょう。58行はレベルの10倍に応じて得点を加え、@SCOREを呼び出しています。32行で代入したLV2は、画面に残っている宝箱の数で、取るたびに1つ引いています。引いた後もまだ1以上あるなら、GOTO @GET_RETで@LOOPの中に戻ります。LV2がゼロなら一面クリア。DEF JIでクリアメッセージを出し、2秒間待って、LVとBGM番号をどちらも1つ足しています。なおBGM番号のうち4~6番はブリッジ(半永久演奏でなく、短く演奏すると終わる)なので、42番以上は存在しないのでエラーになってしまうため、それぞれIF命令で7番と0番に変えています。そして@INIT2にジャンプすれば、面クリア後に必要な処理は、全て@INIT2でやります。

KOZ02_S3.jpg

KOZ02_S4.jpg

@GAMEOVER ゲームオーバー
 前回のスクロールスキーゲームと基本的に同じです。文字表示はPRINTでなく、DEF JIで行っています。67行ではSPCHRで頭のしかめっ面にしています。次のFOR I=1 TO 60…WAITは、60分1秒待ちながらを60回繰り返す、つまり「1秒間に60回処理をする」という事で、その間にRGB関数とRND関数で色のRGBをランダムにしている、つまり顔の色がチカチカと変わって、やられた演出を表現しています。71行では変数SC(今回のスコア)と変数HS(ハイスコア)を比較し、SCの方が大きかったら、HSにSCの内容を代入し、@SCOREを呼び出してスコア表示部を書き換えています。

KOZ02_P3.jpg

★ 定義済み処理 ★
 定義済み処理とは、共通した処理をどこからでも呼び出せる便利な処理で、大別して二種類あります。「GOSUB~RETURN」は古い時代から存在し、プチコンでも初代はこれだけでした。呼び出し元から定義済み処理へジャンプ時、変数を渡したり返したりする機能がなく、個別に「変数=値」を書く必要があります。新しい時代から登場した「DEF~END」は、プチコンでは3号から採用。変数を渡す事ができます。返すにはRETURNとOUTの二種類があるが、今回は渡しだけ使っています。
@SCORE 「DEF JI」を使って、スコアやハイスコアを表示
 注意して欲しいのは、JIでの文字表示用引数は文字列しか使えないので、数値変数はSTR$関数で文字列に変えている事です。例えばA$=STR$(255)と書くと、A$に文字列"255"が入ります。
@CHR12 ゲームに必要な画面を一端クリア
 CLSで文字、GCLSでグラフィック、BGCLRで4つあるBGの1番と3番を消し、DEF ATAMAも実行しています。
DEF SYMBOL L$ GPUTCHRを使って文字列を表示
 オープニング画面で、ゲームの説明を出す時、JIではアルファベットしか出せず、PRINTでは小さいので、GPUTCHRという命令で、文字をグラフィックで出し、また縦横とも2倍の大きさにしています。またどの色でもイマイチ見えにくいので、#WHITEで書く前に、座標を少しずらして#BLACKで書いて、影をつけています。
DEF JI LX,LY,L$ BGを使って文字列を表示
 実はスプライトもBGも、定義番号の32~95番は、文字表示用のアスキーコードの32~95番と同じになっています。このためアルファベットや数字なら、BGで大きい字を出せます。BGレイヤー番号は、一番手前の3番に出しています。またLXに-1を入れておくと、自動的に位置が中央に来るという親切設計にしています。
DEF ATAMA LX,LY スプライトを使って頭を表示
 座標が、グラフィックとスプライトは文字の8倍で400x240、BGは2分の1で25x15です。ここではスプライトによる頭を表示する時、ゲームで使っているBGにあわせた座標を、ススプライト用にあわせるため、引数のLXとLYを16倍して、SPOFSでスプライトを表示しています。頭を隠す時はLXかLYどっちかの座標を、-1とか画面の外に指定すればいい訳です。

KOZ02_P4.jpg

★ 最後に ★
 一つ課題?を。実は何度もゲームをやっていると、宝箱を全部取ったのに、面クリアしないバグが時々あります。どうしてそうなるのか? 改良方法は? 私は気づきましたが、わざと改良しませんでした(直せなかったんぢゃないよ!)これを読んでいて、ある程度プログラミングに自信のある方は、そこを見つけて、改良してみましょう!
(第三回につづく 次回は反射神経を使わず頭脳だけを使う、コマンド入力ゲームの予定です)

★今回の教材プログラムがうまく打ち込めなかった方のために、同じ教材プログラムを、サーバにアップしてあります。必要な方はサーバからダウンロードして、どこが間違っているかなどを、見比べてみて下さい。
 ご多聞にもれず、どんどんリストが長くなっているので、リスト全体を載せる事は、今回が最後になると思います。次回からは別ジャンルのミニゲームを何回か載せていく予定ですが、公開キーで一発ダウンロードのみになると思います。
公開キー  :ED743WAE(連載が進んで新しい教材プログラムが追加されると、公開キーも変わります。この公開キーでダウンロード出来ない場合は、連載の一番新しい回の公開キーをご利用下さい)
プロジェクト:KOZA
ファイル名 :上の教材プログラムの見出しをご覧下さい。
=-=-=-=-=-=-=-=-=-=-
※次の更新は、12月20日。URAURA! GAME REVIEWの予定です。お楽しみに!

2018年11月19日

プチコンゲームプログラミング講座~第一回「すごく簡単なゲームを打ち込んでみよう」

文 プチ太郎 氏
=-=-=-=-=-=-=-=-=-=-
 前回は自己紹介程度だったので、今回からゲームと言えるプログラムを掲載し、それを解説・学習していきます。

 「命令文の入力方法も知らない人向け」から、「テキストエディタぐらいや簡単な命令文は使えるが、命令文を組み合わせてプログラムを完成させるまでは無理」まで、どれくらいの学習度の人を対象にするのか、なかなか迷うところなんですが…このブログの他の講座を見るとだいたい後者ぐらいなので、この連載も後者にあわせます。

 「最低限簡単なプログラムで、最低限何度か遊びたくなるゲームは何だ?」と聞かれたら、いろんな回答が多いかしら? 私は今回ここで、2作品を挙げようと思ったのですが…実は力が入り過ぎて、前回やここのブログの他の内容に比べ、大幅に容量が増えてしまいました(^^;どうしようか悩んだのですが、一回目から量が多いと引かれそうなので、今回は1作品のみとしました。

 色は白黒のみ、使用キャラもスプライトは無しで文字グラフィックだけ、サウンドも最小限です。この辺は次回以降、機会を見てさらに加えた演出を説明予定です。

教材プログラム 1-1 「スクロールスキーゲーム」(ファイル名「KOZA01-1」)

PGP01_1.jpg

★ ゲームの概要 ★

 皆さんはコンピュータに表示される文字が多すぎて、下まで行ききったら、どうなると思いますか? 現代のコンピュータプログラムはそこまでちゃんと考えているので、「絶対文字がはみ出さない」か「画面が上下左右にスクロールする」どっちかだと思います。

 昔のコンピュータ、特にホビーマイコンや高級言語では「ラリーX」や「ドラクエ」のように画面をスクロールさせる事が難しく、スクロールするゲームは、機械語を使わねばなりませんでした。

 ところが文字が下に行ってしまうと、今でも多くのパソコンの機能やアプリは、強制スクロールします。これをうまく使って下にスクロールし続けながら、障害物を避けるゲームというのが、昔から今でも結構存在します。「最低限何度か遊びたくなるゲーム」の中では、もっとも短い行数と言えましょう。

★ ゲームの内容 ★

 一口に一方向スクロールゲームと言っても、障害物を避けるもの、目標物に当てると得点になるもの、両側に壁が出るもの、横に進むものなど、いろいろあります。今回は前述通り、一番簡単に作れる内容でかためました。

1.画面中央の人型が、あなたの操るプレイヤーキャラクターです。十字ボタンで左右に動かして、迫ってくるゲートの中(「アンダーバー」と呼ばれる下線"_"の部分)を通ってください。通ると点数が入ります。
2.10点ごとにスピードが上がります。
3.ゲートの横の四角"■"にぶつかったらゲームオーバーです。Yを押すとまたゲームができますが、Xを押すとプログラムを終了します(Y=Yes、X=バツ、と覚えて下さい)

★ プログラムの説明 ★

PGP01_1B.jpg

 "@"から始まる文字は「ラベル」(Label)と言って、GOTOやGOSUBでジャンプ先、またはデータの読み込み先を指定すると、そのラベルのすぐ下からプログラム実行やデータ読み込みを開始します。言語によっては"*"を使うものもあります。

★2行目
 ACLSは"All CLear Screen"の略で、訳としては「画面要素全削除」となります。プチコンを構成する画面要素のほとんどがリセットされます。スプライトなどもリセットされてしまうので、一般にプログラムの一番最初、および終了して元の一般的な画面に戻る時(このプログラムでは22行目)だけ書きます。だが今回は簡単なゲームなので、リプレイのたびにACLSをしても問題ないので、リプレイ時には一番最初にGOTOしています。

 ACLSの後は、ゲームで使う変数の初期設定です。一般的なゲームの場合、実行後の一回だけ設定、面クリアごとに設定など、設定のタイミングが何種類かありますが、今回は前述通り簡単なゲームなので、全て初期設定だけです。一通り説明しましょう。

 ・X - プレイヤーキャラクターの初期位置。プチコン3号の上画面は50字幅なので、左端が0で右端が49。つまり24は真ん中です。このゲームではキャラの高さがずっと同じなので、縦位置を表す"Y"は使っていません。
 ・S - "Score"のS、つまりプレイヤーが取得したスコア。
 ・S2 - スコアが上がるたびに、レベルアップする基準。
 ・W - ゲーム全体の待ち時間。これもレベルアップすると少なく、つまり速くなります。

★4行目、15行目
 @LOOPは名前通りメインループです。ゲームに何か変化があってGOTOで外に飛び出さない限り、15行目の"GOTO @LOOP"で、また7行目に戻ります。

★5~6行目
 BUTTON()は後ろにカッコが付いていますが、プチコンでは関数は全て、後ろにカッコが付いています。これはDSのボタンが現在押されているかを返す関数で、何も押さないとゼロを返すが、どこかのボタンが何個押すかで、返す数値が変わります。返す数値の中身については、また次回以降に詳しく解説します。

 頭にシャープ(#)を付けた文字は、ツイッターのハッシュタグ…でわなくてwプチコン3号のバージョンアップで追加された「定数リテラル」と言います。定数という通り、一つの名前に必ず同じ数字しか入っていないのですが、名前を見ればどういう存在かわかるので、リストが少し読みやすくなります。「IF BUTTON()==4」より「IF BUTTON()==#LEFT」のほうが、「左」だとわかりますね? つまりこの行は

・5行目「もしボタンが左に押され、かつキャラの座標がゼロ未満であれば、座標変数Xを一歩左に動かせ」
・6行目「もしボタンが右に押され、かつキャラの座標が49を超えないなら、座標変数Xを一歩右に動かせ」

 です。第0回の教材プログラム0-2(ファイル名「KOZA00-2」)とよく似ていますね。

★7~8行目
 LOCATEは文字表示の場所を指定する命令で、ドラマや映画の「ロケ」とい同じ語源です。昔は"CURSOR"と書くBASICもありましたが、マイクロソフトBASICが出てきてからは、ほとんどLOCATEです。

 それから、"?"という記述がありますね。実はこれ、文字を表示するPRINT命令が面倒で、省略して書けるようにしたものです。普通のBASICは"?"と入力しても、PRINTに自動変換されていたのですが、初代プチコンではこれをうっかり忘れてしまい、"?"とPRINTが同じ働きをする別々の命令として存在しています。その"?"で、文字キャラクタの中からキャラクタグラフィックの、「上向き人形」を出しています。これは1978年に発売されたMZ-80K/Cで登場した文字キャラで、使いやすいため、多くのゲームにも使われました。

 BEEPは一番簡単なサウンド「ブッ」を出して、全く音のないゲームの遊びにくさをフォローしています。

 RND関数はRANDOMの略、つまり乱数を返します。現代では「最少はゼロ~最大はカッコ内の数マイナス1」がランダムで出るので、RND(45)は横座標の0~44が出るという事ですね。画面座標は49まであるので、45~49文字目には出さないか?と思いますが、それは"?"で書いている、”■___■”を書く事で、49文字目まで使っています。ここで一番下の29行目に表示する文字列に「改行しない」という意味の”;”(セミコロン。命令文の間の”:”はコロン)を書いていないので、何が何でもここで画面がスクロールします。

 なお四角い"■"はプチコンに二種類あり、わかりにくいのですが、ここでは小さめで隙間の有るほう(キーボードでハートマークを押して、画面上部の”(”のあたり)を入力しています。大きめで隙間の無いほう(画面右下の”.”のあたり)ではありません。8行目と13行目両方で同じ文字を入力すればいいが、それぞれ違うとゲーム進行がおかしくなるので、注意して下さい。

★9行目
 9~12行目は微妙に違う処理を二つ並行しているので、判らない人には判りにくくなるかも知れません(簡単なゲームでも、そうしないとゲームが完成出来ない部分があります!)CHKCHR関数は「カッコ内の座標にある文字の文字コードを返す」、CHR$関数は「カッコ内の文字コードに文字を返す」。これが文字変数"C$"に入ります。本当はCHR$を使わずに「C=CHKCHR(X,10)」のほうが簡単なのですが、そうすると条件判断が「IF C==数字 THEN…」で初心者に読みにくいので、わざとCHR$を挟みました。

★10行目、12行目
 9行目のC$が”_”、つまりゲートだったら、ポイントを通過したという事で、得点の変数Sに一つ追加しています。得点はその時取っても取らなくても、12行目で表示し続けています。これは8行目で強制スクロールするので、ここで再度書かないと、得点が見えなくなるからです。

★11行目、14行目
 「現在の得点Sが次のレベルアップ基準S2に並んだなら」、待ち時間Wを1つ減らし、レベルアップのS2を10増やしています。ただしそのまま続けると、Wがゼロになったら待ち時間が無くなってメチャクチャ速くなり、-1だと文法エラーで止まってしまうので、最初のIFの時に「… AND W>0」も入れて、Wは絶対1以下には減らないようにしています。変数Wによる時間待ちは14行目。待ち時間は原則として一番最後に書きます。

★13行目、17行目~
 9行目とほぼ同じ処理で、C$が”■”、つまり柱だったらゲームオーバー。IF文の後の処理は、そんなに数が多くなかったり(今回はここ以外のIFはみんなそうしている)、ENDIF(今回は使っていない)でまとめられるならそこで書きますが、ここは量が多いのと、その後@LOOPには戻らないので、@GAMEOVERに飛ばしています。

PGP01_1C.jpg

★18行目~19行目
 ここはまた文字表示ですね。

★20行目
 BEEP 108はプチコン3号から追加された、通称「大爆発」で、結構凄い音がします。よく使うBEEP番号として、108は覚えておいて損はないです。

 WAIT 60ですが、1fpsは60分の1秒、つまりちょうど1秒待ちます。これは画面演出をゆっくり見せたいという理由もありますが、WAITを入れておかないと、遊んでいる人がボタンを押したままで、すぐ次の画面に行っちゃって、「え?今どうなったの?」と迷う事があるからです(ミーバースのプチコン3号コミュを読んでいたのですが、初めての人は結構ハマるミスのようでした)

★21行目~
 REPEATとUNTILは、FOR文(今回出てきませんでしたね。詳しくは後日!)やIF文の変形みたいなもので、UNTILの後の条件が「YES」になるまで、繰り返し処理をするというものです。つまり「IF 条件 THEN その後の処理…」と「REPEAT:途中の処理:UNTIL 条件:その後の処理…」は、同じようなものです。

 変数Bで何をやっているかは、もう判りますね。押されたボタンが「#X」ならACLSして、ENDでプログラム終了。「#Y」ならまた@INITからやり直しです。

★ 最後に ★

 次回からは、徐々に複雑にしたいろいろなゲームを挙げて、プログラムのスキルを上げて行きます。また「こんなジャンルのゲームを扱ってほしい!」というリクエストもお待ちしています。ANDとOR、BEEPとBGMPLAYなど、今回簡単な解説で済ませた命令や関数については、後日また解説予定です。

(第二回につづく)

★今回の教材プログラムがうまく打ち込めなかった方のために、同じ教材プログラムを、サーバにアップしてあります。必要な方はサーバからダウンロードして、どこが間違っているかなどを、見比べてみて下さい。

公開キー  :XK2NEDC1(連載が進んで新しい教材プログラムが追加されると、公開キーも変わります。この公開キーでダウンロード出来ない場合は、連載の一番新しい回の公開キーをご利用下さい)
プロジェクト:KOZA
ファイル名 :上の教材プログラムの見出しをご覧下さい。

=-=-=-=-=-=-=-=-=-=-

次の更新は、11月22日。『ゲームむかしがたり『チャンピオンシップ・ロードランナー』』の予定です。お楽しみに!