`cocos2dx非完整` 开始自己的FW模块

上一篇的文章中说到了一些个人习惯的东西以及一些简单的项目配置,这一篇文章我们来进一步完善一些东西.首先,打开编译以后的客户端执行,会看到一大堆的fileutils加载luac文件的提示,在终端显示一大堆,挺烦人的,我做的第一件事就是去修改他.这个很简单,有两种做法,第一种是在c++部分添加调用

 1 cocos2d::FileUtils::getInstance()->setPopupNotify(false); 

当然也可以在lua部分添加,

 1 cc.FileUtils:getInstance():setPopupNotify(false) 

两种做法都很简单,根据自己选择.我选择是在AppDelegate.cpp中添加.暂时没有在c++部分添加自己的模块,因为现在还不需要,后面需要的时候会再说.我将新项目中的其他lua文件全部删除了,res下面的所有资源也都删除了,修改了main.lua中的源码,只留下了引擎启动初始化glview部分的代码,这样就足够了,无论是开发一款什么样子的项目,我们都是从这里开始的.修改后的源码如下,很多同学不用看,只是为了保持我写文章的原始目的,尽量说明我的思路.

 1 -- 小岩<757011285@qq.com>

 2 -- 2015-5-25 13:10

 3 cc.FileUtils:getInstance():addSearchPath("res")

 4 cc.FileUtils:getInstance():addSearchPath("src")

 5 

 6 require "cocos.init"

 7 local fw = require "fw.init"

 8 

 9 function __G__TRACKBACK__(msg)

10     print("lua error: " .. tostring(msg) .. "\n")

11     print(debug.traceback())

12     return msg

13 end

14 

15 local function main()

16     collectgarbage("collect")

17     -- avoid memory leak

18     collectgarbage("setpause", 100)

19     collectgarbage("setstepmul", 5000)

20 

21     -- initialize director

22     local director = cc.Director:getInstance()

23     local glview = director:getOpenGLView()

24     if nil == glview then

25         glview = cc.GLViewImpl:createWithRect("HelloLua", cc.rect(0,0,900,640))

26         director:setOpenGLView(glview)

27     end

28 

29     glview:setDesignResolutionSize(480, 320, cc.ResolutionPolicy.NO_BORDER)

30 

31     --turn on display FPS

32     director:setDisplayStats(true)

33 

34     --set FPS. the default value is 1.0/60 if you don't call this

35     director:setAnimationInterval(1.0 / 60)

36 

37 end

38 

39 local status, msg = xpcall(main, __G__TRACKBACK__)

40 if not status then

41     error(msg)

42 end
main.lua

 

好的,可能很多人做到这里,就会思考并开始写代码了.我像这样应该还是缺少很多东西的,尤其是我们做过一些项目后就知道,有很多基础的模块和功能还是需要的,实现这个过程就像是盖房子打地基,我就花费了半天的时间来做这件事情.我先是构思了一下,然后稍作修改了一下项目的目录结构.修改后的目录结构如下:

-- res

-- src

   -- cocos

   -- fw

      -- ini.lua

      -- util

         -- fileutil.lua

         -- platform.lua

         -- convert.lua

      -- oop

         -- ini.lua

         -- csv.lua

         -- kv.lua

         -- classickv.lua

   -- game

   -- main.lua

好的下面我来解释一下这个目录.我添加了fw目录作为项目通用的模块,这样做是有好处的,如果以后项目需要的话,做的好,我完全可以直接把这个模块拿过去,稍作修改甚至是不用修改就可以胜任了,也就是积累我们自己的代码.当然,鱿鱼经验受限,我们会一次又一次的重构这个模块,就像我,不停的去修改去完善,让它在某些方面更合理.其实昨天我主要是添加了三个方面的功能:

1.我将cc.FileUtils里面的结构全部倒入了我写的fileutil中,并添加了部分自己的功能,源码如下:

 1 -- 小岩<[email protected]>

 2 -- 2015-5-25

 3 local platform = require "fw.util.platform"

 4 

 5 local fu = {}

 6 local cc_fileutils_ = cc.FileUtils:getInstance()

 7 

 8 function fu.is_dir(filename)

 9     return string.byte(filename, -1) == 47

