Day05_OpenTTD的Sprite介绍

返回目录

今天的内容终于要与游戏沾边了,sprite是游戏里面贴图的小组件,比如地形上面的每一个方块,草地、水面、道路、铁轨,以及在上面跑的汽车、火车,天上的飞机,都是属于sprite。OpenTTD里面在游戏启动阶段会扫描预设的磁盘路径,把扩展名 grf 的文件信息解密加载到内存cache里面,后面的贴图直接采用内存块拷贝的方式推送到显卡上面。我们使用 openttd -d 2 启动游戏,在主控上可以看到大量包含 Replacing sprites 关键字的信息,如下:

在这里插入图片描述

通过这个关键字,我们可以检索到以下的调用链:

KeyWord: Replacing sprites
<- newgrf.cpp GraphicsNew /* Action 0x05 */
<- newgrf.cpp DecodeSpecialSprite()
<- newgrf.cpp LoadNewGRFFile()
<- newgrf_config.cpp FillGRFDetails()
<- gfxinit.cpp LoadSpriteTables()
<- gfxinit.cpp GfxLoadSprites()
<- genworld.cpp GenerateWorld()

这里特别需要说明的是,DecodeSpecialSprite()方法定义二维函数数组 handlers , 通过解析 grf文件里面的字段来确定使用具体的函数实现来解析文件生成相应的sprite
我们进一步分析 GraphicsNew()方法调用了 spritecache.cpp LoadNextSprite()

/**
* Load a real or recolour sprite.
* @param load_index Global sprite index.
* @param file_slot GRF to load from.
* @param file_sprite_id Sprite number in the GRF.
* @param container_version Container version of the GRF.
* @return True if a valid sprite was loaded, false on any error.
*/
bool LoadNextSprite(int load_index, byte file_slot, uint file_sprite_id, byte container_version)
{
...
    SpriteCache *sc = AllocateSpriteCache(load_index);
    sc->file_slot = file_slot;
    sc->file_pos = file_pos;
    sc->ptr = data;
    sc->lru = 0;
    sc->id = file_sprite_id;
    sc->type = type;
    sc->warned = false;
    sc->container_ver = container_version;


    return true;
}

在这个方法的最后部分,构造了一个SpriteCache类型的变量 sc,我们进一步分析AllocateSpriteCache()

struct SpriteCache {
    void *ptr;
    size_t file_pos;
    uint32 id;
    uint16 file_slot;
    int16 lru;
    SpriteType type;     ///< In some cases a single sprite is misused by two NewGRFs. Once as real sprite and once as recolour sprite. If the recolour sprite gets into the cache it might be drawn as real sprite which causes enormous trouble.
    bool warned;         ///< True iff the user has been warned about incorrect use of this sprite
    byte container_ver;  ///< Container version of the GRF the sprite is from.
};


static inline SpriteCache *GetSpriteCache(uint index)
{
    return &_spritecache[index];  <-- 看这里
}


static SpriteCache *AllocateSpriteCache(uint index)
{
    if (index >= _spritecache_items) {
        /* Add another 1024 items to the 'pool' */
        uint items = Align(index + 1, 1024);


        DEBUG(sprite, 4, "Increasing sprite cache to %u items (" PRINTF_SIZE " bytes)", items, items * sizeof(*_spritecache));


        _spritecache = ReallocT(_spritecache, items);


        /* Reset the new items and update the count */
        memset(_spritecache + _spritecache_items, 0, (items - _spritecache_items) * sizeof(*_spritecache));
        _spritecache_items = items;
    }


    return GetSpriteCache(index);
}
 

通过以上代码,我们可以了解到 游戏启动阶段,构造了 _spritecache 这个SpriteCache类型的数组,后面的学习中,我们将进一步了解到程序是如何使用内存中的这个数组完成界面元素的绘制工作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值