SDL中文论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 5632|回复: 3
打印 上一主题 下一主题

[讨论] 存档文件

[复制链接]

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
跳转到指定楼层
楼主
发表于 2020-8-24 15:59:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 ancientcc 于 2020-8-24 16:01 编辑

存档文件有两种格式,游戏存档和录像存档。游戏存档用于做个存档,以便将来某一时间继续玩,录像存档是用于录像回放。在内容上,录像存档是从游戏存档“抽”出,它是游戏存档子集。两种格式可用统一的格式进行表示。


存档文件形成有两种情况,单机和联网

不论单机还是联网,存档将不再使用wesnoth原有的[config]结构。虽然[config]形式是易读、易解析,但是考虑到要缩小存档文件大小。config的string_map中属性名,这些属性名说来是冗余的。

存档文件存放路径
X:\Documents and Settings\Administrator\My Documents\My Games\Kingdom0.1\saves

存档文件文件名
扩展名:*.sav
例如:
WOK-南郡战役_回合_12.sav
WOK-南郡战役-自动存档2.sav

用中文作为文件名会出现CreateFile失败问题。系统设置:1)安装的是简体中文WinXP;2)在控制面版“区域和语言选项”“高级”设置为“中文(台湾)”;3)重启系统,此时程序存档时CreateFile失败。
——以上换为没中文就成功。至此改为纯英文作为文件名,这就要求[campaign]块中的abbrev字段必须是纯英文。

如果安装的本来就是繁体中文,不知这问题是什么情况。
回复

使用道具 举报

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
沙发
 楼主| 发表于 2020-8-24 16:02:07 | 只看该作者

单机

存储
有两种方式存储操作:自动和手动。
自动存储是每一回合轮到玩家阵营时,自动生成一个存储文件。
手动存储是在程序运行过程中,玩家在菜单中选择“存储”命令。
自动存储(savegame::save_game_automatic)
save_game_automatic会用savegame::save_game执行:
  1. 1:before_save。形成[snapshot]等可以直接写入内存的变量。
  2. 2:write_game_to_disk。把[snapshot]等写入文件。
复制代码
手动存储(savegame::save_game_interactive)
1:显示确认存储对话框。
2:调用save_game。

加载
有两种情况下加载操作:初始界面时的“加载”操作,游戏过程中的“加载”操作

程序上“加载”加操作是通过loadgame中的两个load_game操作得到的。

初始界面时的“加载”操作
1:loadgame::load_game(std::string& filename, bool show_replay, bool cancel_orders, hero_map& heros)
@filename:要加载的文件名,包括*.sav扩展名,但不含路径。(前面是filename参数意义,但在此处就没有确定要选择哪个存档文件,给出的filename是空字串,loadgame::load_game须要显示“加载”对话框让玩家玩择一个存档文件)。
@heros:存档文件中的武将数据要被存放到hero_map。
注:存档文件中的config,虽然在load_game参数没有指定这个变量,但在loadgame构造函数时已传这下值。


游戏过程中的“加载”操作
1:loadgame::load_game()
这个load_game两个操作;1)显示“加载存档对话框”,2)向上抛出个game::load_game_exception异常,launch_game捕获到这个异常,并退出到do_gameloop,go_gameloop进而调用接下load_game。
2:loadgame::load_game(std::string& filename, bool show_replay, bool cancel_orders, hero_map& heros)。
回复 支持 反对

使用道具 举报

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
板凳
 楼主| 发表于 2020-8-24 16:02:44 | 只看该作者

处理“加载”

存档目录下有数十个存档文件时,如何提高“加载”响应速度,也就是更快地向玩家显示“加载”对话框?

游戏支持自动存储,每回合一个,很快就能形成数十个存档文件。

游戏加载执行逻辑(dialog.cpp中的load_game_dialog函数):

1:扫描存储目录,形成一个vector,std::vector<save_info>,vector单元save_info可理解为是内含(文件名,文件创建时间)这两个字段的结构。“文件创建时间”从文件系统得到,和文件内容无关。

2:std::vector<save_info>转换为std::vector<config*>。这个config当中内容是让玩家看的存储概述,但此时很简单,只有一个save字段有效,它指向存档文件名。注:config其它字段填充时机(第一个除外),它是在显示对话框后,玩家选中某一存档后才从该存档文件中读出概述部分,然后填充向config。

3:std::vector<config*>准备完毕,要开始显示。由于显示时列表框选择光标位在第1项,需让这个概述有效,执行从第一个存档文件中读出概述部分,填充完整这个config。

4:玩家看到“加载”框,切换到另外个“未曾访问”存档时,程序从该存档文件中读出概述部分,填充完整这个config。对于“未曾访问”和“已访问”是依据config中的label字段,空是“未曾访问”,否则“已访问”。
回复 支持 反对

使用道具 举报

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
地板
 楼主| 发表于 2020-8-24 16:03:24 | 只看该作者

处理“保存”

以手动保存实时存档为例

play_controller::save_game()被调用,它处理保存的全过程。
1、构造一个save_block::save_unblocker对象;
2、构造一个savegame::game_savegame对象;
3、调用game_savegame中的save_game_interactive操作,执行存储。

FAQ
A:在存储过程中,gamae_state是怎么个情况?
Q:game_state一直没有被构造过,它只是以引用形式从play_controller传到savegame层。
存储过程耗时不会是game_state对象造成的。

A:为什么须要调用(以上play_controller::save_game)构造snapshot块?
Q:这个snapshot块和最终在存档文件中的不是同一个。但它包含了snapshot块中主要部分,像[side],[time],以它为核心“底层”存储对象再加上像[event]块等构成了最终的[snapshot]。

这个snapshot块来源。——来自当时状态,play_controller:;to_config形成这个config,主要数据有[side]块,[time]块。

要注意,并不是所有类型存档文件的[snapshot]块都是有数据,有的只一对[snapshot][/snapshot]而已。以下是存档文件的对应[snapshot]情况。
实时存档(包括自动(game_savegame)和手工保存(autosave_savegame)):有[snapshot];
oos存档(oos_savegame):有[snapshot];
录像存档(replay_savegame):空[snapshot];
scenariostart存档(scenariostart_savegame):空[snapshot];

A:为加快保存速度,编程要注意什么?
Q:优化表现在让snapshot只赋值一次,即只是在to_config时。[snapshot]当中是大数据,多赋值一次可能就是数秒时间。
1)修改play_controller::to_config实现。它直接接收一个config做为参数,然后在这config上修改。不要使用内部构造一个config,然后这个config赋给上层形成。——基于这个改动,使这个to_config形式和savegame::savegame_config要求的不一致,play_controller暂改为不从savegmae_config派生。
2)snapshot_在savegame中以引用存在。这意味着1:“保存”模块将修改上层传下的snapshot(当前都是要保存时临时用to_config形成个config);2:引用值在构造函数时是必须被初始,但像录像存档时上层是不传snapshot的,这时“保存”模块使用一个静态“哑”config传给内部,满足了要求。savegame.cpp中的dummy_snapshot就是这个“哑”config,理论上是什么时候都应该是空的。

注:代码在game_save构造函数中对snapshot赋值是使用snapshot().merge_with(snapshot_cfg),而不是直接等于。现在改为引用可说是直接等于,不知这会不会造成问题。

game_state已经是引用,不须要优化了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|丽谷软件|libsdl.cn

GMT+8, 2025-5-2 03:43 , Processed in 0.049251 second(s), 22 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表