10 end

11 

12 function fu.is_absolute_path(filename)

13     return cc_fileutils_:isAbsolutePath(filename)

14 end

15 

16 function fu.get_writable_path(filename)

17     if filename then

18         return platform.get_writable_path() .. filename

19     end

20     return platform.get_writable_path()

21 end

22 

23 function fu.get_full_path(filename)

24     return cc_fileutils_:fullPathForFilename(filename)

25 end

26 

27 function fu.get_string(filename)

28     return cc_fileutils_:getStringFromFile(filename)

29 end

30 

31 function fu.write_content(filename, content, mode)

32     mode = mode or "w+b"

33     local file = io.open(filename, mode)

34     if file then

35         if file:write(content) == nil then 

36             return false

37         end

38         io.close(file)

39         return true

40     else

41         return false

42     end

43 end

44 

45 function fu.is_exists(filename)

46     if fu.is_dir(filename) then

47         return cc_fileutils_:isDirectoryExist(filename)

48     end

49     return cc_fileutils_:isFileExist(filename)

50 end

51 

52 function fu.make_dir(dirname)

53     return cc_fileutils_:createDirectory(dirname)

54 end

55 

56 function fu.remove(filename)

57     if fu.is_dir(filename) then

58         return cc_fileutils_:removeDirectory(filename)

59     end

60     return cc_fileutils_:removeFile(filename)

61 end

62 

63 function fu.rename_file(dir, old, new)

64     return cc_fileutils_:renameFile(dir, old, new)

65 end

66 

67 function fu.get_file_size(filename)

68     return cc_fileutils_:getFileSize(filename)

69 end

70 

71 return fu
fileutil.lua

 

2.添加了跨平台部分的文件存储处理,主要是处理writablepath.这个在platform.lua中,很快我就会写到增量动态更新模块,我期望在windows下面存储的路径就是res/,而在android下面则是writablepath.所以这个修改也是为了这部分功能先行的.源码如下:

 1 -- 小岩<[email protected]>

 2 -- 2015-5-25

 3 local p = {}

 4 

 5 local OS_NAME = 

 6 {

 7     "WINDOWS",

 8     "LINUX",

 9     "MAC",

10     "ANDROID",

11     "IPHONE",

12     "IPAD",

13     "BLACKBERRY",

14     "NACL",

15     "EMSCRIPTEN",

16     "TIZEN",

17     "WINRT",

18     "WP8",

19 }

20 

21 local arch_code = cc.Application:getInstance():getTargetPlatform()

22 local arch_name = OS_NAME[arch_code+1]

23 

24 p.arch_code = arch_code

25 p.arch_name = arch_name

26 

27 function p.get_writable_path()

28     if p.arch_code == cc.PLATFORM_OS_WINDOWS then

29         return "res/"

30     else

31         return cc.FileUtils:getInstance():getWritablePath()

32     end

33 end

34 

35 return p
platform.lua

 

