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』の予定です。お楽しみに!