zoukankan      html  css  js  c++  java
  • cocos2dx之lua项目开发中MVC框架的简单应用

    ****************************************************************************

    时间:2015-03-31

    作者:Sharing_Li

    转载注明出处:http://blog.csdn.net/sharing_li/article/details/44658317

    ****************************************************************************

           近期的游戏项目中使用了lua脚本来开发,项目中用到了MVC框架,近期有朋友问我怎么弄。在这里简单分享一下思路和一些开发中的技巧。 

           先简单说说MVC,即Model View Controller。Model(模型),一般负责数据的处理。View(视图)。一般负责界面的显示。Controller(控制器),一般负责前端的逻辑处理。拿一款手机游戏来说,界面UI的显示、布局等就是View负责;点击了button,手势的滑动等操作由Controller来处理;游戏中须要的数据资源就交给Model。 

           接下来,看看在游戏开发中怎么用,这里用Lua(环境使用cocos code ide)给大家说说。

           先来看看项目的文件夹结构:

            当中cocos、Controller、Model、View这个不用多说,Event里面保存的全局消息类型,Managers是用于管理游戏中的东东的。比方管理资源,管理各种场景切换。层的切换等等。Utilities提供一些工具类,比方字符串的处理等。大家也能够依据自己的需求来定制目录,比方定义一个NetCenter目录,专门用于处理网络的。

    本样例中没实用到数据操作和工具类。所以这两个目录为空。

            我们以游戏的执行流程为线索来展开说明。

            执行项目。进入到main.lua文件,来看看main函数:

    local function main()
        collectgarbage("collect")
        -- avoid memory leak
        collectgarbage("setpause", 100)
        collectgarbage("setstepmul", 5000)
    
        -- initialize director
        local director = cc.Director:getInstance()
    
        --turn on display FPS
        director:setDisplayStats(true)
    
        --set FPS. the default value is 1.0/60 if you don't call this
        director:setAnimationInterval(1.0 / 60)
        
        cc.Director:getInstance():getOpenGLView():setDesignResolutionSize(320, 480, 1)
        
        --create scene 
        local scene = require("GameScene")
        local gameScene = scene:startGame()
    
    end

            我们最后调用了GameScene类中的startGame函数,来看看GameScene这个类:

    require("Managers.SceneManager")
    require("Managers.LayerManager")
    
    local GameScene = class("GameScene")
    local scene = nil
    
    function GameScene:startGame()
        --初始化
    	scene = cc.Scene:create()
    	if cc.Director:getInstance():getRunningScene() then
            cc.Director:getInstance():replaceScene(scene)
    	else
    	    cc.Director:getInstance():runWithScene(scene)
    	end
    	SceneManager:initLayer(scene)
    	self:enterGame()
    end
    
    function GameScene:enterGame()
        LayerManager:getInstance():gotoLayerByType(LAYER_TYPE_MAIN)
    end
    
    return GameScene

           在startGame函数中,我们创建了一个空场景。然后调用SceneManager场景管理器来初始化场景。最后调用enterGame函数正式进入游戏主界面,当中enterGame函数中又有一个LayerManager层管理器。

    我们来看看这两个管理器是怎样工作的。先看看SceneManager:

    --场景管理器
    SceneManager = {}
    
    --背景层
    bgLayer = nil
    --游戏层
    gameLayer = nil
    --弹窗层
    panelLayer = nil
    
    function SceneManager:initLayer(scene)
    	bgLayer = cc.Layer:create()
    	scene:addChild(bgLayer)
    	
    	gameLayer = cc.Layer:create()
    	scene:addChild(gameLayer)
    	
    	panelLayer = cc.Layer:create()
    	scene:addChild(panelLayer)
    end

           非常easy,按顺序初始化了三个空Layer。再来看看LayerManager管理器:

    --Layer管理器
    LayerManager = {}
    
    LAYER_TYPE_MAIN = "LAYER_TYPE_MAIN"
    
    local curLayer = nil
    
    function LayerManager:new(o)
    	o = o or {}
    	setmetatable(o,self)
    	self.__index = self
    	return o
    end
    
    function LayerManager:getInstance()
    	if self.instance == nil then
    		self.instance = self:new()
    	end
    	
    	return self.instance
    end
    
    function LayerManager:gotoLayerByType(type)
        if curLayer ~= nil then
            curLayer:destroy()
        end
        
        if type == "LAYER_TYPE_MAIN" then
    		local layer = require("Controller.MainLayerController"):create()
    		curLayer = layer
    	end
    end
    

            看看gotoLayerByType这个函数,首先切换层的时候。看看当前层是否为空。不为空就删掉。然后依据传递过来的參数来推断要切换到哪个层。这里出现MVC中的Controller部分,看看是什么情况。这里调用了类MainLayerController中的create函数:

    function MainLayerC:create()
    	local layer = MainLayerC:new()
    	return layer
    end
    
    function MainLayerC:ctor()
        self:createUI()--创建界面
        self:addBtnEventListener()--加入button监听
    end
    
    function MainLayerC:createUI()
    	local layer = require("View.MainLayerView")
        self.mainLayer = layer:createUI()
    	gameLayer:addChild(self.mainLayer)
    end

           这里我们又发现了MVC中的View,在createUI函数中,我们调用了类MainLayerView的createUI函数,并将其加入到场景的游戏层中。我们来看看MainLayerView这个类。

    local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
    
    local MainLayerV = class("MainLayerView",function()
    	return cc.Layer:create()
    end)
    
    function MainLayerV:createUI()
    	local mainLayer = MainLayerV:new()
    	return mainLayer
    end
    
    function MainLayerV:ctor()
    	self:initUI()
    end
    
    function MainLayerV:initUI()
        local winSize = cc.Director:getInstance():getWinSize()
    	self.bg = cc.Sprite:create(ResManager.main_bg)
    	self.bg:setPosition(winSize.width / 2,winSize.height / 2)
    	self:addChild(self.bg)
    	
    	local function menuCallback(tag,menuItem)
            local event = cc.EventCustom:new(EVENT_CLICK_MENU_MAIN)
            event._usedata = tag
            eventDispatcher:dispatchEvent(event)
    	end
        
        self.btnItem1 = cc.MenuItemImage:create(ResManager.main_btn1,ResManager.main_btn1,ResManager.main_btn1)
        self.btnItem1:setPosition(winSize.width / 2,winSize.height / 3)
        self.btnItem1:setTag(1)
        self.btnItem1:registerScriptTapHandler(menuCallback)
        
        self.btnItem2 = cc.MenuItemImage:create(ResManager.main_btn2,ResManager.main_btn2)
        self.btnItem2:setPosition(winSize.width / 2,winSize.height / 2)
        self.btnItem2:setTag(2)
        self.btnItem2:registerScriptTapHandler(menuCallback)
        
        self.btnItem3 = cc.MenuItemImage:create(ResManager.main_btn3,ResManager.main_btn3)
        self.btnItem3:setPosition(winSize.width / 2,winSize.height / 3 * 2)
        self.btnItem3:setTag(3)
        self.btnItem3:registerScriptTapHandler(menuCallback)
        
        --创建菜单
        self.menu = cc.Menu:create(self.btnItem1,self.btnItem2,self.btnItem3)
        self.menu:setPosition(0,0)
        self:addChild(self.menu)
    end
    
    return MainLayerV


            能够看到,我们在主界面中加入了一张背景图和三个button。我们是通过资源管理器ResManager来管理游戏中的素材的。ResManager文件非常easy:

    --资源管理器
    ResManager = {}
    
    --主界面
    ResManager.main_bg = "bg_big.png"
    ResManager.main_btn1 = "cell.png"
    ResManager.main_btn2 = "cell2.png"
    ResManager.main_btn3 = "cell3.png"

           这样做的优点是,假设图片改了名字或者换了路径等。仅仅须要在这里改一次就能够了。

           能够看到我们给三个button注冊了响应函数menuCallback,在这个函数中。就是MVC中的V和C之间的“沟通”了。

    我们定义了一个自己定义事件EVENT_CLICK_MENU_MAIN,并给这个事件加入了一个附带參数_usedata,这个參数保存的是三个button的tag。然后将这个事件发送给他的监听者。这里大家应该明确了,我们在相应的Controller中注冊了EVENT_CLICK_MENU_MAIN的监听,但有这个事件发过来时。我们就响应。依据事件携带的參数_usedata,我们就知道了在View中。玩家点击了哪个button。这样做的优点是,保证了每一个界面仅仅有一个消息。我们仅仅须要依据这个消息携带的附加參数来推断详细的事件,从而降低了消息个数,这样有助于游戏的效率。另外,我们在响应这个消息的时候,也会做一定的优化,来看看类MainLayerController的响应函数:

    function MainLayerC:addBtnEventListener()
    	--button事件处理
    	local function eventBtnListener(event)
           local eventNum = event._usedata
    	   local switch = {
    	       [1] = function()
    	            print("Btn one")
    	       end,
    	       [2] = function()
                    print("Btn two")
    	       end,
    	       [3] = function()
                    print("Btn three")
    	       end
    	   }
    	   switch[eventNum]()
    	end
    	--注冊事件处理
    	self._eventBtnListener = cc.EventListenerCustom:create(EVENT_CLICK_MENU_MAIN,eventBtnListener)
        eventDispatcher:addEventListenerWithSceneGraphPriority(self._eventBtnListener,self.mainLayer)
    end

            能够看到实际情况,我们并不须要对传递过来的參数进行推断,而是定义了一个函数数组。直接依据下标来调用相应的消息响应。之后继续通过各种管理器来对游戏内容进行变化,方式和MainLayerController和MainLayerView差点儿相同。

            到这里,MVC应用的简介就结束啦。免费下载代码




     

     

  • 相关阅读:
    Ajax入门
    多线程入门(五)
    多线程入门(四)
    多线程入门(三)
    多线程入门(二)
    多线程入门(一)
    git使用简介
    Windows远程登录到VirtualBox安装的Ubuntu11.10
    阿里面试2(转)
    百度java开发面试题
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5125274.html
Copyright © 2011-2022 走看看