3.处理各种配置文件,我暂时添加了四种,k-v有两种,ini格式,csv格式,准确的说是三种,不过我提供的classickv是支持lua语法的,因为本质上就是使用luastring返回的函数生成的,所以可以直接在其中使用lua语法,如果是使用sublime,可以直接ctrl+shift+p, 然后输入set synatax:lua去直接编辑配置文件.不过很快我就会再次介绍这种使用lua语法的好处,用在启动引擎的各种参数上面再好不过了.下面我就一一给出这四个文件.不过首先得看convert.lua 这个其实就是各加载到内存的配置字符串,解析成为对应的lua table.

  1 -- 小岩<[email protected]>

  2 -- 2015-5-25

  3 local c = {}

  4 

  5 c.t = 

  6 {

  7     kv     = "key-value format",

  8     ini = "section-key-value format",

  9     csv = "export csv format",

 10     classickv = "classic key-value format",

 11 }

 12 

 13 local function lua_split(str, reps)

 14     local str_list = {}

 15     string.gsub(str, '[^' .. reps ..']+', function(w) 

 16             table.insert(str_list, w) 

 17         end)

 18     return str_list

 19 end

 20 

 21 function c.c2t(content, type, ...)

 22     if type == c.t.kv then

 23         return c.c2t_kv(content, ...)

 24     elseif type == c.t.ini then

 25         return c.c2t_ini(content, ...)

 26     elseif type == c.t.csv then

 27         return c.c2t_csv(content, ...)

 28     elseif type == c.t.classickv then

 29         return c.c2t_kv(content)

 30     end

 31     return "unsupport-format"

 32 end

 33 

 34 function c.c2t_kv(content, sep, l_sep)

 35     sep   = sep or "="

 36     l_sep = l_sep or "\r\n"

 37     

 38     local ret = {}

 39     for _, line in ipairs(lua_split(content, l_sep)) do

 40         local k,v = line:match('^([%w_]+)%s-' .. sep .. '%s-(.+)$')

 41         if k then

 42             if not v then

 43                 v = ""

 44             end

 45             if tonumber(v) then

 46                 v =tonumber(v)

 47             elseif v == "true" then

 48                 v = true

 49             elseif v == "false" then

 50                 v = false

 51             end

 52             ret[k] = v

 53         end

 54     end

 55     return ret

 56 end

 57 

 58 function c.c2t_classickv(content)

 59     return loadstring("return {" .. content .. "}")()

 60 end

 61 

 62 function c.c2t_ini(content, sl_sep, sr_sep, kv_sep, l_sep)

 63     sl_sep = sl_sep or "["

 64     sr_sep = sr_sep or "]"

 65     kv_sep = kv_sep or "="

 66     l_sep  = l_sep or "\r\n"

 67 

 68     local ret = {}

 69     local sec

 70     for _, line in ipairs(lua_split(content, l_sep)) do

 71         local section = line:match('^%' .. sl_sep ..  '([^%]]+)%' .. sr_sep .. '$')

 72         if section then

 73             sec = section

 74             ret[sec] = ret[sec] or {}

 75         end

 76 

 77         local k,v = line:match('^([%w_]+)%s-' .. kv_sep .. '%s-(.+)$')

 78         if k and v then

 79             if tonumber(v) then

 80                 v = tonumber(v)

 81             elseif v == "true" then

 82                 v = true

 83             elseif v == "false" then

 84                 v = false

 85             end

 86 

 87             if sec then

 88                 ret[sec][k] = v

 89             end

 90         end

 91     end

 92 

 93     return ret

 94 end

 95 

 96 function c.c2t_csv(content, sep, l_sep)

 97     sep   = sep or ","

 98     l_sep = l_sep or "\r\n"

 99 

100     local ct = lua_split(content, l_sep)

101     local headers = lua_split(ct[1], sep)

102     table.remove(ct, 1)

103 

104     local ret = {}

105     local n = 1

106     for _, line in ipairs(ct) do

107         local vks = lua_split(line, sep)

108         ret[n] = {}

109         for j =1, #headers do

110             ret[n][headers[j]] = vks[j]

111         end

112         n = n + 1

113     end

114 

115     return ret

116 end

117 

118 function c.c2s(t, type, ...)

119     if type == c.t.kv then

120         return c.c2s_kv(t, ...)

121     elseif type == c.t.ini then

122         return c.c2s_ini(t, ...)

123     elseif type == c.t.csv then

124         return c.c2s_csv(t, ...)

125     elseif type == c.t.classickv then

126         return c.c2s_kv(t)

127     end    

128     return "unsupport-format"

129 end

130 

131 function c.c2s_kv(t, sep, l_sep)

132     sep   = sep or "="

133     l_sep = l_sep or "\r\n"

134     local content = ""

135     for k, v in pairs(t) do

136         content = content .. tostring(k) .. sep .. tostring(v) .. l_sep  

137     end

138     return content

139 end

140 

141 function c.c2s_ini(t, sl_sep, sr_sep, kv_sep, l_sep)

142     sl_sep = sl_sep or "["

143     sr_sep = sr_sep or "]"

144     kv_sep = kv_sep or "="

145     l_sep  = l_sep or "\r\n"

146 

147     local content = ""

148     for s, kv in pairs(t) do

149         content = content .. sl_sep .. tostring(s) .. sr_sep .. l_sep 

