转载于:http://www.2cto.com/kf/201504/386984.html
最近的游戏项目中使用了lua脚本来开发,项目中用到了MVC框架,最近有朋友问我怎么弄,在这里简单分享一下思路和一些开发中的技巧。
先简单说说MVC,即Model View Controller。Model(模型),一般负责数据的处理;View(视图),一般负责界面的显示;Controller(控制器),一般负责前端的逻辑处理。拿一款手机游戏来说,界面UI的显示、布局等就是View负责;点击了按钮,手势的滑动等操作由Controller来处理;游戏中需要的数据资源就交给Model。
接下来,看看在游戏开发中怎么用,这里用Lua(环境使用cocos code ide)给大家说说。
先来看看项目的目录结构:
其中cocos、Controller、Model、View这个不用多说,Event里面保存的全局消息类型,Managers是用于管理游戏中的东东的,比如管理资源,管理各种场景切换,层的切换等等。Utilities提供一些工具类,比如字符串的处理等。大家也可以根据自己的需求来定制目录,比如定义一个NetCenter文件夹,专门用于处理网络的。本例子中没有用到数据操作和工具类,所以这两个文件夹为空。
我们以游戏的运行流程为线索来展开说明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
local function main()
@H_404_80@
collectgarbage(collect)
@H_404_80@-- avoid memory leak
@H_404_80@collectgarbage(setstepmul,0)!important">5000
)
@H_404_80@-- initialize director
@H_404_80@local director = cc.Director:getInstance()
@H_404_80@--turn on display FPS
@H_404_80@
@H_404_80@cc.Director:getInstance():getOpenGLView():setDesignResolutionSize(
320
,0)!important">480
1
)
@H_404_80@
@H_404_80@--create scene
@H_404_80@local scene = require(GameScene)
@H_404_80@local gameScene = scene:startGame()
end
|
我们最后调用了GameScene类中的startGame函数,来看看GameScene这个类:
require(Managers.SceneManager)
require(Managers.LayerManager)
local GameScene =
class
(GameScene)
local scene = nil
function GameScene:startGame()
@H_404_80@--初始化
@H_404_80@scene = cc.Scene:create()
@H_404_80@cc.Director:getInstance():replaceScene(scene)
else
@H_404_80@cc.Director:getInstance():runWithScene(scene)
@H_404_80@end
@H_404_80@SceneManager:initLayer(scene)
@H_404_80@self:enterGame()
end
function GameScene:enterGame()
@H_404_80@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)
很简单,按顺序初始化了三个空Layer。再来看看LayerManager管理器:
23
24
25
@H_125_404@
26
27
28
29
30
31
32
--Layer管理器
LayerManager = {}
LAYER_TYPE_MAIN = LAYER_TYPE_MAIN
local curLayer = nil
function LayerManager:
new
(o)
@H_404_80@o = o or {}
@H_404_80@self.__index = self
@H_404_80@ o
end
function LayerManager:getInstance()
@H_404_80@ self.instance == nil then
@H_404_80@self.instance = self:
()
@H_404_80@end
@H_404_80@
@H_404_80@ self.instance
end
function LayerManager:gotoLayerByType(type)
@H_404_80@ curLayer ~= nil then
@H_404_80@curLayer:destroy()
@H_404_80@end
@H_404_80@
@H_404_80@ type == LAYER_TYPE_MAIN then
@H_404_80@local layer = require(Controller.MainLayerController):create()
@H_404_80@curLayer = layer
@H_404_80@end
function MainLayerC:create()
@H_404_80@local layer = MainLayerC:
()
@H_404_80@ layer
end
function MainLayerC:ctor()
@H_404_80@self:createUI()--创建界面
end
function MainLayerC:createUI()
@H_404_80@local layer = require(View.MainLayerView)
@H_404_80@self.mainLayer = layer:createUI()
@H_404_80@gameLayer:addChild(self.mainLayer)
这里我们又发现了MVC中的View,在createUI函数中,我们调用了类MainLayerView的createUI函数,并将其添加到场景的游戏层中。我们来看看MainLayerView这个类。
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@H_502_644@local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
local MainLayerV =
(MainLayerView,function()
@H_404_80@ cc.Layer:create()
end)
function MainLayerV:createUI()
@H_404_80@local mainLayer = MainLayerV:
()
@H_404_80@ mainLayer
end
function MainLayerV:ctor()
@H_404_80@self:initUI()
end
function MainLayerV:initUI()
@H_404_80@local winSize = cc.Director:getInstance():getWinSize()
@H_404_80@self.bg = cc.Sprite:create(ResManager.main_bg)
@H_404_80@self:addChild(self.bg)
@H_404_80@
@H_404_80@local function menuCallback(tag,menuItem)
@H_404_80@local event = cc.EventCustom:
(EVENT_CLICK_MENU_MAIN)
@H_404_80@event._usedata = tag
@H_404_80@eventDispatcher:dispatchEvent(event)
@H_404_80@self.btnItem1 = cc.MenuItemImage:create(ResManager.main_btn1,ResManager.main_btn1,ResManager.main_btn1)
@H_404_80@self.btnItem1:setTag(
)
@H_404_80@self.btnItem1:registerScriptTapHandler(menuCallback)
@H_404_80@
@H_404_80@self.btnItem2 = cc.MenuItemImage:create(ResManager.main_btn2,ResManager.main_btn2)
@H_404_80@self.btnItem2:setPosition(winSize.width /
)
@H_404_80@self.btnItem2:setTag(
)
@H_404_80@self.btnItem2:registerScriptTapHandler(menuCallback)
@H_404_80@
@H_404_80@self.btnItem3 = cc.MenuItemImage:create(ResManager.main_btn3,ResManager.main_btn3)
@H_404_80@self.btnItem3:setTag(
)
@H_404_80@self.btnItem3:registerScriptTapHandler(menuCallback)
@H_404_80@
@H_404_80@self.menu = cc.Menu:create(self.btnItem1,self.btnItem2,self.btnItem3)
@H_404_80@self:addChild(self.menu)
end
MainLayerV
可以看到,我们在主界面中添加了一张背景图和三个按钮。我们是通过资源管理器ResManager来管理游戏中的素材的,ResManager文件很简单:
--资源管理器
ResManager = {}
--主界面
ResManager.main_bg = bg_big.png
ResManager.main_btn1 = cell.png
ResManager.main_btn2 = cell2.png
ResManager.main_btn3 = cell3.png
这样做的好处是,如果图片改了名字或者换了路径等,只需要在这里改一次就可以了。
可以看到我们给三个按钮注册了响应函数menuCallback,在这个函数中,就是MVC中的V和C之间的“沟通”了。我们定义了一个自定义事件EVENT_CLICK_MENU_MAIN,并给这个事件添加了一个附带参数_usedata,这个参数保存的是三个按钮的tag。然后将这个事件发送给他的监听者。这里大家应该明白了,我们在对应的Controller中注册了EVENT_CLICK_MENU_MAIN的监听,但有这个事件发过来时,我们就响应。根据事件携带的参数_usedata,我们就知道了在View中,玩家点击了哪个按钮,这样做的好处是,保证了每个界面只有一个消息,我们只需要根据这个消息携带的附加参数来判断具体的事件,从而减少了消息个数,这样有助于游戏的效率。另外,我们在响应这个消息的时候,也会做一定的优化,来看看类MainLayerController的响应函数:
21
function MainLayerC:addBtnEventListener()
@H_404_80@--按钮事件处理
@H_404_80@local function eventBtnListener(event)
@H_404_80@local eventNum = event._usedata
@H_404_80@[
] = function()
@H_404_80@print(Btn one)
@H_404_80@end,
@H_404_80@] = function()
@H_404_80@print(Btn two)
@H_404_80@] = function()
@H_404_80@print(Btn three)
@H_404_80@}
@H_404_80@[eventNum]()
@H_404_80@end
@H_404_80@self._eventBtnListener = cc.EventListenerCustom:create(EVENT_CLICK_MENU_MAIN,eventBtnListener)
@H_404_80@eventDispatcher:addEventListenerWithSceneGraPHPriority(self._eventBtnListener,self.mainLayer)
可以看到实际情况,我们并不需要对传递过来的参数进行判断,而是定义了一个函数数组,直接根据下标来调用对应的消息响应。之后继续通过各种管理器来对游戏内容进行变化,方式和MainLayerController和MainLayerView差不多。
猜你在找的Cocos2d-x相关文章