ゲーム開発28:マップデータ読み込み

今回はマップデータを読み込む処理を、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でメモリを確保し、WidthHeightから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;
}

コメントを残す

メールアドレスが公開されることはありません。