网页功能: 加入收藏 设为首页 网站搜索  
Tile文件的组织
发表日期:2006-08-23作者:[转贴] 出处:  

  斜视角Tile游戏中,Tile是组成地图的最基本的东西,整个地表(不包括上面的建筑)都是由Tile拼出来的。每个Tile就是个小图片,描述了这个地表(象地板、街道、草地、溪流等等)的样子。依照(我的)习惯,同类文件就组织在一起打成一个包,下面就给出一个Tile文件的结构。

  我们先来讨论一下Tile图片的颜色数,在以前我曾经说过,对256色模式我有一种怪异的癖好,而且我也讲过一些256色的好处,很多Tile肯定都可以用相同的调色板(象不同形状的草地等等),而且这些调色板也可以给那些物体用(节省空间是我们的目的),另外说实话,每个Tile根本不见得有256个有意义的像素,因此在这里,每个Tile仍然用256色就足够了。但是256色就有个调色板的问题,这个在后面具体讨论数据结构的时候再解决。

  每个Tile图片都有很大的压缩余地,毕竟同一种地表肯定有很多相邻颜色是相同的,而且菱形的四周都是透明色,肯定是要压缩的。压缩方法就采用《DIABLO中的图像压缩方法》中提及的Diablo所采用的RLE压缩方法(简单、效果也不差)。由于采用了压缩方法之后,这些Tile的大小就变得大小不等了。为了快速在文件中定位每个Tile,我们需要建立一个索引文件(可以叫xxx.inx),整个文件就是个数组,记录着每个Tile在Tile文件中的位置及一些必要信息,具体数据结构稍候讨论。这样,就可以根据Tile的ID号(实际就是Tile在整个它所处的Tile文件中的索引号)快速在Tile文件中查找到所需要的Tile。当然,也可以把这个索引放到Tile文件的里面(头上或尾部),这样看起来显得更紧凑一些。

好了,现在该说到具体的数据结构了。

typedef struct {
  int  Version;
  int  nTileWidth, nTileHeight;
  int  nTileNumber;
  int  Compress;
  char TileFileDesc[44];
} TILEFILEHEADER;

这是个64字节的Tile文件头的结构。Version是描述一下这个Tile文件的版本,以备后来的Tile引擎以及地图编辑器识别的,如果日后再定义了一些新的Tile格式,只要把这个版本号改一下,通知Tile引擎或地图编辑器就行了;nWidth,nHeight两个成员是说明每个Tile的长和宽的,因为每个Tile都是等大的(不然怎么拼起来?),所以在前面定义一次就够了;nTileNumber是记录在这个文件中总共有多少个Tile,如果索引在这个Tile文件中的话,那么这个成员就很有用了;Compress是说明Tile数据是用什么方法压缩的(模仿BITMAPINFO里的结构搞了这么个东西),以备扩展;TileFileDesc是这个Tile文件的描述,给地图编辑器用的,提供给编辑者一个对这个Tile文件的初步印象。

文件头后面就是一个Tile索引表(还是按我的习惯,把东西都放到一起,看起来整洁一点)。索引表实际就是个如下的结构数组:

typedef struct {
  int  nTilePos;
  int  nFrameNumber;
  char TileDesc[24];
} TILEINDEX;

nTilePos是最重要的成员,它记录着这个Tile在文件中的位置(相对于文件头的偏移,用SetFilePointer函数可以很容易的定位Tile);nFrameNumber是用来记录这个Tile的帧数,当这个值为1时,代表这个Tile只有一幅图片,也就是个静止的Tile,当值大于1时,这个成员就指定了这个Tile的帧数,也就是说这是个动态的Tile(比如说,随风摆动的草地、起伏的水面等等);TileDesc这个东西又是给编辑器看的,描述了这个Tile的名字,说明这是个什么样的地表形状,有了这么个成员,我们就可以在编辑Tile的时候直接读取每个Tile相关的信息,以选择所需要的Tile,而不用扫描整个文件了。

索引表的后面就是具体的Tile数据了,每个静态的Tile数据都有一个自己的8个字节的数据头。

typedef struct {
  int  nPaletteNumber;
  int  nTileSize;
} STATICTILEHEADER;

nPaletteNumber是用来记录当前这个Tile图片是使用哪个调色板,Tile图片数据的每个像素的值实际就是在这个调色板里的索引,实际的颜色值是记录在这个调色板里的;nTileSize是给出这个Tile的被压缩后的图片数据大小,也就是在文件中真正占据空间的大小,这个是为了读Tile到内存时和解压缩时的方便。每个Tile Header后面就是具体的压缩过的图片数据了。

对于动态的Tile来说,这个数据头稍稍有点变化。

typedef struct {
  int  nPaletteNumber;
  int  nTileSize;
  int  nFramePos[1];
} DYNAMICTILEHEADER;

这里的nTileSize是指所有帧的压缩图片大小的总和;nFramePos是个数组,记录着每一帧的数据相对于第一帧开头数据的偏移,对于每一帧的图片都是分别压缩的,举个例子:一个动态的Tile总共有5帧图像,每帧图像压缩后的大小分别是10、20、25、16、15,那么nFramePos[0] = 0,nFramePos[1] = 10,nFramePos[2] = 30,nFramePos[3] = 55,nFramePos[0] = 71,就是这样。这样把Tile读入内存时可以完全不用做任何改动,很方便的就可以迅速定位到任何一帧数据的开头上。

  当把这些Tile载入内存的时候(可能不是全部载入),就需要在内存中再建一个类似的索引,nTilePos这个成员就成了指向Tile数据的指针了。在内存里可是寸土寸金,TILEINDEX的TileDesc成员就没必要要了。对于建立这个索引,还有一点要说明的。因为在一幅地图中,所用到的Tile数是有限的,没必要也不应该把所有的Tile一古脑全都读到内存里去。所以有很多Tile都是用不到的,那么在这个索引中,这些没用到的Tile的指针就置成NULL,以免误操作。只把需要的Tile读入内存,把相应索引里的指针置成正确的值。

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 Tile文件的组织
本类热点文章
  WIA模型及其参考
  游戏中如何读取压缩包文件
  游戏中的资源打包
  游戏中的资源打包技术
  数据结构在游戏中的简单应用
  Tile文件的组织
  管理项目的好助手——VSS入门
  怎样在VC++中读取INI文件
  ADO数据库编程入门
  数据打包格式
  VC中调用ADO的常用方法
  读取光盘
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00354