ゲームマップをバイナリ形式でファイルに保存しています。ファイルの一般的な構造は次のとおりです。
- (4byte) 幅
- (4byte) 高さ
- 幅高さ:
- (1byte) タイル
- 幅高さ:
- (4byte) データ
ファイルのサイズを小さくするために、読みたい数値の正確なサイズがわかっているので、すべてを文字で保存することにしました。getByte と makeInt の 2 つの関数を作成しました。
unsigned char getByte(int src, short int c) //get byte number c from src
{
return ((char*)(&src))[c];
}
int makeInt(char src[4]) //build int from src
{
int r=0;
for (int i=3; i>=0; i--)
r+=(r<<8)+((unsigned char*)(src))[i];
return r;
}
マップを保存してロードする方法は次のとおりです。
void Map::save(const char *fname)
{
ofstream f;
f.open(fname,fstream::out | fstream::binary);
for (int i=3; i>=0; i--)
f.put(getByte(W,i));
for (int i=3; i>=0; i--)
f.put(getByte(H,i));
for (int i=0; i<W; i++)
for (int j=0; j<H; j++)
f.put(tiles[i][j]);
for (int i=0; i<W; i++)
for (int j=0; j<H; j++)
for (int k=3; k>=0; k--)
f.put(getByte(data[i][j],k));
f.close();
}
void Map::load(const char *fname)
{
ifstream f;
f.open(fname,fstream::in | fstream::binary);
char bytes[4];
for (int i=3; i>=0; i--)
f.get(bytes[i]);
W=makeInt(bytes);
for (int i=3; i>=0; i--)
f.get(bytes[i]);
H=makeInt(bytes);
for (int i=0; i<W; i++)
for (int j=0; j<H; j++)
f.get(tiles[i][j]);
for (int i=0; i<W; i++)
for (int j=0; j<H; j++)
{
for (int k=3; k>=0; k--)
f.get(bytes[k]);
data[i][j]=makeInt(bytes);
}
f.close();
}
タイル (char) は適切に保存およびロードされ、すべて問題ありません。しかし、int はそうではありません。奇妙なバグのため、256 を保存すると 257 が読み込まれます。予想される 512 の代わりに、514 が読み込まれます。汚い方法 (r-=r/256) にしたくありません...兆候、そしてそれがおそらくこれがすべて起こる理由です。符号なしキャストを追加する前は、127 の後は -127、-126、-125 などでした。これが役立つ場合、マップクラスは次のとおりです。
class Map
{
public:
int W;
int H;
char tiles[MW][MH]; //MW and MH are macros, now they are 64.
int data[MW][MH];
void save(const char *fname);
void load(const char *fname);
/* moar code */
};
このパターンでマップを生成してテストしました:
for (int i=0; i<64; i++)
for (int j=0; j<64; j++)
map.data[i][j]=(i*64+j);