28. 内容支持Part4: 策划数据¶
为实现游戏逻辑,须要能够使用策划人员创建的游戏数据。 例如,对于道具的价格或属性信息而言,各个道具并不是通过单独的C++/C#类来实现的,而是依赖于从外部读取到的item策划文件。
为此,iFun引擎提供了用于读取游戏数据的 ResourceManager
接口。
该class的具体信息可在 此处 查看。
28.1. 读取策划数据¶
策划数据支持JSON文件、各项用tab区分的文件,以及存在于MySQL DB中的文件。
28.1.1. 当策划数据为JSON文件时,¶
如下所示,将在MANIFEST.json中写入JSON文件所在目录名称。
"ResourceManager": {
"game_json_data_dir": "game_data"
}
iFun引擎将读取 game_json_data_dir
目录下的JSON文件。
Important
此时,各个文件的扩展名须为json、txt、text中的一种,且不分大小写。
Tip
在游戏服务器打包时,最好同时包含 game_json_data_dir
。因此,除了MANIFEST.json以外,最好也在CMakeLists.txt的 RESOURCE_DIRS
中列出。具体内容请参考 将游戏资源文件包含在package中 。
28.1.2. 当策划数据为tab分隔符文件时¶
与JSON类似,可以读取用tab分行的数据文件。MANIFEST.json的设置相同。
28.1.2.1. 文件条件¶
此时,文件须满足如下条件。
28.1.2.1.1. 编码及扩展名¶
文件须为ascii或utf-8,当为utf-8时,包含BOM。
文件的扩展名须为.txt或.text。
28.1.2.1.2. 注释¶
以//或#开头的行是注释。
28.1.2.1.3. 标头¶
除了注释以外的其他首行代码均属于header,并用tab分隔来列出field名称。
28.1.2.1.4. 数据¶
Header之后的行属于data,用tab分隔,列出field名称。
header的field个数和data的field个数应相同。
各字段前后的空格均删除。
如果已删除空格的data field为null string,相应的field将成为null JSON object。
非null的field可为整数、实数、字符串的形式。
28.1.2.2. 转换为JSON数据¶
拥有上述结构的文件可通过如下规则转换成JSON数据。
每行为{“header1”: “data1”, “header2”: “data2”}的形式。
转换后的行单元内容将成为数组的元素。
因为已转换成了JSON,所以在游戏中使用时,将运用 ResourceManager::GetJsonData(…) 函数。
28.1.2.2.1. 示例:tab分隔符文件的JSON转换¶
例如,如下所示的Item.txt文件最终将转换成下面的JSON。
// comment
// comment
Index Name Price Description
0 힐링 포션 100.0 힐링해주는 포션. 힐링힐링~
1 단검 50.0 가장 기본이 되는 검.
[
{
"Index": 0,
"Name": "힐링포션",
"Price": 100.0,
"Description": "힐링해주는 포션. 힐링힐링~"
},
{
"Index": 1,
"Name": "단검",
"Price": 50.0,
"Description": "가장 기본이 되는 검."
}
]
28.1.3. 当策划数据以DB数据表形式存在时¶
28.1.3.1. 设置MANIFEST.json¶
按如下所示设置MANIFEST.json。
"ResourceManager": {
"enable_game_data_mysql": true,
"game_data_mysql_server": "tcp://localhost:3306",
"game_data_mysql_username": "funapi",
"game_data_mysql_password": "funapi",
"game_data_mysql_database": "funapi",
"game_data_mysql_tables": "game_data_table1,game_data_table2"
}
所记述的内容为DB访问信息和要读取的DB table名称。
要读取的DB table名称在 game_data_mysql_tables
中记述,并且可以列出多个数据表,用逗号(,)分开即可。
28.1.3.2. 转换为JSON数据¶
各个table通过以下规则转换成JSON文件。
Table的名称为JSON文件的文件名。
各row以{“column1”: “data1”, “column2”: “data2”}的形式转换为JSON object。
转换后的行单元内容将成为数组的元素。
值的读取方法使用 ResourceManager::GetJsonData(TABLE_NAME) 。
28.1.3.2.1. 示例:DB中策划数据的JSON转换¶
例如,以下为名为Item的DB table,最终将转换成下面的JSON。
mysql> select * from Item;
+-------+----------+-------+----------------------------+
| Index | Name | Price | Description |
+------------------+-------+----------------------------+
| 0 | 힐링 포션| 100.0 | 힐링해주는 포션. 힐링힐링~ |
| 1 | 단검 | 50.0 | 가장 기본이 되는 검. |
+------------------+-------+----------------------------+
2 rows in set (0.00 sec)
[
{
"Index": 0,
"Name": "힐링포션",
"Price": 100.0,
"Description": "힐링해주는 포션. 힐링힐링~"
},
{
"Index": 1,
"Name": "단검",
"Price": 50.0,
"Description": "가장 기본이 되는 검."
}
]
28.2. 使用策划数据¶
- 首先,已读取的JSON data可通过
ResourceManager::GetJsonData(…) 进行访问。在上述示例中,若存在名为Item.json的文件,则该JSON数据可按如下所示调用。
Ptr<const Json> items = ResourceManager::GetJsonData("Item.json");
BOOST_ASSERT(items && items->IsArray());
for (size_t i = 0; i < items->Size(); ++i) {
const Json &item = (*items)[i];
LOG(INFO) << "item name: " << item["Name"].GetString();
LOG(INFO) << "item price: " << item["Price"].GetDouble();
}
JToken items = ResourceManager.GetJsonData ("Item.json");
Log.Assert (items != null && items.Type == JTokenType.Array);
foreach (JObject item in items) {
Log.Info ("item name: {0}", item["Name"].Value<string>());
Log.Info ("item price: {0}", item["Price"].Value<double>());
}
28.3. 为策划数据建立索引¶
为通过数据表形式读取的游戏数据建立索引,将非常便于管理,可通过key field轻松访问。 为此,iFun引擎提供了名为 ResourceManager::IndexJsonArray(…) 的函数。
Ptr<const IndexedJsonData> indexed_item_table;
bool MyGameServer::Install(const ArgumentMap &arguments) {
...
Ptr<const Json> json = ResourceManager::GetJsonData("Item.json");
indexed_item_table = ResourceManager::IndexJsonArray(*json, "Index");
BOOST_ASSERT(indexed_item_table);
}
void OnItemUse(const Ptr<Session> &session, const Ptr<Json> &message) {
...
int item_index = ...
IndexedJsonData::const_iterator it = indexed_item_table->find(item_index);
BOOST_ASSERT(it != indexed->end());
const Json &item_info = *(it->second);
int price = item_info["Price"].GetInteger();
...
}
public class Server
{
Dictionary<int, JObject> the_indexed_item_table = null;
public static void Install(ArgumentMap arguments)
{
...
JToken json = ResourceManager.GetJsonData ("data.json");
the_indexed_item_table = ResourceManager.IndexJsonArray (
(JArray) json, "Index");
Log.Assert (indexed_item_table != null);
}
void OnItemUse(Session session, JObject message)
{
...
int item_index = ...
JObject item_info = null;
Log.Assert (the_indexed_item_table.TryGetValue(item_index, out item_info));
int price = (int) data ["Price"];
...
}
}
28.4. 策划数据的相关设置参数¶
game_json_data_dir: 以JSON形式存在的、包含游戏策划数据的目录路径。(type=string, default=””)
enable_game_data_mysql: 包含游戏策划数据的MySQL服务器连接信息。(type=bool, default=false)
game_data_mysql_server: 包含游戏策划数据的MySQL服务器连接信息。(type=string, default=”localhost:3306”)
game_data_mysql_username: 包含游戏策划数据的MySQL服务器用户名。(type=string, default=”funapi”)
game_data_mysql_password: 包含游戏策划数据的MySQL服务器密码。(type=string, default=”funapi”)
game_data_mysql_database: 包含游戏策划数据的MySQL数据库名称。(type=string, default=”game_data”)
game_data_mysql_character_set: 用于与游戏策划数据DB进行连接的character set。(type=string, default=”utf8”)
game_data_mysql_tables: 相当于游戏策划数据的MySQL数据表名称。通过逗号区分。(type=string)