首先在开始的MyApp中添加

GameState=require(cc.PACKAGE_NAME .. ".cc.utils.GameState")

或者GameState = require("framework.cc.utils.GameState")

--全局变量
 GameData={}
 function MyApp:ctor()
     MyApp.super.ctor(self)
     GameState.init(function (param)
     local returnValue = nil
     if param.errorCode then
     print("GameState Error")
     else
     print("GameState Right")
     if param.name == "save" then
     local str = json.encode(param.values)
     str = crypto.encryptXXTEA(str, "abcd")
     returnValue = {data = str}
     elseif param.name == "load" then
     local str = crypto.decryptXXTEA(param.values.data, "abcd")
     returnValue = json.decode(str)
     end
     end
     return returnValue
     end,"data.txt","1234")
     if io.exists(GameState.getGameStatePath()) then
     print("dddddddd",GameState.getGameStatePath())
     GameData = GameState.load()
     end
     --存储数据
     GameData.aaa="bbbmmmmmmmmmmmm"
GameState.save(GameData)
--取出数据直接用就OK
print(GameData.aaa)end

注意:初始化的GameState.init和加载GameState.load()只需在构造里面调用一次即可


-----------------------------------------------------------------------------------详细说明------------------------------------------------------------------------------------------

GameState是Quick-Cocos2d-x中特有的一个用户信息存储类,相对于CCUserDefault而言,它增加了数据校验的功能,当数据被人为的改变之后,会被检测出来,下面介绍它的主要用法。

一、初始化

因为GameState并没有在framework中加载,所以我们要在开始的代码中去加载,如在MyApp.lua的开头位置加载

GameState=require(cc.PACKAGE_NAME ..".cc.utils.GameState")


二、提供的方法

1、GameState.init(eventListener_, stateFilename_, secretKey_)

这个方法是初始化GameState,在场景初始化之前调用一次即可,如在MyApp.lua的MyApp:ctor()中调用。

eventListener_是载入或保存时调用的函数,可以写个匿名函数,后面会重点介绍;

stateFilename_是保存的文件名,如果留空或非字符串(string)则是默认的state.txt,该文件会被保存到device.writablePath下;

secretKey_是 校验文件时所用到的密钥,GameState保存的数据格式为{h = hash, s = s},s是我们要保存的数据(一个table),h则是要校验的一个md5码。如果secretKey_留空或为非字符串(string)则不加校验码, 直接保存数据,跟CCUserDefault一样了。

2、GameState.load()

载入并返回数据,一般此方法只调用一些就行,在游戏加载前调用并保存到一个全局变量GameData。

3、GameState.save(newValues)

保存数据,newValues是一个table。GameState.init对应于保存一个文件,此文件的内容就是newValues,所以我们需要更新数据的时候应该改变上面的GameData,然后保存GameData。

4、GameState.getGameStatePath()

保存的文件的完整路径。

三、eventListener(value)

此函数就是GameState.init中的第一个参数,value为一个table,此函数在载入或保存时都会被调用,相当于一个监听器。不同的情况下value的值会不一样。

注意:eventListener一定要有返回值。

1、GameState.load()中用到的eventListener

1)  如果在这个函数中载入数据时有异常发生,value值为{name = “load”, errorCode = errorCode},name有两种值,”load”和”save”,分别对应载入和保存;errorCode分为三种:

GameState.ERROR_INVALID_FILE_CONTENTS          //不合法的文件内容,即取出来的内容不是一个table        
         GameState.ERROR_HASH_MISS_MATCH          //文件被人为更改过        
         GameState.ERROR_STATE_FILE_NOT_FOUND          //文件不存在


这个时候eventListener可返回nil。

2)  如果载入的数据是正确的,value值为

{        
                  name   =          "load"         ,        
                  values = values,        
                  encode = encode,        
                  time            = os.         time         ()        
                  }


values就是取出的数据;encode数据是否加密过;time当前取出的时间。这个时候eventListener返回value.values即可。

2、GameState.save(newValues)中用到的eventListener

这时value值为

{        
                  name   =          "save"         ,        
                  values = newValues,        
                  encode = type(secretKey) ==          "string"        
         }


values就是要保存的数据;encode数据是否要加密。这个时候eventListener返回value.values即可。

当然,以上的情况你都可以做一些其它的事,如弹出错误的窗口,或打印出已加载或已保存的数据。

四、加密数据

GameState保存的还是明文数据,只是加了校验码,如果我们不想被用户知道保存了什么信息,可加密了再保存,这个在eventListener中“过滤”一下就行了。

五、示例

下面是一个完整的加载、初始化、载入,保存及加解密的过程代码:

//MyApp.lua(加载、初始化、载入,加解密)        
         ...        
         require(         "framework.cc.init"         )        
         GameState=require(cc.PACKAGE_NAME ..".cc.utils.GameState"                  )        
         -- global var        
         GameData={}        
         ...        
         function MyApp:ctor()        
                  -- init GameState        
                  GameState.init(function(param)        
                  local returnValue=nil        
                  if          param.errorCode then        
                  CCLuaLog(         "error"         )        
                  else        
                  -- crypto        
                  if          param.name==         "save"          then        
                  local str=json.encode(param.values)        
                  str=crypto.encryptXXTEA(str,          "abcd"         )        
                  returnValue={data=str}        
                  elseif param.name==         "load"          then        
                  local str=crypto.decryptXXTEA(param.values.data,          "abcd"         )        
                  returnValue=json.decode(str)        
                  end        
                  -- returnValue=param.values        
                  end        
                  return          returnValue        
                  end,          "data.txt"         ,         "1234"         )        
                  if          io.exists(GameState.getGameStatePath()) then        
                  GameData=GameState.load()        
                  end        
         .....        
         end        
         ....        
         //保存的时候        
         GameData.aaa=         "bbb"        
         GameState.save(GameData)