一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Lua - lua開發中實現MVC框架的簡單應用

lua開發中實現MVC框架的簡單應用

2020-04-21 11:09hebedich Lua

最近的游戲項目中使用了lua腳本來開發,項目中用到了MVC框架,最近有朋友問我怎么弄,在這里簡單分享一下思路和一些開發中的技巧。有需要的小伙伴可以參考下。

       先簡單說說MVC,即Model View Controller。Model(模型),一般負責數據的處理;View(視圖),一般負責界面的顯示;Controller(控制器),一般負責前端的邏輯處理。拿一款手機游戲來說,界面UI的顯示、布局等就是View負責;點擊了按鈕,手勢的滑動等操作由Controller來處理;游戲中需要的數據資源就交給Model。

       接下來,看看在游戲開發中怎么用,這里用Lua(環境使用cocos code ide)給大家說說。

       先來看看項目的目錄結構:

lua開發中實現MVC框架的簡單應用

        其中cocos、Controller、Model、View這個不用多說,Event里面保存的全局消息類型,Managers是用于管理游戲中的東東的,比如管理資源,管理各種場景切換,層的切換等等。Utilities提供一些工具類,比如字符串的處理等。大家也可以根據自己的需求來定制目錄,比如定義一個NetCenter文件夾,專門用于處理網絡的。本例子中沒有用到數據操作和工具類,所以這兩個文件夾為空。

        我們以游戲的運行流程為線索來展開說明。

        運行項目,進入到main.lua文件,來看看main函數:

?
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()
  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這個類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--場景管理器
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

       很簡單,按順序初始化了三個空Layer。再來看看LayerManager管理器:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
--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函數:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function MainLayerC:create()
  local layer = MainLayerC:new()
  return layer
end
 
function MainLayerC:ctor()
  self:createUI()--創建界面
  self:addBtnEventListener()--添加按鈕監聽
end
 
function MainLayerC:createUI()
  local layer = require("View.MainLayerView")
  self.mainLayer = layer:createUI()
  gameLayer:addChild(self.mainLayer)
end

       這里我們又發現了MVC中的View,在createUI函數中,我們調用了類MainLayerView的createUI函數,并將其添加到場景的游戲層中。我們來看看MainLayerView這個類。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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

        可以看到,我們在主界面中添加了一張背景圖和三個按鈕。我們是通過資源管理器ResManager來管理游戲中的素材的,ResManager文件很簡單:

?
1
2
3
4
5
6
7
8
--資源管理器
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的響應函數:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function MainLayerC:addBtnEventListener()
  --按鈕事件處理
  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應用的簡單介紹就結束啦,希望大家能夠喜歡本文,能夠對大家學習lua有所幫助。

延伸 · 閱讀

精彩推薦
  • LuaLua中的元方法__newindex詳解

    Lua中的元方法__newindex詳解

    這篇文章主要介紹了Lua中的元方法__newindex詳解,本文講解了查詢與更新、監控賦值、通過table給另一個table賦值等內容,需要的朋友可以參考下 ...

    笨木頭8872020-04-09
  • LuaLua中table庫函數方法介紹

    Lua中table庫函數方法介紹

    這篇文章主要介紹了Lua中table庫函數方法介紹,本文講解了concat、insert、maxn、remove、sort、foreachi等方法,需要的朋友可以參考下 ...

    腳本之家2502020-04-17
  • Lua深入探究Lua中的解析表達式

    深入探究Lua中的解析表達式

    這篇文章主要介紹了深入探究Lua中的解析表達式,對于其語法部分的說明和示例都超詳細,極力推薦此文!需要的朋友可以參考下 ...

    腳本之家3542020-05-05
  • LuaLua中計算、執行字符串中Lua代碼的方法

    Lua中計算、執行字符串中Lua代碼的方法

    這篇文章主要介紹了Lua中計算、執行字符串中Lua代碼的方法,類似JavaScript中eval函數的功能,在Lua中也可以實現,需要的朋友可以參考下 ...

    腳本之家6322020-04-30
  • LuaLua簡介、編譯安裝教程及變量等語法介紹

    Lua簡介、編譯安裝教程及變量等語法介紹

    這篇文章主要介紹了Lua簡介、編譯安裝教程及變量等語法介紹,本文同時講解了lua注釋語法、Lua命令行方式等內容,需要的朋友可以參考下 ...

    junjie3632020-04-14
  • LuaLua教程(二):基礎知識、類型與值介紹

    Lua教程(二):基礎知識、類型與值介紹

    這篇文章主要介紹了Lua教程(二):基礎知識、類型與值介紹,本文講解了Hello World程序、代碼規范、全局變量、類型與值等內容,需要的朋友可以參考下 ...

    腳本之家5922020-04-28
  • LuaLua實現__add方法重載示例

    Lua實現__add方法重載示例

    這篇文章主要介紹了Lua實現__add方法重載示例,本文直接給出實現代碼,需要的朋友可以參考下 ...

    腳本之家7452020-04-24
  • LuaLua和C語言的交互詳解

    Lua和C語言的交互詳解

    這篇文章主要介紹了Lua和C語言的交互詳解,Lua和C語言通過棧完成交互,本文結合代碼實例詳細講解了交互的方法,需要的朋友可以參考下 ...

    果凍想3702020-04-14
主站蜘蛛池模板: 国产区成人精品视频 | 女人国产香蕉久久精品 | 久久理论片迅播影院一级 | 冰漪丰满大乳人体图片欣赏 | 亚洲欧美优优色在线影院 | 国偷盗摄自产福利一区在线 | 久久re视频精品538在线 | 欧美a在线 | 紧身牛仔裤美女被啪啪久久网 | 果冻传媒 天美 麻豆 | 日本黄色大片免费观看 | 日本中文字幕在线观看视频 | 成人啪啪漫画羞羞漫画www网站 | 亚洲欧美一区二区三区在饯 | 91香蕉小视频 | 日韩视频在线精品视频免费观看 | 菠萝视频5正版在线观看 | 国产成人在线视频播放 | 欧美一卡二卡科技有限公司 | 超逼网 | 激情影院免费 | 久久伊人久久 | 国产精品成人一区二区 | 午夜精品区 | 国产三级精品久久三级国专区 | 天堂网在线网站成人午夜网站 | 午夜久久免费视频 | 免费观看大片毛片 | 公交车上插入 | 女张腿男人桶羞羞漫画 | 国产香蕉一区二区在线网站 | 91制片厂制作果冻传媒2021 | 男人女人性生活视频 | 天天天综合网 | 无码人妻精品一区二区蜜桃在线看 | 91制片厂制作传媒免费版樱花 | 逼123 | 国产在线成人精品 | 好大好爽好舒服视频 | 高清在线一区二区 | 好大好长好紧爽免费 |