1

我正在制作一个需要输出自定义地图文件的关卡编辑器,以便与我将为图形库编写的源代码一起使用。

我的问题是:在决定如何构建自定义文件类型时,我需要牢记什么?另外,我如何将标准位图图像编码到我的文件(图块集)中,以便它可以全部包含在单个文件而不是两个文件中;地图文件和图块集(.bmp 文件)。

谢谢。

4

1 回答 1

3

首先你需要设计你的文件层,你需要固定大小的数据来确定如何解码你的可变数据,例如,你读取的前四个字节可以告诉你有多少瓦片,接下来的 4 个字节可以告诉你有多少地图文件还有,在你拥有第一个文件之后,你必须定义你的文件信息,例如哪个文件和它有多少字节,然后你知道你离下一个文件条目还有多少字节等等。 .

您还可以使用结构并重载 ofstream 运算符 << 和 >> 来创建自己的文件类型,我在为《极品飞车 2》创建重播系统时自己这样做了

struct Point4D { float x, y, z, w; };
struct Point3D { float x, y, z; };
struct Point2D { float x, y; };


struct QuatRot
{
    Point4D Front;//frontvector
    Point4D Right;//rightvector
    Point4D Up;//upvector
};

#define NFS_MAX_VEHICLES (14)//seriously just 14.. (including the player)


struct VehicleInfo
{
    //type      name                                    array   offset
    float       unknown_01                              [8];    //0x0
    Point3D     Pos;                                            //0x20
    float       unknown_02;                                     //0x2C
    QuatRot     Rotation;                                       //0x30
    Point3D     unknown_03;                                     //0x60
    float       unknown_04;                                     //0x6C
    Point3D     Velocity;                                       //0x70
    float       unknown_05;                                     //0x7C
    Point3D     TurnSpeed;                                      //0x80
    float       unknown_06;                                     //0x8C
    float       SpeedAndBrakeAccelerator;                       //0x90
    float       unknown_07                              [3];    //0x94
    Point3D     unknown_08;                                     //0xA0
    float       unknown_09;                                     //0xAC
    Point4D     unknown_10                              [5];    //0xB0
    float       unknown_11                              [20];   //0x100
    float       unknown_12_is_zero_when_accelerating;           //0x150
    //end of structure...?
};

std::ostream& operator<<(std::ostream& stream, const VehicleInfo &info);
//overload << and >> operators on "VehicleInfo" type
std::ofstream& operator<<(std::ofstream& stream, VehicleInfo &info);
std::ifstream& operator>>(std::ifstream& stream, VehicleInfo &info);
//overload << and >> operators on "FrameInfo" type
std::ofstream& operator<<(std::ofstream& stream, Recorder::FrameInfo &info);
std::ifstream& operator>>(std::ifstream& stream, Recorder::FrameInfo &info);

namespace Recorder
{
    struct FrameInfo//1392 bytes / frame | max 167040 bytes @ 120 fps | 9.56 MB / min max
    {
        std::chrono::high_resolution_clock::duration time;
        VehicleInfo Vehicle;
        int Nitro;
        float RPM;
        float TURBO;
        int CurrentGear;
        KeyManager Keys[256];
    };
};

std::ofstream& operator<<(std::ofstream& stream, VehicleInfo &info)
{
    stream.write(reinterpret_cast<char*>(&info.unknown_01[0]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_01[1]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_01[2]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_01[3]), sizeof(float));
        //...
    stream.write(reinterpret_cast<char*>(&info.unknown_11[18]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_11[19]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_11[20]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_12_is_zero_when_accelerating), sizeof(float));
    return stream;
}

std::ifstream& operator>>(std::ifstream& stream, VehicleInfo &info)
{
    stream.read(reinterpret_cast<char*>(&info.unknown_01[0]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_01[1]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_01[2]), sizeof(float));
            //.....
    stream.read(reinterpret_cast<char*>(&info.unknown_11[16]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_11[17]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_11[18]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_11[19]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_11[20]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_12_is_zero_when_accelerating), sizeof(float));
    return stream;
}

std::ofstream& operator<<(std::ofstream& stream, Recorder::FrameInfo &info)
{
    stream.write(reinterpret_cast<char*>(&info.time), sizeof(std::chrono::high_resolution_clock::duration));
    stream << info.Vehicle;
    stream.write(reinterpret_cast<char*>(&info.Nitro), sizeof(int));
    stream.write(reinterpret_cast<char*>(&info.RPM), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.CurrentGear), sizeof(int));
    stream.write(reinterpret_cast<char*>(&info.TURBO), sizeof(int));
    for(int i = 0; i < 256; ++i)
    {
        stream.write(reinterpret_cast<char*>(&info.Keys[i].Pressed), sizeof(bool));
        stream.write(reinterpret_cast<char*>(&info.Keys[i].Released), sizeof(bool));
        stream.write(reinterpret_cast<char*>(&info.Keys[i].Down), sizeof(bool));
        stream.write(reinterpret_cast<char*>(&info.Keys[i].Up), sizeof(bool));
    }
    return stream;
}

