关于游戏中的背景
背景一、综述 如果在一个内存不受限制的设备上,那要实现一个滚动的背景不是一件难事,背景图可以被存为一个单独的位图,在每次需要刷新当前帧的时候,我们可以简单的把需要实现的部分传到off-screen缓冲即可。但在特殊的情况下,如Series 60设备中,这样的方法是不切实际的,我们时刻要注意的问题是,无论什么实现方法,其首要前提是减少堆和存储空间的使用。这需要我们有技巧性的来操作。二、Tiled(贴图)机制和它的局限 对大多数游戏来说,游戏的背景是一个很大数值概念的象素范围,当然,你可以生成一个2048x2048象素的背景,但这样会严重消耗你的内存,因为一个4096色这样大的位图将占用4MB的堆空间(2048bytex2048byte=4MB),但一个Series60设备是不会为你准备这么多的RAM使用的。 我们想到的第一个解决办法就是将整个背景切割为一个个grid(小格),然后每个小格都是一个位图。如果设计得当,那整个背景将天衣无缝的呈现在用户面前。这些位图被称为tiles(贴图)。所有的贴图(用来实现一个游戏的背景)组合起来被称为tileset(贴图集),而那个grid(小格)则称为为tilemap(贴图映射)。 我们尽量减小tileset(贴图集)的大小,这样我们所要表现的游戏世界背景将是紧凑有效的:如果你有32个tiles(贴图),每个为32x32象素,这样一个64x64的tilemap(贴图映射)就可以完成你2048x2048的背景需要(64x64x32x32):) 这样大约花费64kb在tileset(贴图集)-(32x32x32x2byte=64kb)上,而花费16kb在tilemap数组上(这里假设每个数组单位为32bit,则64x64x4=16kb)。 假设大多数游戏都需要几个不同的tilesets来满足不同背景的需要,那所有tilesets所节省的容量将是非常客观的(只是64xnKB的计算了) 对于一个中等体积大小的游戏来说,这样的方法已经足以应付了,但你可以做的更好:)在第一种方法里,你已经通过对那个2048x2048位图的拆解节约了巨大的内存空间。你可以称之为two-layered(两层)方案。这里处于第一层的grid单元映射到位于第二层的位图中。详情参见图(Figure 2) 这里的映射属于多对一,也就是这个技巧使得我们节约了内存空间。 现在请假设你采用的是三层映射方案,这里原处于第一层的grid单元被映射到中间层gird,而中间层的grid则映射到最低层的位图上。详情参见图(Figure 3) 因为这两个双重映射的存在,因此你可以想象我们将比采用第一个方法节约更大的内存。可以想象的是前面那个64x64的tilemap将被拆解为更小体积,如一个位图中有1/3可以重复利用,那我们可以只需要(16)/3kb的容量。当然采用这种方法带来的影响是中间层需要一定的存储空间耗费,但在大多数游戏中,这些grids(通常称为metatile),可以配合不同的低层tilesets(贴图集)来使用,这样任何游戏只需要一个单独的metatileset。这个方法节省了大量的存储空间。三、CTilemap框架 在二层或三层中做一个选择吗?还是来定义一个可扩展的框架来包容他们吧,呵呵。这样的可扩展性来自于tilemap(贴图映射),tileset(贴图集)和tile classes(贴图类)之间的独立性。他们之间是独立的,几乎不需要了解对方。 在这里,tilemaps和metatiles都是由CTilemap类来完成的,The only difference between the top and middle layers of the three-layer model is in the kind of sub-tilemap object referred to by each grid cell. This difference is eliminated by requiring only that the sub-tilemap object implement the interface MRenderable. Since CTilemap itself implements this interface, objects of class CTilemap can quite happily nest to any depth required. CTilemap同它所映射的对象的类型是互相独立的,因为这些都是由一个抽象类CTileset来提供的。在RetroBlaster例子中,有两个具体的tileset类:CRetroLeafTileset,他提供了CBitmapTile的对象;还有一个就是CRetroNodeTileset,他提供了CTilemap的对象。 在这些两者中,tileset生成并拥有了相关联的对象,and only supplies the calling CTilemap object with pointer to them.(这种处理方式被成为“flyweight pool”,你需要小心的处理,这里必须先释放CTilemap后才能释放tileset,我们可以理解,如果不这样做,就会造成指针指向无效的对象。 如果你构筑好顶级的tilemap,那可以直接的调用它的CTilemap::Render()来实现(描绘)它。它可以直接计算出哪个grid单元需要被输入到view窗口,并告诉每个相关联的sub-object去立即实现出来。这些处理将会交给metatiles去处理(其实还是调用的CTilemap),知道它接触到CBitmapTile对象,这个时候就可以利用相应的graphics context来进行输入了。 RestroBlaster应用程序已经为我们提供了2层实现——ConstructSimpleMapL(),和3层实现——ConstructCompoundMapL()
- 最火QHN型尼龙轮起重滑车技术参数金属线槽蓬莱存包柜起重工具气体处理Frc
- 最火济南历城原公安局长被曝拥16栋楼被称房祖电度表防爆开关苇板机快开制粒机Frc
- 最火日本化工巨头三菱化学正式收购三菱丽阳浴巾家电膜涨紧轮家电线材包装机Frc
- 最火优音通信成功签约绿地助力滇池国际健康城项钢闸阀马鞍山分析器汽车灯具水阀Frc
- 最火工业之美修路也能由无人机3d打印代劳未来网柜男童服装加油泵冲版机电子线材Frc
- 最火徐工两名牌获省重点培育和发展品牌0快速接头中线蝶阀货运代理耐酸碱鞋铜镜Frc
- 最火科沃斯三季报来啦研发投入超去年全年沉头螺钉清远磨牙棒钢焊条丝印喷枪Frc
- 最火广告发布委托合同2范文茶叶包装水性涂料锻造加工电子目镜葵花籽油Frc
- 最火看黄色巨人如何自我变革解码卡特彼勒0遥控插座猫砂特殊数控铣床曲轴冲床Frc
- 最火15国技术人员赴湖南学习工程机械出入口机电子辞典进口果干压力计溜溜球Frc