キャラクタ定義と表示方法を調べてみる

1枚絵を表示するライブラリを使うと、png画像を8×8ドットのパーツに分離してパレットを生成してPCG(tile)定義してBG面に並べて表示するところまで簡単にできます。 ただそれだと、小回りがきかないので、自分でPCG(tile)を定義する方法を調べてみます。

■ ライブラリを眺める

vdp_tile.hをみると色々あって、どれがなんだかわからないので簡単そうなものから使ってみます。

PCGの定義に使えそうなのは、VDP_loadTileData()VDP_loadTileSetの2種類があります。 比べてみると、引数が違いますね。

1枚絵を表示した時に使ったVDP_drawImageEx()を改めて確認してみると、第一引数が Image構造体で、TileSet構造体へのポインタがメンバ変数に含まれています。ということは、1枚絵を表示した時のリソースデータを使ってPCG定義が出来そうです。

■ PCG定義してみる

適当に8×8ドットを基準にした16色以内の画像を用意します。今回はこちら。(パレット0番に透明色を指定したpngなので見えにくいですね...)

これを1枚を表示した時と同じ手順でリソース化します。res\fontset.resというファイルを作って、次のような内容を記述します。

IMAGE fontset "FONTSET8.png" -1

たまにリソースファイルをコンパイルしてくれないことがある(resource.hが生成されない)のですが、よくわかりません。ファイルを追加するタイミングみたいのがあるような気がします。

メインプログラムはこんな感じで。PCGの定義場所はVDP_loadTileSet()の第二引数で指定しますが、TILE_USERINDEXにしておくと、SGDKのライブラリを使う時に都合がよさそうです。

#include <genesis.h>
#include "resource.h"

int main()
{
	int	i;

	VDP_setPalette(0, fontset.palette->data);
	VDP_loadTileSet(fontset.tileset, TILE_USERINDEX, TRUE);

	for (i = 0; i < 39; i++) VDP_setTileMapXY(VDP_PLAN_A, TILE_USERINDEX + i, i, 0);

	while(1)
	{
		VDP_waitVSync();
	}
	return (0);
}

■ 他の関数

vdp_tile.hには他にも色々な関数がありますから、適当に使ってみました。 VDP_setTileMapXY()は指定位置にパーツを書き込む命令で以前も使いましたね。

VDP_fillTileMapRect()

VDP_fillTileMapRect()は、x,y位置から幅と高さを指定して同じパーツを敷き詰めます。

VDP_fillTileMap()

VDP_fillTileMap()<\a>は、TILE_ATTR_FULL()マクロで指定したパーツをBG面の指定位置(index)からnum個並べます。indexというのはBG面の左上端を0とした指定方法のようです。引数がindex(ind)となっている関数は全てBG面を一次元配列(相対アドレス)とした指定方法みたいですね。

使用例) VDP_fillTileMap(VDP_PLAN_A, TILE_ATTR_FULL(PAL0, 1, 0, 0, TILE_USERINDEX+3), 10, 5);

VDP_fillTileMapInc()

VDP_fillTileMapInc()は、VDP_fillTileMap()同様に、TILE_ATTR_FULL()マクロで指定したパーツをBG面の指定位置(index)からnum個並べますが、パーツを一つ置く毎にパーツ番号を+1するようです・・・が、なぜかうまく動きません。マクロでの指定方法が違うのかな?

使用例)VDP_fillTileMapInc(VDP_PLAN_A, TILE_ATTR_FULL(PAL0, 1, 0, 0, TILE_USERINDEX+1), 0, 39);

VDP_setTileMapData

VDP_setTileMapData()は、第二引数のPCGアトリビュート定義の配列をVRAMに連続して書き込む関数です。

#include <genesis.h>
#include "resource.h"

int main()
{
	int	i;
	u16	str[16];
	char	scoreStr[16] = "SCORE 1000000000";

	for (i = 0; i < 16; i++) {
		str[i] = TILE_ATTR_FULL(PAL0, 1, 0, 0, TILE_USERINDEX+scoreStr[i]-0x20);
	}

	VDP_setPalette(0, fontset.palette->data);
	VDP_loadTileSet(fontset.tileset, TILE_USERINDEX, TRUE);
	VDP_setTileMapData(VDP_PLAN_A, str, 0, sizeof(str) / sizeof(u16), TRUE);

	while(1)
	{
		VDP_waitVSync();
	}
	return (0);
}

VDP_setTileMapDataRect

VDP_setTileMapDataRect()は、第二引数のPCGアトリビュート定義の配列をVRAMに矩形で書き込む関数です。ドット絵ツールとマップエディタがあれば、この関数で一発表示できそうです。

	u16	str[16];

	VDP_setPalette(0, fontset.palette->data);
	VDP_loadTileSet(fontset.tileset, TILE_USERINDEX, TRUE);
	for (i = 0; i < sizeof(str) / sizeof(u16); i++) str[i] = TILE_ATTR_FULL(PAL0, 1, 0, 0, TILE_USERINDEX+i);
	VDP_setTileMapDataRect(VDP_PLAN_A, str, 10, 10, 4, 4);

VDP_setMap()

VDP_setMap()は、Map構造体に従ってBG面に書き込みます。Map構造体ですが、実はこれまで、png画像を表示する時に自動的に作られていて、Image構造体のメンバとして含まれているのです。つまり、png画像をリソースとして組み込むと、自動的に8×8のパーツ分けにすると同時に、パーツ番号状の配列まで生成してくれるので、あとはVDPsetMap()を使って表示するだけで済むのですね。

■ 使い方のわからなかったもの

VDP_fillTileData()

VDP_setTileMapDataEx

VDP_setTileMapDataEx

特に、***Ex()系の関数はよくわかりませんでした。VDP_setTileMapData()とVDP_setTileMapDataEx()の違いってなんだろう?


上のページに戻る