150         for k, v in pairs(kv) do

151             content = content .. tostring(k) .. kv_sep .. tostring(v) .. l_sep 

152         end

153     end

154     return content

155 end

156 

157 function c.c2s_csv(t, sep, l_sep)

158     sep   = sep or ","

159     l_sep = l_sep or "\r\n" 

160 

161     local content = "" 

162     local header = ""

163     for index, kv in ipairs(t) do

164         for k, v in pairs(kv) do

165             if index == 1 then

166                 header = header .. tostring(k) .. sep                 

167             end

168             content = content .. tostring(v) .. sep

169         end

170         content = content .. l_sep

171     end

172 

173     return l_sep .. header .. l_sep .. content

174 end

175 

176 return c
convert.lua

 

 1 -- 小岩<[email protected]>

 2 -- 2015-5-26

 3 local fu       = require "fw.util.fileutil"

 4 local convert = require "fw.util.convert"

 5 local kv = class("kv")

 6 

 7 function kv:ctor(filename, ...)

 8     self.filename_ = filename

 9     self.extra_cfg_ = {...}

10     self:init_with_file()

11 end

12 

13 function kv:copy()

14     return clone(self)

15 end

16 

17 function kv:init_with_file()

18     assert(self.filename_ and type(self.filename_) == "string", 

19         string.format("ini assert error: init_with_file() - invalid param %s", self.filename_))

20     local file_content = fu.get_string(self.filename_)

21     self.props_ = convert.c2t(file_content, convert.t.kv, unpack(self.extra_cfg_))

22 end

23 

24 function kv:get(k)

25     assert(k and type(k) == "string",

26         string.format("ini assert error: get() - invalid param %s", k))

27     return self.props_[k]

28 end

29 

30 function kv:update(k, nv)

31     local ov = self.props_[k]

32     self.props_[k] = nv

33     return ov

34 end

35 

36 function kv:save_2_path(new_filepath)

37     local old_filepath = self.filename_

38     local content = convert.c2s(self.props_, convert.t.kv, unpack(self.extra_cfg_))

39     if fu.write_content(new_filepath, content) then

40         self.filename_ = new_filepath

41         return old_filepath

42     end

43     return nil

44 end

45 

46 function kv:save()

47     local content = convert.c2s(self.props_, convert.t.kv, unpack(self.extra_cfg_))

48     if fu.write_content(self.filename_, content) then

49         return true

50     end

51     return false

52 end

53 

54 return kv
kv.lua

 

 1 --小岩<[email protected]>

 2 --2015-5-26

 3 local fu        = require "fw.util.fileutil"

 4 local convert = require "fw.util.convert"

 5 local classickv = class("classickv")

 6 

 7 function classickv:ctor(filename)

 8     self.filename_  = filename

 9     self:init_with_file() 

10 end

11 

12 function classickv:copy()

13     return clone(self)

14 end

15 

16 function classickv:init_with_file()

17     assert(self.filename_ and type(self.filename_) == "string", 

18         string.format("ini assert error: init_with_file() - invalid param %s", self.filename_))

19 

20     local file_content = fu.get_string(self.filename_)

21     self.props_ = convert.c2t(file_content, convert.t.classickv)

22 end

23 

24 function classickv:get(k)

25     assert(k and type(k) == "string",

26         string.format("ini assert error: get() - invalid param %s", k))

27     return self.props_[k]

28 end

29 

30 function classickv:update(k, nv)

31     local ov = self.props_[k]

32     self.props_[k] = nv

33     return ov

34 end

35 

36 function classickv:save_2_path(new_filepath)

37     local old_filepath = self.filename_

38     local content = convert.c2s(self.props_, convert.t.classickv)

39     if fu.write_content(new_filepath, content) then

40         self.filename_ = new_filepath

41         return old_filepath

42     end

43     return nil

44 end

45 

46 function classickv:save()

47     local content = convert.c2s(self.props_, convert.t.classickv)

48     if fu.write_content(self.filename_, content) then

49         return true

50     end

51     return false

52 end

53 

54 return classickv
classickv.lua

 

-- 小岩<[email protected]>

-- 2015-5-25

