cocos2dx lua繼承C++類

這段時間用lua在做一個項目,用cocos2dx爲基礎來開發,採用lua腳本語言爲核心語言。但是對lua幾乎零基礎的我,處處碰壁。首先瞭解到lua一般是用面向過程的方式來寫腳本,並且看到cocos2dx裏的lua sample幾乎都是用的面向過程的方式來寫的,但是我還是比較熟悉C++的面向對象的方式來寫。

先是研究到lua通過元表的方式可以模擬面向對象的編程方式,但在網上多數的資料都是子類繼承lua寫的基類,而cocos2dx卻要繼承C++的類,所以cocos2dx裏的extern.lua就派上用場了,它裏面編寫了lua繼承C++類的模板,直接調用class函數就可以實現繼承cocos2dx裏C++類。

extern.lua保存在cocos2dx的cocos2d-x-2.2.1\samples\Lua\TestLua\Resources\luaScript\extern.lua。

以下簡單寫寫試用方式:

 

require "luaScript/extern.lua"

local Login = class("Login",
	function()
		return CCLayer:create()
	end
)

function Login:create()
	local ret = Login.new()
	ret:init()
	return ret
end

function Login:init()
	--添加需要的初始化腳本
	
end


然後就可以用local login = Login:create()來創建以上的子類了。

 

 

但是隨着功能的增加發現又要重寫C++父類的方法,該怎麼寫呢,又在網上一通查找,可以沒發現幾個真正能用的方式。最後還是發現了一個blog寫的實現了這樣的功能。鏈接地址是http://www.litefeel.com/lua-override-userdata/。實際上早有發現這樣個blog,但是當時沒看明白就忽略了,後來再次發現的時候,茅塞頓開。這裏簡單寫下我的使用方式,以上鍊接的blog寫了幾種實現的方式,各有利弊。

方法一:

 

local _setVisible = nil
local MyLayer = class("MyLayer", function()
    local layer = CCLayer:create()
    -- save c++ member method point.
    _setVisible = layer.setVisible
    return layer
end)
-- override CCLayer::setVisible
function MyLayer:setVisible(visible)
    -- invoke CCLayer::setVisible
    _setVisible(self, visible)
    -- to do something.
end

以上方法一雖然是作者說的最優的方法,但是總感覺這樣寫很彆扭。而且懷疑實例化以上多個類時,_setVisible這個變量是不是被所有實例化的類共享的,比較懶一直沒去證實。 

 

方法二:

 

local MyLayer = class("MyLayer", function()
    return CCLayer:create()
end)
-- override CCLayer::setVisible
function MyLayer:setVisible(visible)
    -- invoke CCLayer::setVisible
    getmetatable(self).setVisible(self, visible)
    -- to do something.
end

此方法二雖然實現很簡潔,但是經測試,以上的方式只能繼承C++的直接父類,父類的父類是不能繼承的。我也很喜歡這中實現方式,但很遺憾,不是所有情況都能用。

 

 

然後繼承了C++的父類,怎麼添加lua類裏自己的成員變量呢,網上大多數都是這樣寫的:

require "extern"
  
MySprite = class("MySprite", 
    function(fileName) 
        return CCSprite:create(fileName)  
    end 
) 
  
MySpriteMySprite.__index = MySprite
  
MySprite.type = 0
  
function MySprite:createMS(fileName,_type)
    local mySprite = MySprite.new(fileName) 
    mySprite:myInit(_type) 
    return mySprite 
end 
  
function MySprite:myInit(_type)
    self.type =_type 
end 

但是經使用發現,以上的方法 MySprite.type = 0 這個成員變量是被所有實例化的lua類共享的,所有此種方式對於實例化一次的類來說使用不影響,但如果多次實例化就出現問題了。經過多次研究測試後發現以下這樣寫就可以被多次實例化:

 

 

require "extern"

MySprite = class("MySprite",
    function(fileName)
        return CCSprite:create(fileName)
    end
)

function MySprite:createMS(fileName,_type)
    local mySprite = MySprite.new(fileName)
    mySprite.type = 0
    mySprite:myInit(_type)
    return mySprite
end
  
function MySprite:myInit(_type)
    self.type =_type
end


可能剛開始接觸lua的時候看到過這樣的說法,self類似於C++裏的this,大概可以這樣理解,但並不是完全一樣。self.var裏的self是指當前var所屬於的table,與直接使用Table.var是不一樣的(這裏的Table是指定義的table變量名)。

 

 

以上都是自己在使用lua過程中,對lua的一些結論和認識,如有發現問題,歡迎指正和討論。

 

最後給自己寫的小遊戲打下廣告,一個釋放你壓力的小遊戲,一個你敢叫它敢動的小遊戲。敢不敢來試下?

點擊下載,或在 Google Play Store 搜索 Make a Noise

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章