/****************************************************************/
/* Virtual Screen */
/****************************************************************/
#include "gba.h"
#include "back.h"
#include "back.c"
void init_screen(void);
void wait(int);
|
back.h は、背景画像のマップデータです。back.c は、背景画像のタイルデータとパレットデータです。これらの作り方は、ページの最後のほうに記載してあります。
|
hword* bcolor = (hword*) BG_PALETTE;
// Screen definition
screen plane[ 1 ] = {
{ (hword*) VRAM_MAP(16), (hword*) VRAM_TILE(0), 0, 0 } // Page 0
};
|
背景パレットの先頭アドレス 0x05000000は、2 Byte 配列 bcolor にポインタとして設定されています。screen は、gba.h の中で、定義された構造体(マップデータ、タイルデータ、x座標、y座標)です。この構造体は、複数画面制御を簡単に行うために定義されたものですが、この例では、背景画像1枚しか使用しませんので、配列要素は1個だけになっています。スカラーとして定義することもできます。
|
int main() {
int key, xoff = 0, yoff = 0; // Key status, x-offset, y-offset
|
キー入力状態を代入する変数 key, 仮想画面上のLCD画面の左上座標(オフセット)を記憶するための変数、(xoff, yoff) を宣言します。
|
// Initialize screen
init_screen();
|
init_screen() は、背景の設定を行います。ページの後ろのほうを参照。
|
// Key scan loop
while (1) {
key = gba_reg(KEY_STA);
if ((key & KEY_ALL) == KEY_ALL)
continue;
key = key ^ KEY_ALL;
|
キーステータスレジスタから、key 変数にキー入力状態を取得し、key & KEY_ALL(全キー入力ビットマスク) により、キー入力を確認。キー入力が無ければ、ループ先頭に戻り、キー入力があれば、KEY_ALL との EXOR によりビット反転を行う。詳しくは、キー入力と複数画面合成のページを参照。
|
if (key & KEY_UP) {
if (yoff == 0)
continue;
yoff--;
gba_reg(BG0_VOFFSET) = yoff;
}
else if (key & KEY_DOWN) {
if (yoff == (256 - (20 * 8)))
continue;
yoff++;
gba_reg(BG0_VOFFSET) = yoff;
}
else if (key & KEY_RIGHT) {
if (xoff == (256 - (30 * 8)))
continue;
xoff++;
gba_reg(BG0_HOFFSET) = xoff;
}
else if (key & KEY_LEFT) {
if (xoff == 0)
continue;
xoff--;
gba_reg(BG0_HOFFSET) = xoff;
}
|
4方向各々のカーソルキーのビットマスク KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_LEFT により、どの方向のキーが押されているか判定し、それに応じて、(xoff, yoff) をインクリメントまたはデクリメントする。但し、LCDが仮想画面の端に来ている場合に、さらにLCD座標を変更すると仮想画面からはみ出てしまうので、LCD表示領域が、仮想画面の端に来ていないか調べて、端まで来ていたら、ループ先頭に戻っています。仮想画面の大きさは、32x32タイル(背景コントロールレジスタポインタLCD_SIZE00で指定)に相当します。タイルは、8x8 pix なので、仮想画面サイズは、256x256 pix となります。LCD のサイズは、
30x20 タイルです。上のLCD表示領域の判定条件を、よく確認してください。また、仮想画面からはみ出すとどうなるか試してみてください。オフセットは、pix 単位で指定できますので、スムーズなスクロールが可能です。
|
wait(80);
};
}
|
スクロール速度調節用の、時間調整用ループ。
|
void init_screen(void) {
int i;
// Initialize palette
for (i = 0; i < 256; i++)
bcolor[ i ] = back_pal[ i ];
// Setup tiles for background
for (i = 0; i < 8 * 2 * 32; i++)
plane[ 0 ].tile[ i ] = back_data[ 2 * i ] + (back_data[ 2 * i + 1] << 8);
// Setup the map for background
for (i = 0; i < 32 * 32; i++)
plane[ 0 ].map[ i ] = back[ i ];
|
背景用パレット、タイルデータ、マップデータを、screen 構造体を用いて、パレットおよびVRAMに書き込んでいる。
|
// Start LCD display
gba_reg(BG0_CTL) = LCD_SIZE00 |
LCD_COLOR256 |
LCD_BGTILE(0) |
LCD_BGMAP(16);
gba_reg(LCD_CTL) = LCD_BG0 |
LCD_MODE0;
}
|
背景コントロールレジスタに、サイズ32x32タイル、パレット色数256色、タイル領域0番、マップ領域16番を設定。背景は、BG0番を使用。背景データの使用メモリアドレスマップは、自分で確認してみてください。
|
void wait(int time) {
int i, j;
for (i = 0; i < time; i++)
for (j = 0; j < time; j++) ;
}
|
スクロール速度調節用の、時間調整用ループ。
|
const unsigned char back_data[8*2*64] = {
0x15,0x33,0x13,0x36,0x36,0x36,0x47,0x36,
0x15,0x36,0x33,0x36,0x36,0x2C,0x33,0x36,
:
:
};
const unsigned short back_pal[256] = {
0x0000,0x0842,0x1084,0x18C6,0x18C6,0x294A,0x318C,0x318C,
0x39CE,0x4631,0x4E73,0x4E73,0x56B5,0x5EF7,0x6739,0x6739,
:
:
};
|
全面を一枚の画像をタイルに分割して背景にする方法を、キー入力と複数画面合成のページで説明しました。この場合には、マップは、bmp2rgb2 が自動的に作成したものをそのまま使用しました。ゲームでは、少数のタイルを組み合わせて、所謂、ダンジョンマップを作成することがよくあります。まず、下のようなタイルパターンを用意します。GBAのタイルの単位は、8x8pixですので、8の倍数の長さのタイルパターンが必要です。この例では、16x16pixのものを4種類用意しました。これらのタイルパターンをフォトレタッチやお絵かきツールで結合します。縦長でも横長でもOKです。色は256色にして、Windows BMP 形式で保存します。これを、bmp2rgbで、GBAのRGB形式に変換します。*.c ファイルに、パレット、タイル、マップのデータが保存されていますが、パレットとタイルデータのみ使用します。このツールの出力するタイルデータは、8 bit 単位の配列になっているので、16 bit 幅のVRAMに読み込むときには、注意が必要です。
|
const unsigned short back[] = {
6,7,6,7,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
:
:
};
|
マップは、自力でこつこつ作成してもよいのですが、やはり画面をみながらでないと、かっこいいマップはできません。ここでは、WideMapEditorというツールを使用しました。上で作成した、タイルパターンの Windows BMP 画像を読み込み、マウスでクリックしていくと、マップ画像が出来上がっていきます。8x8 タイルや 16x16 タイル単位でも操作することが出来て大変便利なツールです。完成したら、GBA用ファイルを出力します。*.h を上書きするか聞いてきますが、上書きでOKです。
|