std::ifstream& operator>>(std::ifstream& stream, Recorder::FrameInfo &info)
{
    stream.read(reinterpret_cast<char*>(&info.time), sizeof(std::chrono::high_resolution_clock::duration));
    stream >> info.Vehicle;
    stream.read(reinterpret_cast<char*>(&info.Nitro), sizeof(int));
    stream.read(reinterpret_cast<char*>(&info.RPM), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.CurrentGear), sizeof(int));
    stream.read(reinterpret_cast<char*>(&info.TURBO), sizeof(int));
    for(int i = 0; i < 256; ++i)
    {
        stream.read(reinterpret_cast<char*>(&info.Keys[i].Pressed), sizeof(bool));
        stream.read(reinterpret_cast<char*>(&info.Keys[i].Released), sizeof(bool));
        stream.read(reinterpret_cast<char*>(&info.Keys[i].Down), sizeof(bool));
        stream.read(reinterpret_cast<char*>(&info.Keys[i].Up), sizeof(bool));
    }
    return stream;
}

///

std::stringstream& operator<<(std::stringstream& stream, VehicleInfo &info)
{
    stream.write(reinterpret_cast<char*>(&info.unknown_01[0]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_01[1]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_01[2]), sizeof(float));
            //...
    stream.write(reinterpret_cast<char*>(&info.unknown_11[19]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_11[20]), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.unknown_12_is_zero_when_accelerating), sizeof(float));
    return stream;
}

std::stringstream& operator>>(std::stringstream& stream, VehicleInfo &info)
{
    stream.read(reinterpret_cast<char*>(&info.unknown_01[0]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_01[1]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_01[2]), sizeof(float));
            //....
    stream.read(reinterpret_cast<char*>(&info.unknown_11[20]), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.unknown_12_is_zero_when_accelerating), sizeof(float));
    return stream;
}

std::stringstream& operator<<(std::stringstream& stream, Recorder::FrameInfo &info)
{
    stream.write(reinterpret_cast<char*>(&info.time), sizeof(std::chrono::high_resolution_clock::duration));
    stream << info.Vehicle;
    stream.write(reinterpret_cast<char*>(&info.Nitro), sizeof(int));
    stream.write(reinterpret_cast<char*>(&info.RPM), sizeof(float));
    stream.write(reinterpret_cast<char*>(&info.CurrentGear), sizeof(int));
    stream.write(reinterpret_cast<char*>(&info.TURBO), sizeof(int));
    for(int i = 0; i < 256; ++i)
    {
        stream.write(reinterpret_cast<char*>(&info.Keys[i].Pressed), sizeof(bool));
        stream.write(reinterpret_cast<char*>(&info.Keys[i].Released), sizeof(bool));
        stream.write(reinterpret_cast<char*>(&info.Keys[i].Down), sizeof(bool));
        stream.write(reinterpret_cast<char*>(&info.Keys[i].Up), sizeof(bool));
    }
    return stream;
}

std::stringstream& operator>>(std::stringstream& stream, Recorder::FrameInfo &info)
{
    stream.read(reinterpret_cast<char*>(&info.time), sizeof(std::chrono::high_resolution_clock::duration));
    stream >> info.Vehicle;
    stream.read(reinterpret_cast<char*>(&info.Nitro), sizeof(int));
    stream.read(reinterpret_cast<char*>(&info.RPM), sizeof(float));
    stream.read(reinterpret_cast<char*>(&info.CurrentGear), sizeof(int));
    stream.read(reinterpret_cast<char*>(&info.TURBO), sizeof(int));
    for(int i = 0; i < 256; ++i)
    {
        stream.read(reinterpret_cast<char*>(&info.Keys[i].Pressed), sizeof(bool));
        stream.read(reinterpret_cast<char*>(&info.Keys[i].Released), sizeof(bool));
        stream.read(reinterpret_cast<char*>(&info.Keys[i].Down), sizeof(bool));
        stream.read(reinterpret_cast<char*>(&info.Keys[i].Up), sizeof(bool));
    }
    return stream;
}
于 2013-05-22T01:21:47.230 回答