/×
关于文件版本块的结构定义方法。
×/
struct chunk{
JDWORD type;
JDWORD version;
JDWORD size;
}
通过 type 来识别这个 chunk 的类型,如果是已知的类型就按照其对应的版本号 Version 来读取数据
如果不是则跳过该 chunk 并给出一定的警告信息。
size 保存了这个 chunk 的实际长度,通常情况下不包含自己的长度。
可以通过和实际加载的数据长度进行对比,如果两个值不行等,就说明其版本或者数据存在错误~无法继续加载。
举个例子。
我们有一个结构体。
struct MapInfo{
int width;
int height;
int mapdata[100];
// 下面两个变量是在 2.0 版本之后才会出现的。
int posX;
int posY;
};
现在要把这个结构体按照我们的保存结构进行保存。
首先给这个结构定义一种chunk类型,以确保他在程序中是唯一的标志。
例如。 我们定义
#define MAP_INFO_CHUNK_TYPE 0x1000
#define MAP_INFO_CHUNK_VERSION 0x0010 //表示 1.0
保存函数:
JResult saveMapInfo( JIStream* pStream , const MapInfo* mi ){
chunk c;
c.type = MAP_INFO_CHUNK_TYPE;
c.version = MAP_INFO_CHUNK_VERSION; //根据不同的版本。进行写入。
c.size = 0;
JDWORD cur_pos = pStream->getPos();
pStream->write( c ); //先把数据写入文件缓冲。(占位置)
if( c.version >= 0x0010 ){
c.size += pStream->write( mi->width );
c.size += pStream->write( mi->height );
c.size += pStream->write( mi->mapdata );
}
if( c.version >= 0x0020 ){ //
c.size += pStream->write( mi->posX );
c.size += pStream->write( mi->posY );
}
pStream->setPos( TPOS_SET , cur_pos );
pStream->write( c ); //回写chunk数据。
return JROK;
}
读取函数:
JDWORD loadMapInfo( JIStream* pStream , const MapInfo* mi ){
chunk c;
JDWORD size = 0;
size += pStream->read( &c );
if( c.type != MAP_INFO_CHUNK_TYPE ){
JSetLastErrorEx( "error chunk type!\n" );
return size;
}
if( c.version >= 0x0010 ){
size += pStream->read( mi->width );
size += pStream->read( mi->height );
size += pStream->read( mi->mapdata );
}
if( c.version >= 0x0020 ){ //未来各个版本之间的控制。 向下兼容。
size += pStream->read( mi->posX );
size += pStream->read( mi->posY );
}
//检查数据读取长度是否和chunk中记录的相同!
if( size != c.size ){
JSetLastErrorEx( "data chunk have a error existed!\n" );
return size;
}
return size; //这里应该返回该函数总共在这个过程中读取的字节长度。
//以便以后在多层次的嵌套或者递归式可以很方便的求出下一个chunk的位置。
}
大概就是如此。
另外很多情况下一个chunk中可以包含很多子chunk以实现嵌套
#define SCENE_VERSION_V1 100
#define SCENE_VERSION_V2 200
#define SCENE_VERSION_V3 300
#define SCENE_CURRENT_VERSION SCENE_VERSION_V3
#define HEADER_VERSION_V1 100
#define HEADER_VERSION_V2 200
#define HEADER_VERSION_V3 300
#define HEADER_CURRENT_VERSION HEADER_VERSION_V3
#define GRID_VERSION_V1 100
#define GRID_VERSION_V2 200
#define GRID_VERSION_V3 300
#define GRID_CURRENT_VERSION GRID_VERSION_V3
1JResult GridDisplacement::saveMap( JIStream* pStream )
2{
3#define SAVECHUNK( func ) { \
4 chunk_t chunk; \
5 JIStream::tPos cpos = write_chunk( pStream , chunk ); \
6 chunk.size =(JDWORD)(func); \
7 JIStream::tPos tcurrent = pStream->getPos(); \
8 write_chunk( pStream , chunk , cpos ); \
9 pStream->setPos( tcurrent , JIStream::TPOS_SET ); }
10
11 SAVECHUNK( save_header( &chunk , pStream ) );
12 SAVECHUNK( save_grid( &chunk , pStream ) );
13 SAVECHUNK( save_sector( &chunk , pStream ) );
14
15#undef SAVECHUNCK
16 return JR_OK;
17}
分成三个部分保存,header, grid ,sector,每个都有自己的版本控制,
1size_t GridDisplacement::load_header( chunk_t* pc , JIStream* pStream )
2{
3 size_t size = 0;
4 if( pc->version >= HEADER_VERSION_V1 ){
5 size = pStream->read( name , sizeof( name ) );
6 }
7
8 if( pc->version >= HEADER_VERSION_V1+1 ){
9 size += pStream->read( &player_info.start_point , sizeof( vec3 ) );
10 }
11
12 //if( pc->version >= HEADER_VERSION_V4 ){
13 // size += pStream->read( width );
14 // size += pStream->read( height );
15 //}
16
17 return size;
18}
19
20size_t GridDisplacement::save_header( chunk_t* pc , JIStream* pStream )
21{
22 pc->version = HEADER_CURRENT_VERSION;
23 pc->name = MF_HEADER;
24
25 size_t size = 0;
26 size += pStream->write( name , sizeof(name) );
27 size += pStream->write( &player_info.start_point , sizeof( vec3 ) );
28
29 //if( HEADER_CURRENT_VERSION >= HEADER_VERSION_V3 ){
30 // size += pStream->write( width ); //HEADER_VERSION_V4 added
31 // size += pStream->write( height );
32 //}
33
34 //size += pStream->write( pitch );
35 return size;
36}
37
38size_t GridDisplacement::load_grid( chunk_t* pc , JIStream* pStream )
39{
40 size_t size = 0;
41
42 size += pStream->read( width );
43 size += pStream->read( height );
44 size += pStream->read( pitch );
45
46 if( JROK( generate_maze( width , height ) ) ){
47 r_setLastErrorMsg( "load_grid error ! generate_maze" ) ;
48 return 0;
49 }
50
51 // size += pStream->read( grids , pitch * height );
52
53 return size;
54}
55
56size_t GridDisplacement::save_grid( chunk_t* pc , JIStream* pStream )
57{
58 pc->version = GRID_CURRENT_VERSION;
59 pc->name = MF_GRIDS;
60
61 size_t size = 0;
62 size += pStream->write( width );
63 size += pStream->write( height );
64 size += pStream->write( pitch );
65
66 // size += pStream->write( grids , pitch * height );
67
68 return size;
69}
LoadMap分别加载
JResult GridDisplacement::loadMap( JIStream* pStream )
{
chunk_t chunk;
//JResult result = JR_OK;
const char* lpszErrorPos = NULL;
// while( !pStream->eof() )
{
#define LOADCHUNK( func ) if( chunk.size != (func) ){ lpszErrorPos=#func; goto _END; }
// switch( chunk.name )
// {
// case MF_HEADER:
pStream->read( &chunk , sizeof( chunk_t ) );
LOADCHUNK( load_header( &chunk , pStream ) );
// break;
// case MF_GRIDS:
pStream->read( &chunk , sizeof( chunk_t ) );
LOADCHUNK( load_grid( &chunk , pStream ) );
// break;
// case MF_SECTOR:
pStream->read( &chunk , sizeof( chunk_t ) );
LOADCHUNK( load_sector( &chunk , pStream ) );
// break;
// default:
// JNOTE( "GD_load_map_warning! unknow chunk%x\n" , chunk.name );
// pStream->setPos( chunk.size , JIStream::TPOS_CUR );
// break;
// }
#undef LOADCHUNK
}
_END:
if( lpszErrorPos ){
//JNOTE( "GD_load_map_error! pos:%s <%s>\n" , lpszErrorPos , r_getLastErrorMsg() );
return JR_FAILED;
}
for( int i=0;i<sector_count;i++ ){
Sector* ps = §ors[ i ];
for( int j=0;j<ps->obj_list.count();j++ ){
IObject* pi = ps->obj_list[ j ];
if( pi && pi->getType() == IObject::LIGHT ){
GLight* light = (GLight*)pi;
if( light->light_ptr ){
light->light_ptr->need_update_static_UT = JTRUE;
light->light_ptr->need_update = JTRUE;
}
}
}
}
return JR_OK;
}
posted on 2010-05-20 15:46
风轻云淡 阅读(282)
评论(0) 编辑 收藏 引用 所属分类:
GameDevelop