引擎: CocosCreator 3.8.0
环境: Mac
Gitee: oops-game-kit
引言
oops-framework是由作者dgflash
编写,基于CocosCreator 3.x而实现的开源框架。
该框架以插件形式存在,主要目的是为了降低与项目的耦合,并且通过插件内部的命令快速的获取最新版本。
该框架的特性有:
- 提供游戏常用的功能库,提高开发效率
- 提供业务模块代码模版,降低程序设计难度
- 内置模块低耦合,可根据需要自行删减,以适应不同的类型
- 提供了常用的插件工具,支持Excel表转Json、支持热更新、AB包
- 增加了ECS、MVVM框架相关,以及常用的屏幕适配,UI管理,多语言等等
为了方便大家更好的学习和使用该框架,作者很贴心的准备了一些学习资料:
注:oops-framework框架QQ群: 628575875
在CocosCreator官方商店,可以通过 oops 搜索更多的框架项目Demo进行学习。
本地存储
在CocosCreator中,本地存储主要使用sys.localStorage
接口,主要接口有:
接口 | 描述 |
---|---|
setItem(key, value) | 保存指定索引的数据 |
getItem(key) | 获取指定索引的数据 |
removeItem(key) | 移除指定索引的数据 |
clear() | 清空所有数据 |
数据以 key-value的格式进行存储,最后以sqlite数据库格式 明文 保存。
// 保存简单数据
sys.localStorage.setItem('gold', 100);
// 保存复杂数据
let userData = {
name: 'Tracer',
level: 1,
gold: 100
};
sys.localStorage.setItem('userData', JSON.stringify(userData));
// 读取数据
let data = sys.localStorage.getItem('gold');
console.log(data);
注: 内容参考官方文档:存储和读取用户数据
StorageManager
在 oops-framework 框架中,本地存储是通过 StorageManager
来实现的, 在Oop.ts
中调用的入口:
export class oops {
/** 本地存储 */
static storage: StorageManager = new StorageManager();
}
StorageManager
的实现,是对CocosCreator本地存储的额外包装,增加了新的特性,主要有:
- 设置用户ID,将key和用户ID组合,避免存储数据被覆盖
- 增加了MD5、AES的第三方库加密,key使用MD5加密, value使用AES加密,增加的数据的安全性
- 在模拟器或浏览器的调试下,不会触发数据加密,方便明文调试
提供的主要参数或接口有:
接口 | 返回类型 | 说明 |
---|---|---|
init(key: string, iv: string) | void | 初始化密钥 |
setUser(id: string) | void | 初始化用户ID,默认为空 |
set(key: string, value: any) | void | 存储数据 |
get(key: string, defaultValue: any = “”) | string | 获取数据 |
getNumber(key: string, defaultValue: number = 0) | number | 获取number类型数据 |
getBoolean(key: string) | boolean | 获取boolean类型数据 |
getJson(key: string, defaultValue?: any) | any | 获取Json类型数据 |
remove(key: string) | void | 移除指定字段的数据 |
clear() | void | 清空所有数据 |
以音频管理的初始化为例,看下简单示例:
let data = oops.storage.get(LOCAL_STORE_KEY);
加密
加密相关使用的是NPM第三方加密库: crypto-es, 支持对称加密、哈希函数、数字签名和公钥加密等。
注: 更多内容可参考: NPM crypto-es
关于加密相关,在框架中已经提供,在 node_modules/crypto-es目录中。
如果想自己安装,需要安装NPM,终端安装命令:
npm install -g yarn
yarn add crypto-es
注: NPM的安装可参考: Mac 安装使用NPM
框架针对于 crypto-es 封装了一个工具类: EncryptUtil.ts
,主要接口有:
接口 | 说明 |
---|---|
initCrypto(key, iv) | 初始化加密库的key和iv |
md5(msg) | 获取md5加密字段 |
aesEncrypt(msg, key, iv) | AES加密 |
aesDecrypt(msg, key, iv) | 获取AES解密数据 |
注: key和iv的设定在 resources/config.json中有设定
初始化
本地存储的初始化主要包含两个方面:
- key和iv的初始化,这个在框架的
Root.ts
获取 resources/config.json 完成初始化的
// Root.ts
onLoad() {
if (!isInited) {
let config_name = "config";
oops.res.load(config_name, JsonAsset, () => {
var config = oops.res.get(config_name);
// 初始化本地存储加密
var key = oops.config.game.localDataKey;
var iv = oops.config.game.localDataIv;
oops.storage.init(key, iv);
});
}
}
- 用户ID的初始化,在请求服务器获取用户ID后,进行初始化,示例代码:
var uid = 10000; // 用户唯一编号数据
oops.storage.setUser(uid);
注:本地模拟,没用用户ID,框架会默认为""
保存数据
数据的保存主要通过接口: set(key: string, value: any)
set(key: string, value: any) {
// 根据用户ID连接key
var keywords = `${key}_${this._id}`;
if (null == key) {
console.error("存储的key不能为空");
return;
}
// 检测是否对key进行MD5加密
if (!PREVIEW) {
keywords = EncryptUtil.md5(keywords);
}
if (null == value) {
console.warn("存储的值为空,则直接移除该存储");
this.remove(key);
return;
}
if (typeof value === 'function') {
console.error("储存的值不能为方法");
return;
}
// 转换object,number类型的value
if (typeof value === 'object') {
try {
value = JSON.stringify(value);
}
catch (e) {
console.error(`解析失败,str = ${value}`);
return;
}
}
else if (typeof value === 'number') {
value = value + "";
}
// 检测是否对value进行AES加密
if (!PREVIEW && null != this._key && null != this._iv) {
value = EncryptUtil.aesEncrypt(`${value}`, this._key, this._iv);
}
sys.localStorage.setItem(keywords, value);
}
框架主要做的事情:
- 将key字段以 key_用户ID 的方式进行连接,并检测是否进行MD5加密
- 检测value字段的类型,是否为null、function等不合法类型
- 转换value字段数据,将number转换为字符串、将object转换为json字符串
- 检测value字段是否进行AES加密
- 调用引擎提供的接口存储
Map数据存储
框架对于基础数据类型的支持是很好,但对 Map
对象的支持不太好,我们可以通过ES6的特性将Map转换为数组, 获取的时候将数组转换为Map对象,简单的示例:
let map = new Map();
map.set("a", 1);
map.set("b", "hello");
map.set("c", true);
// 将map转换为数组
let mapToArray = Array.from(map);
console.log(mapToArray); // [["a", 1], ["b", "hello"], ["c", true]]
// 将数组转换为map
let arrayToMap = new Map(mapToArray);
console.log(arrayToMap); // Map (3) {"a" => 1, "b" => "hello", "c" => true}
示例:
// 保存数据
private saveMapData() {
let map = new Map();
map.set("a", 1);
map.set("b", "hello");
map.set("c", true);
// 将map转换为数组
let mapToArray = Array.from(map);
// 存储数据
oops.storage.set("MapData", mapToArray);
}
// 获取数据
private getMapData():any {
let map = null;
let data = oops.storage.getJson("MapData", []);
if (Object.keys(data).length <= 0) {
map = new Map();
} else {
map = new Map(data);
}
return map;
}
// mapData: Map(3) {'a' => 1, 'b' => 'hello', 'c' => true}
console.log("mapData:", this.getMapData());
最后,祝大家学习生活工作愉快!