cocos2dx 3.10 版本提供了 cocos studio 界面导出到 lua 的功能,同时内置了一套基本的 MVC 框架。在此基础上进行代码改进,实现了以下几项功能:

  1. 无需手动填写 RESOURCE_BINDING 的内容。
  2. Button 自动根据 UI 名字绑定对应的函数。例如按钮命名为 btnClose,其单击事件会自动绑定到函数 ui_btnCloseClicked。只需在 cocostudio 中重命名按钮,再在 lua 脚本中添加对应的 ui_btnCloseClicked 函数即可。
  3. UI 元素自动绑定到 table 成员。例如有一个名为 txtTips 的元素,在 lua 脚本中可以直接使用 self.ui.txtTips:setString("11"),方便快速开发。

使用示例:添加一个新按钮的流程

  1. 在 cocostudio 中添加一个名为 btnNew 的按钮,并导出资源为 lua 格式。
  2. 在 MainScene.lua 中添加函数 ui_btnNewClicked,该函数即为按钮点击事件的回调。

重构后的代码

MainScene.lua

local t = class("MainScene", cc.load("mvc").ViewBase)
                
                t.RESOURCE_FILENAME = "res/MainScene.lua"
                t.RESOURCE_BINDING =
                {
                    -- ["Button_1"]={["varname"]="Button_1",["events"]={{["event"]="touch",["method"]="onBtnTouch"}}},
                    --  ["Text_1"] = {["varname"] = "txt_info"},
                    -- ["Panel"] = {["varname"] = "Panel"},
                };
                
                function t:onCreate()
                    printf("resource node = %s", tostring(self:getResourceNode()))
                end
                
                function t:ui_btnCloseClicked()
                    print("  close");
                end
                
                function t:ui_btnSendClicked()
                    print("  send");
                    self.counter =(self.counter and self.counter + 1) or 0;
                    self.ui.txtInfo:setString("12344 " .. self.counter);
                end
                
                function t:ui_Panel_Panel2_btnShowClicked()
                    print("  pp show");
                end
                
                function t:ui_Panel_btnShowClicked()
                    print("show   " .. self.counter);
                end
                
                return t

ViewBase.lua

function ViewBase:ctor(app, name)
                    self:enableNodeEvents()
                    self.app_ = app
                    self.name_ = name
                
                    -- check CSB resource file
                    local res = rawget(self.class, "RESOURCE_FILENAME")
                    if res then
                        self:createResoueceNode(res)
                    end
                
                    local binding = rawget(self.class, "RESOURCE_BINDING")
                    if res and binding then
                        self:createResoueceBinding(binding)
                    end
                
                    if self.onCreate then self:onCreate() end
                    self.ui = { };
                    self.ui.root = self.resourceNode_;
                    self:autoBind(self.resourceNode_);
                end
                
                function ViewBase:getFullParentName(node)
                    local parent = "";
                    if node and node ~= self.ui.root then
                        local tmp = node;
                        while tmp:getParent() ~= self.ui.root do
                            parent = tmp:getParent():getName() .. "_" .. parent;
                            tmp = tmp:getParent();
                        end
                    end
                    return parent;
                end
                
                function ViewBase:autoBind(node)
                    for _, v in pairs(node:getChildren()) do
                        print(v:getName());
                        local node_name = v:getName();
                
                        if string.find(node_name, "btn") then
                            -- bind button
                            v:onTouch( function(e)
                                if e.name == "ended" then
                                    local name = self:getFullParentName(v) .. node_name .. "Clicked";
                                    local cb = self["ui_" .. name];
                                    if cb then
                                        cb(self);
                                    else
                                    end
                
                                end
                            end );
                        end
                        self.ui[self:getFullParentName(v) .. node_name] = v;
                        -- bind var
                        self:autoBind(v);
                        -- bind child
                    end
                end