機械学習周りのプログラミング中心。 イベント情報
ポケモンバトルAI本電子書籍通販中

ゲームボーイ上で強化学習を行う part4

前回、Q学習のアルゴリズムゲームボーイ向けビルドしました。今回は、学習した車の動きを画面に表示するための実装を進めます。

実装

ゲームボーイのグラフィックシステム

ゲームボーイの画面は幅160px、高さ144pxの液晶です。色はモノクロで、白、明るい灰色、暗い灰色、黒の4階調を表現できます。ゲームボーイのグラフィックシステムは、「背景」「ウインドウ」「スプライト」を重ね合わせて表示します。背景は、8×8の画像(タイル)を画面全体に敷き詰めて表示します。座標(0,0), (0,8), (0,16), ..., (8,0), ...について、あらかじめ登録したタイルのうち何番のものを表示するのかを指定します。ウインドウは、画面の一部の長方形領域にタイルを敷き詰めて表示します。本プロジェクトでは使用しません。スプライトは、8×8のタイルを1px単位で画面上の任意の位置に表示することができます。スプライトごとに、何番のタイルをどの座標に表示するかを指定します。今回はごくシンプルな機能のみを使用しますが、背景のスクロールなどの機能を利用し多彩な表現が可能になっています。

画面の構成とアセットの作成

ゲームボーイのグラフィックシステム上でMountainCarを表現していきます。

画面の完成形

コースは動かないので背景で、1px単位で動かしたい車はスプライトで表示します。画面下部の文字は、printfの機能により独自のグラフィックデータを用意することなく表示していますが背景の一部です。コースの画像は、まず160×144サイズのPNG形式の画像を作成し、それをPic2TilesというツールでC言語ソースコードに変換します。画像は、Pythonで地面となるサインカーブを描き、Photoshopでゴールの旗を描き込みました。Pic2TilesにPNG画像を読み込ませ、"C (gbdk)"形式で出力を行います。

Pic2Tilesの画面

bg.cには、タイルごとの8×8の画像がゲームボーイ用の形式で格納されます。1つのタイルは、1ピクセル当たり2ビット(4色)ですので16バイトの容量を占めます。画面全体では横20個、縦18個のタイルを表示できますので最大で360種類のタイルが定義されることになりますが、今回用意した背景は真っ白のタイルが何度も出てきますので、これに対応するタイルは1回だけ定義され、45種類のタイルで背景が表現されています。

const unsigned char TileData[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x07,0x02,0x05,0x03,0x04,0x03,0x04,0x03,0x04,0x03,0x04,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x60,0xC0,0x38,0xF0,0x0C,0xF0,0x0C,
0x03,0x04,0x03,0x04,0x02,0x05,0x00,0x06,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x0F,
0xC0,0x38,0x00,0xE0,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,
// 省略: 合計45タイル

bg_map.cには、画面上の各領域にどのタイルを表示するかを指示する定数が格納されます。タイル1個は1バイトで表現されています。真っ白の領域はタイル0x00が割り当てられ、それ以外の領域は個別のタイル番号が割り振られていますので、ソースコード上におおまかなコースの形が現れています。

const unsigned char MapData[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x04,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x06,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x0B,0x00,0x00,0x00,
0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x0E,0x00,0x00,0x00,0x00,
0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
0x11,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x14,0x00,0x00,0x00,0x00,0x00,
0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x17,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x1A,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x1D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x20,0x21,0x00,0x00,0x00,0x00,0x00,0x22,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x24,0x1B,0x00,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x26,0x27,0x00,0x0D,0x28,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x2A,0x2B,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

車のスプライトは、GBTD (Gameboy Tile Designer)を用いて作成します。ゲームボーイに特化したツールで、4階調のドット絵を作成することができます。

GBTDを用いたスプライトの作成

GBDK用のC言語ソースコードを出力すると、以下のようになります。

const unsigned char SpriteLabel[] =
{
  0x00,0x00,0x00,0x00,0x3C,0x3C,0x7E,0x78,
  0xFF,0xFF,0x99,0xFF,0x00,0x66,0x00,0x00
};

次回は、用意したアセットを画面上に表示する実装を行います。