local fu        = require "fw.util.fileutil"

local convert = require "fw.util.convert" 

local ini = class("ini")



function ini:ctor(filename, ...)

    self.filename_ = filename or nil

    self.extra_cfg_ = {...}

    self:init_with_file()

end



function ini:copy()

    return clone(self)

end



function ini:init_with_file()

    assert(self.filename_ and type(self.filename_) == "string", 

        string.format("ini assert error: init_with_file() - invalid param %s", self.filename_))



    local file_content = fu.get_string(self.filename_)

    self.props_ = convert.c2t(file_content, convert.t.ini, unpack(self.extra_cfg_))

end



function ini:get(s, k)

    assert(s and type(s) == "string",

        string.format("ini assert error: get() - invalid param %s", s))

    assert(k and type(k) == "string",

        string.format("ini assert error: get() - invalid param %s", k))



    if self.props_[s] then

        return self.props_[s][k]

    else

        return nil

    end

end



function ini:update(s,k,nv)

    if not self.props_[s] then

        self.props_[s] = {}

    end

    local ov = self.props_[s][k]

    self.props_[s][k] = nv

    return ov

end



function ini:save_2_path(new_filepath)

    local old_filepath = self.filename_

    local content = convert.c2s(self.props_, convert.t.ini, unpack(self.extra_cfg_))

    if fu.write_content(new_filepath, content) then

        self.filename_ = new_filepath

        return old_filepath

    end

    return nil

end



function ini:save()

    local content = convert.c2s(self.props_, convert.t.ini, unpack(self.extra_cfg_))

    if fu.write_content(self.filename_, content) then

        return true

    end

    return false

end



return ini
ini.lua

 

 1 -- 小岩<[email protected]>

 2 -- 2015-5-25

 3 local fu        = require "fw.util.fileutil"

 4 local convert = require "fw.util.convert"

 5 local csv = class("csv")

 6 

 7 function csv:ctor(filename, ...)

 8     self.filename_ = filename

 9     self.extra_cfg_ = {...}

10     self:init_with_file()

11 end

12 

13 function csv:copy()

14     return clone(self)

15 end

16 

17 function csv:init_with_file()

18     assert(self.filename_ and type(self.filename_) == "string", 

19         string.format("ini assert error: init_with_file() - invalid param %s", self.filename_))

20 

21     local file_content = fu.get_string(self.filename_)

22     self.props_ = convert.c2t(file_content, convert.t.csv, unpack(self.extra_cfg_))

23 end

24 

25 function csv:get(n, k)

26     if self.props_[n] then

27         return self.props_[n][k]

28     else

29         return nil

30     end

31 end

32 

33 function csv:update(n, k, nv)

34     if not self.props_[n] then

35         return nil

36     end

37     local ov = self.props_[n][k]

38     self.props_[n][k] = nv

39     return ov

40 end

41 

42 function csv:save_2_path(new_filepath)

43     local old_filepath = self.filename_

44     local content = convert.c2s(self.props_, convert.t.csv, unpack(self.extra_cfg_))

45     if fu.write_content(new_filepath, content) then

46         self.filename_ = new_filepath

47         return old_filepath

48     end

49     return nil

50 end

51 

52 function csv:save()

53     local content = convert.c2s(self.props_, convert.t.csv, unpack(self.extra_cfg_))

54     if fu.write_content(self.filename_, content) then

55         return true

56     end

57     return false

58 end

59 

60 return csv
csv.lua

 

我在每一个针对配置文件的操作oop实现table中都提供了从文件读取以及持久化到文件的方法.不过如果使用lua sytax方式的classic.那么在持久化的时候并不能如期的解析table,这也是当初我没有注意到的问题,不过后来我想了一下,如果是需要持久化的数据,那么我都会使用基本数据类型.所以这个不会影响我的使用.好的,另外一点需要注意的是,读取文件的接口我并没有使用lua的io接口,这是因为lua默认还是有环境变量的,不能够读取apk压缩包中的配置,所以我还是使用cc.fileutils中的接口.

 

好的,早上总结了一下昨天完成的内容. 接下来考虑实现那一块先.

 

你可能感兴趣的:(cocos2dx)