配置读取流程

配置读取流程

说的透彻一点,配置读取的本质就是把xml文件中的数据读取到程序中定义的数据结构中去。


开始读取配置

首先要提醒的是,在读取的过程中,我们必须做严格的检查,对读取失败的情况给出易读的说明。通常情况,读取失败意味着进程终止。这项工作并不容易,它伴随我们工作的自始至终,我们必须严谨对待。

当程序启动后,首先要做的事情就是加载配置,游戏中的硬编码配置极少,大部分都是通过配置文件来获取的。

配置之间也会有依赖关系,比如大部分的逻辑配置都依赖于物品配置,解决依赖的办法就是让物品配置先于逻辑配置加载。在World::InitGameWorld方法中就是全部游戏配置的加载步骤,其调用顺序是:

ServerLogic::Start
    World::Start
        World::InitGameWorld
                ...
                    LogicConfigManager::Init
                        yourconfig::Init // 你自己要实现的配置

我们大部分的配置都属于逻辑配置,它们被统一放在了(LogicConfigManager)里面管理。

定义配置结构体

我们需要把一张配置表的内容抽象成一个数据结构。我们的配置表就是一张行列二维表,因此用数组抽象是最合适的。

比如,有这样的配置结构:

cs cs cs cs cs
宠物id 激活所需物品 攻击 防御 血量
id active_item_id gongji fangyu maxhp
0 26000 100 100 100
1 26001 200 200 200
2 26002 300 300 300

前两行是说明,真正有效的内容从第三行开始。cs代表配置内容生成到客户端(c)和服务端(s)。中文的说明是给策划看的。

我们可以用这样的数据结构来抽象这个配置:

struct PetConfigItem
{
    int id = 0;                 // 宠物id
    ItemID active_item_id = 0;  // 激活所需物品
    int gongji = 0;             // 攻击
    int fangyu = 0;             // 防御
    int maxhp = 0;              // 血量
};

static const int MAX_PET_COUNT = 8;
PetConfigItem m_petconfig_list[MAX_PET_COUNT];  // 宠物配置

注意,PetConfigItem里的类内初始值是C++11的语法,部分项目并不支持,这时候应该用构造函数列表初始化。忘记初始化将是一种严重的编程错误,请务必牢记!

Question

以上配置结构的定义还有什么问题,有哪些优化方法?

提供获取配置的接口

配置读取完毕后,必须提供一个接口访问配置内容。这个接口的返回值必须是一个const指针(或引用)。

比如要获取一个宠物配置项,可以这样编写接口:

inline bool IsValidPetID(int id)
{
    // 保证是合法的、不会导致数组越界的id
    // ...
}

const PetConfigItem* GetPetConfigItem(int id)
{
    if (IsValidPetID(id))
    {
        return &m_petconfig_list[id];
    }
    return nullptr;
}

在实际编程中,我建议把这样有关数组下标判断的工作放到一个简单的inline函数中去。因为你可能在许多地方要做这样的判断工作,而且一旦出现错误,后果非常严重。

猜你喜欢

转载自blog.csdn.net/jonWei/article/details/82319140