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定義が出来そうです。
適当に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()は、x,y位置から幅と高さを指定して同じパーツを敷き詰めます。
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_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()は、第二引数の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()は、第二引数の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()は、Map構造体に従ってBG面に書き込みます。Map構造体ですが、実はこれまで、png画像を表示する時に自動的に作られていて、Image構造体のメンバとして含まれているのです。つまり、png画像をリソースとして組み込むと、自動的に8×8のパーツ分けにすると同時に、パーツ番号状の配列まで生成してくれるので、あとはVDPsetMap()を使って表示するだけで済むのですね。
VDP_fillTileData()
VDP_setTileMapDataEx
VDP_setTileMapDataEx
特に、***Ex()系の関数はよくわかりませんでした。VDP_setTileMapData()とVDP_setTileMapDataEx()の違いってなんだろう?