今回はマップデータを読み込む処理を、CMapDataクラスとして作成しました。
Platinumというマップエディタでマップを作ってますが、このツールから書き出す形式にFMFというのがあって、これがベタデータでわかり易かったので、とりあえずこれをそのまま取り込みます。
サンプルプログラムがあったのでそれを参考に、というか多少手を入れた程度のものを作ってみました。
まずFMFのデータ形式ですが、ヘッダ部は以下のようになっています。
typedef struct FMFHeader
{
DWORD Identifier; // ファイル識別子 'FMF_'
DWORD Size; // ヘッダを除いたデータサイズ
DWORD Width; // マップの横幅
DWORD Height; // マップの高さ
BYTE ChipWidth; // マップチップ1つの幅(未使用)
BYTE ChipHeight; // マップチップ1つの高さ(未使用)
BYTE LayerCount; // レイヤーの数
BYTE BitCount; // レイヤデータのビットカウント(未使用)
}FMFHEADER;
これの後ろに実データがレイヤー毎に区切り無く入ってます。なのでヘッダ内のSizeでメモリを確保し、WidthとHeightから1レイヤーのサイズを計算して、任意の場所のデータを読み書きすれば良い感じです。もうサンプルのまんまだけどねw
しかしこのレイヤーという概念は便利で良いですね。1つのデータファイルにマップデータのみならず、キャラクタの配置やイベント発生場所といった物を持たせられます。しかも同一のデータ形式で。
今まではキャラクタの位置情報は別形式で持ってたけど、FMFに一緒に載せてしまおうか。
次回は読み込んだマップデータを表示させます。
//-----------------------------------------------------------------------------
// ファイル読み込み
BOOL CMapData::File(char *filename)
{
HANDLE FP;
DWORD ReadBytes;
// ファイルオープン
FP=CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (FP==INVALID_HANDLE_VALUE) {
return FALSE;
}
// ヘッダ情報取得
if (!ReadFile(FP, &fmfHeader, sizeof(FMFHEADER), &ReadBytes, NULL) || ReadBytes!=sizeof(FMFHEADER)) {
CloseHandle(FP);
return FALSE;
}
// 必要なメモリ確保
LayerAddr= new BYTE[fmfHeader.Size];
if (LayerAddr==NULL) {
CloseHandle(FP);
return FALSE;
}
// レイヤーデータ取得
if (!ReadFile(FP, LayerAddr, fmfHeader.Size, &ReadBytes, NULL) || ReadBytes!=fmfHeader.Size) {
CloseHandle(FP);
return FALSE;
}
CloseHandle(FP);
return TRUE;
}
//-----------------------------------------------------------------------------
// マップ情報取得
int CMapData::Get(BYTE layer_no, BYTE x, BYTE y)
{
int chip_no;
BYTE *Layer;
Layer=LayerAddr+fmfHeader.Width*fmfHeader.Height*layer_no;
chip_no=*(Layer+y*fmfHeader.Width+x);
return chip_no;
}
//-----------------------------------------------------------------------------
// マップ情報上書き
void CMapData::Write(BYTE layer_no, BYTE x, BYTE y, BYTE chip_no)
{
BYTE *Layer;
// 範囲チェック
if (layer_no>=fmfHeader.LayerCount || x>=fmfHeader.Width || y>=fmfHeader.Height) {
return;
}
Layer=LayerAddr+fmfHeader.Width*fmfHeader.Height*layer_no;
*(Layer+y*fmfHeader.Width+x)=chip_no;
}
//-----------------------------------------------------------------------------
// マップの横幅取得
int CMapData::GetWidth()
{
return fmfHeader.Width;
}
//-----------------------------------------------------------------------------
// マップの縦幅取得
int CMapData::GetHeight()
{
return fmfHeader.Height;
}