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

时间: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应用的简介就结束啦。免费下载代码

cocos2dx之lua项目开发中MVC框架的简单应用的更多相关文章

  1. 分析cocos2d-x的lua项目中的工具方法

    在创建完cocos2d-x的lua项目后.打开项目的Resources中的extern.lua文件.里面有两个用于面向对象的方法.一个是用于克隆,一个是用于继承. 代码分析例如以下 --克隆一个对象 ...

  2. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  3. PHP做Web开发的MVC框架(Smarty使用说明 )

    PHP做Web开发的MVC框架(Smarty使用说明 ) 一.Smarty简明教程 1.安装演示 下载最新版本的Smarty-3.1.12,然后解压下载的文件.接下来演示Smarty自带的demo例子 ...

  4. MyBatis 项目开发中是基于 XML 还是注解?

    只要你对 MyBatis 有所认识和了解,想必知道 MyBatis 有两种 SQL 语句映射模式,一种是基于注解,一种是基于XML. 基于 XML <mapper namespace=" ...

  5. Java项目开发中实现分页的三种方式一篇包会

    前言   Java项目开发中经常要用到分页功能,现在普遍使用SpringBoot进行快速开发,而数据层主要整合SpringDataJPA和MyBatis两种框架,这两种框架都提供了相应的分页工具,使用 ...

  6. 团队项目开发中,常见的版本控制有svn,git

    团队项目开发中,常见的版本控制有svn,git

  7. Angular 项目开发中父子组件传参

    在项目开发中经常会遇到 组件之间传参的问题.今天总结下在使用angular的项目中父子组件传参的问题: 1.父组件向子组件传参: 然后在父组件中 然后在父组件的html中 然后就可以在子组件中使用了 ...

  8. 《Maven在Java项目开发中的应用》论文笔记(十七)

    标题:Maven在Java项目开发中的应用 一.基本信息 时间:2019 来源:山西农业大学 关键词:Maven:Java Web:仓库:开发人员:极限编程; 二.研究内容 1.Maven 基本原理概 ...

  9. 炼金术(1): 识别项目开发中的ProtoType、Demo、MVP

    软件开发是很分裂的,只有不断使用原则和规律,才能带来质量. 只要不是玩具性质的项目,项目应该可以大概划分为0-1,1-10,10-100,100-1000四个种重要阶段.其中,0-1是原型验证性的:1 ...

随机推荐

  1. 基于visual Studio2013解决C语言竞赛题之0710排序函数

     题目

  2. linux i2c驱动架构-dm368 i2c驱动分析

      linux i2c驱动架构-dm368 i2c驱动分析   在阅读本文最好先熟悉一种i2c设备的驱动程序,并且浏览一下i2c-core.c以及芯片提供商的提供的i2c总线驱动(i2c-davinc ...

  3. 使用链表实现队列------《数据结构与算法分析-C语言描述》

    经过ubuntu的gcc验证 一.头文件 que_link.h #ifndef _QUE_LINK_H_ #define _QUE_LINK_H_ struct que_record; typedef ...

  4. Swift学习笔记十三:继承

    一个类能够继承(inherit)还有一个类的方法(methods),属性(property)和其他特性 一.基本的语法 class Human{ var name :String init(){ na ...

  5. 【linux kernel】 softirq 软中断讨论

    欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...

  6. 用c#开发微信(10) JSSDK 基本用法 分享接口“发送到朋友”

    微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包.通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享. ...

  7. CF 319D(Have You Ever Heard About the Word?-模拟)

    D. Have You Ever Heard About the Word? time limit per test 6 seconds memory limit per test 256 megab ...

  8. 关于innodb purge thread和master thread

    由innodb_purge_threads控制purge线程数. (>= 5.6.5)的版本号中该值默觉得1.最大值为32.默认值1表示innodb的purge操作被分离到purge线程中,ma ...

  9. java web解决表单重复提交问题

    我们大家再进行web开发的时候,必不可少会遇见表单重复提交问题.今天就来给总结如何解决表单提交问题,欢迎大家交流指正. 首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提 ...

  10. 树后台数据存储(採用webmethod)

    树后台数据存储 关于后台数据存储将集中在此篇解说 /* *作者:方浩然 *日期:2015-05-26 *版本号:1.0 */ using System; using System.Collection ...