除了Flappy Bird之类的小游戏,许多游戏都需要保存和载入进度,以便玩家可以随时中断游戏,之后又能继续玩下去,在GameMaker Studio中有几种方法都可以实现类似的功能,接下来会分别介绍一下三种方法:
- 自带函数game_save()
- ini配置文件保存
- ds_map加密存储
大家可以根据自己游戏的复杂程度和自己的喜好来选用。
自带函数game_save()
在GameMaker Studio中自带两个存档和读档的方法:
- game_save()
- game_load()
这两个方法在调用时都只需要在括号中填入字符串格式的文件名作为参数即可
game_save("save.dat")
game_load("save.dat")
如上的代码就是将当前游戏的一些静态内容保存到一个名为"save.dat"的文件中(或从中读取),如各种变量等,但这个方法无法指定哪些内容需要保存,而哪些又需要排除,并且无法保存游戏中创建的动态资源,诸如数据结构(ds_list、ds_map等)。
并且当你开启了某个场景(room)自带的物理特性以后这个方法就会失效无法使用。
另外好像这种方法保存的文件在重新编译更新游戏版本时是无法继承的。
所以这个方法其实还是十分有局限性的,只有当游戏非常简单对保存的数据内容非常有限时可以考虑用一下。
ini配置文件保存
这可能是最普遍的一种方法,可以自定义需要保存的值,而且不算复杂,但是使用这种方法首先要对ini配置文件有基本的理解,这里放了一篇基本的说明,不了解的朋友可以先去看看——INI文件介绍。
下面这个图是GMS帮助文档里的配图借来用一下
使用ini配置文件保存数据的方法如下:
ini_open("saveData.ini"); //打开ini文件,如果不存在则新建
ini_write_real("Variables", "score", score); //第一个值是section,第二个值是key,第三个值是对应要写入的value
ini_write_string("Variables","string",string); //同上,不过这是写入字符串的方法
ini_close(); //用完记得关闭文件否则容易内存溢出
在使用ini_open的方法打开/新建了一个ini配置文件以后,就可以将你所需要的值全部存入这个文件,比如血量、分数、人物等级等等,甚至可以把每一个对象的坐标都保存到文件里,方便下次载入时能让画面完全恢复原装。
而当你载入游戏时就需要用以下方法进行读取:
ini_open("saveData.ini");
score = ini_read_real("Variables","score",0); //如果文件中没有对应的值则会将第三个参数保存到文件里
string = ini_read_string("Variables","string","Hello world"); //同上,只是字符串的方法而已
ini_close();
用这个方法你可以把你之前保存的数据依次读取出来,然后加载到你当前的游戏中来,这里要注意的是如果在存档文件中没有获取到对应的值时,会将此处第三个参数的内容作为默认值写入存档文件,切记。
ds_map加密存储
其实在GMS中自带了十分方便的方法可以直接把ds_map、ds_list等数据结构保存成物理文件(对应也有方法可以读取这些文件),下面以ds_map为例介绍一下这种方法,希望能有帮助。
而保存和读取文件主要会使用到的方法是:
- ds_map_secure_save
- ds_map_secure_load
而要使用ds_map来保存数据,首先我们要对这种数据结构有一个大致的了解:
如上图,我们可以把ds_map想像成这样一个数据集合,其实它的数据结构跟ini配置文件十分类似,只是少了一个"section"的分类,其中的数据同样是由一对对"key"、"value"构成。
而GMS中针对ds_map也有大量内置函数可以用于数据的增删改查:
- ds_map_exists
- ds_map_create
- ds_map_add
- ds_map_clear
- ds_map_copy
- ds_map_replace
- ds_map_delete
- ds_map_empty
- ds_map_size
- ds_map_find_first
- ds_map_find_last
- ds_map_find_next
- ds_map_find_previous
- ds_map_find_value
- ds_map_read
- ds_map_write
- ds_map_destroy
有关于这些方法的具体使用可以参考之前翻译的文档——
接下来,我们用一个实际的例子来说明一下如何用ds_map来保存游戏信息:
假设我们现在有一个简单的RPG游戏,现在要保存游戏进度,我们需要保存的内容有英雄的等级、血量、攻击力,以及英雄身上的装备的信息
save_1 = ds_map_create(); //创建一个ds_map保存到save_1变量中
//
ds_map_add(save_1,"Head",hero_head);// 在save_1中增加一个key为"Head"的数据,值为hero_head
ds_map_add(save_1,"Right Hand",hero_right_hand);//同上
ds_map_add(save_1,"Left Hand",hero_left_hand);//同上
ds_map_add(save_1,"Level",hero_level);//在save_1中增加一个key为“Level”的数据,值取hero_level对应的值
ds_map_add(save_1,"HP",hero_hp);//同上
ds_map_add(save_1,"Attack",hero_attack);//同上
ds_map_secure_save(save_1, "save1.dat" ) ;//把save_1中的ds_map保存为一个名为"save1.dat"的物理文件
ds_map_destroy(save1.dat);//释放内存
通过以上操作我们就可以完成我们之前的目标,将需要保存的信息通过ds_map进行储存并加密保存为一个物理文件,由于这种保存方式自带加密操作,因此存档文件的安全性较ini配置文件要更高。
而当游戏中执行加载存档的方法时我们可以这么做:
load_save = ds_map_secure_load("save1.dat")//加载"save1.dat"文件中的ds_map保存到"load_save"中
//加载ds_map中的数据保存到游戏变量中
hero_head = ds_map_find_value(load_save, "Head");
hero_right_hand = ds_map_find_value(load_save, "Right Hand");
hero_left_hand = ds_map_find_value(load_save, "Left Hand");
hero_level = ds_map_find_value(load_save, "Level");
hero_hp = ds_map_find_value(load_save, "HP");
hero_attack = ds_map_find_value(load_save, "Attack");
ds_map_destroy(load_save);//释放内存
以上,其实从原理上来说跟ini配置文件的使用方式是十分类似的,但是个人更推崇这种方式
- 加密性更好
- ds_map的数据结构也更好与ds_list和ds_grid等联动
- ini配置文件同时只能开启一个,ds_map只要内存不炸理论上可以多个同时操作