在C ++中创建自定义文件类型

时间:2013-05-21 22:55:17

标签: c++ bmp file-type

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

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

感谢。

1 个答案:

答案 0 :(得分:2)

首先你需要设计你的文件层,你需要固定大小的数据来确定如何解码你的可变数据,例如,你读的前四个字节可以告诉你有多少个瓷砖,接下来的4个字节可以说明如何有许多映射文件,之后你有第一个文件,你必须定义你的文件信息,例如哪个文件和它有多少字节,然后你知道你离下一个文件条目有多少字节,等...

您还可以使用结构并重载流运算符<<和>>为了创建自己的文件类型I did this myself when creating a replay system for Need For Speed Underground 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;
}