原文總結的很是好,都是咱們學cocos2d-x以來摸索過的東西,若是早有這篇文章就能少走很多彎路了,特此截屏保存。原文連接:http://shahdza.blog.51cto.com/2410787/1569003javascript
(原文中說的getPosition()那個大坑幸虧我沒踩上,我每次都是偷懶用getPositionX()和getPositionY()的,當時還奇怪爲啥cocos2d-x要封裝這個奇怪的兩個方法,哈哈)php
CC3.2+Lua(9) ——從C++過渡到Lua
2014-10-28 22:10:20
標籤:lua cocos2dx
原創做品,容許轉載,轉載時請務必以超連接形式標明文章 原始出處 、做者信息和本聲明。不然將追究法律責任。http://shahdza.blog.51cto.com/2410787/1569003java
【嘮叨】
如今開始學習Lua了,開始用 Cocos Code IDE 開發cocos2dx的遊戲了。
但是呢,由於 cocos2dx v3.x 剛剛纔出來不久,因此網上的教程大部分都是基於C++版本的,
而針對Lua版本的大部分都是老版本 v2.x 的教程,對於用 v3.x 的我來講,不少都不適用了。
無奈之下只好本身摸索,通過幾天的學習,積累了一些 Lua 與 C++ 開發cocos2dx遊戲之間的差別。
如今就在此總結一下。node
【番外】
Cocos2d-X官方就在2014年10月28日,發佈了 Cocos引擎v1.0 Preview版 。
將Cocos Studio、Cocos Code IDE、Cocos2d-X 三件套進行了集成,一鍵部署安裝。
看着實在是太酷炫了,這也說明使用腳本語言 Lua 開發cocos2dx遊戲必將愈加流行。sql
【從C++過渡到Lua】數組
一、Lua中如何使用cocos2dx引擎中的類?
在C++中是這樣調用的:bash
Sprite* sprite = Sprite::create(); sprite->setPosition(Vec2(100, 100));this->addChild(sprite);
而在Lua中是這樣調用的:ide
local sprite = cc.Sprite:create() sprite:setPosition(cc.p(100, 100)) self:addChild(sprite)
是否是很簡單?差異其實不是很大嘛!
Lua中使用引擎中的類,只要在前面多加個 cc. 便可。
而調用類的函數,不是雙冒號:: ,而是一個冒號: 。函數
二、Lua 與 C++ 使用上有何差別?
請耐心看完如下這個類,你或許會有基本上的瞭解。
PS:我比較懶,因此用代碼來代替文字描述了。學習
local winSize = cc.Director:getInstance():getWinSize()-- 繼承Layer類MenuLayer = class("MenuLayer", function() return cc.Layer:create() end) -- 初始化函數 function MenuLayer:ctor() self.name = "hello" -- 成員變量 self.size = cc.size(0, 0) -- 成員變量 end -- 建立包含GameLayer的場景 function MenuLayer:createScene() local scene = cc.Scene:create() local layer = MenuLayer:create() scene:addChild(layer) return scene end -- 建立GameLayer層 function MenuLayer:create() local layer = MenuLayer.new() -- new() layer:init() -- init() return layer end -- 初始化 function MenuLayer:init() self:ShowUI() -- 添加界面元素(Sprite、Label等) self:addBtn() -- 添加菜單按鈕 self:addTouches() -- 添加多點觸摸 end -- 添加界面 function MenuLayer:ShowUI() -- 背景圖片Sprite local bg = cc.Sprite:create("HelloWorld.png") bg:setPosition(cc.p(0, 0)) -- 設置位置 bg:setAnchorPoint(0, 0) -- 設置錨點 self:addChild(bg) -- 添加子節點 -- 添加文字 self.label = cc.Label:createWithSystemFont("debug","res/fonts/Marker Felt.ttf",30) self.label:setPosition(winSize.width/2, winSize.height/2) self:addChild(self.label) end -- 添加按鈕 function MenuLayer:addBtn() local menu local normal, hard -- 回調函數 -- tag 爲menuItem設置的標籤setTag ,menuItem爲相應對象 local function menuCallback(tag, menuItem) print("menuItem: " .. tag) -- Lua中的輸出語句 end normal = cc.MenuItemImage:create("normal.png", "normal.png") normal:setPosition(0, 120) normal:setTag(1) normal:registerScriptTapHandler(menuCallback) -- 按鈕事件 hard = cc.MenuItemImage:create("hard.png", "hard.png") hard:setPosition(0, 20) hard:setTag(2) hard:registerScriptTapHandler(menuCallback) -- 按鈕事件 -- 建立菜單,最後不須要加NULL menu = cc.Menu:create(normal, hard) self:addChild(menu) end -- 多點觸摸 function MenuLayer:addTouches() local touch1, touch2 = cc.Touch, cc.Touch local function onTouchesBegan(touches, event) print("Touches Began") touch1 = touches[1] -- 第一個觸點,下標從1開始 touch2 = touches[2] -- 第二個觸點 local pos1 = touch1:getLocation() -- 獲取觸點1的位置 local pos2 = touch2:getLocation() -- 獲取觸點2的位置 local delta = { x = pos2.x - pos1.x , y = pos2.y - pos1.y } print(delta.x .. " , " .. delta.y) -- 輸出log end local function onTouchesMoved(touches, event) print("Touches Moved") end local function onTouchesEnded(touches, event) print("Touches Ended") end -- 註冊多點觸摸 local dispatcher = cc.Director:getInstance():getEventDispatcher() local listener = cc.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(onTouchesBegan, cc.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(onTouchesMoved, cc.Handler.EVENT_TOUCHES_MOVED) listener:registerScriptHandler(onTouchesEnded, cc.Handler.EVENT_TOUCHES_ENDED) dispatcher:addEventListenerWithSceneGraphPriority(listener, self) end
三、Lua中的字符串格式轉換?
C++中是這樣使用的:
sprintf(str, "hero_%02d.png", i)
而在Lua中則是使用 string.format() 函數。
string.format("hero_%02d.png", i)
四、Lua中的枚舉類型
咱們都知道C++中的枚舉都改爲了強枚舉類型,形如 Control::State::NORMAL 。
而在Lua中將其變成形如:cc.CONTROL_STATE_NORMAL 。
估計你已經明白了吧?把全部字母都變成大寫,而後把雙冒號:: 變成下劃線 _ 便可。
下面列出一些我本身整理的常見枚舉類型在Lua中是如何使用的。
-- ResolutionPolicy 屏幕適配(就這個比較奇葩。。。)-- 含義參見:http://shahdza.blog.51cto.com/2410787/1550089cc.ResolutionPolicy.EXACT_FIT cc.ResolutionPolicy.FIXED_HEIGHT cc.ResolutionPolicy.FIXED_WIDTH cc.ResolutionPolicy.NO_BORDER cc.ResolutionPolicy.SHOW_ALL-- EventKeyboard::KeyCode 鍵盤按鍵枚舉類型(這個也比較奇葩。。。)-- 含義參見(鍵盤事件部分):http://shahdza.blog.51cto.com/2410787/1560222-- 鍵盤按鍵比較多,因此就羅列一部分cc.KeyCode.KEY_A cc.KeyCode.KEY_1 cc.KeyCode.KEY_F1 cc.KeyCode.KEY_SPACE cc.KeyCode.KEY_ALT cc.KeyCode.KEY_SHIFT-- Control::EventType 控件事件類型-- 含義參見:http://shahdza.blog.51cto.com/2410787/1543349cc.CONTROL_EVENTTYPE_TOUCH_DOWN cc.CONTROL_EVENTTYPE_DRAG_INSIDE cc.CONTROL_EVENTTYPE_DRAG_OUTSIDE cc.CONTROL_EVENTTYPE_DRAG_ENTER cc.CONTROL_EVENTTYPE_DRAG_EXIT cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE cc.CONTROL_EVENTTYPE_TOUCH_UP_OUTSIDE cc.CONTROL_EVENTTYPE_TOUCH_CANCEL cc.CONTROL_EVENTTYPE_VALUE_CHANGED-- Control::State 控件狀態-- 含義參見:http://shahdza.blog.51cto.com/2410787/1543349cc.CONTROL_STATE_NORMAL cc.CONTROL_STATE_DISABLED cc.CONTROL_STATE_SELECTED cc.CONTROL_STATE_HIGH_LIGHTED-- EditBox::EditBoxInputMode 文本框虛擬鍵盤的編輯類型-- 含義參見:http://shahdza.blog.51cto.com/2410787/1544213cc.EDITBOX_INPUT_MODE_ANY cc.EDITBOX_INPUT_MODE_URL cc.EDITBOX_INPUT_MODE_DECIMAL cc.EDITBOX_INPUT_MODE_NUMERIC cc.EDITBOX_INPUT_MODE_EMAILADDR cc.EDITBOX_INPUT_MODE_SINGLELINE cc.EDITBOX_INPUT_MODE_PHONENUMBER-- EditBox::EditBoxInputFlag 文本框文本類型-- 含義參見:http://shahdza.blog.51cto.com/2410787/1544213cc.EDITBOX_INPUT_FLAG_PASSWORD cc.EDITBOX_INPUT_FLAG_SENSITIVE cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS-- EditBox::KeyboardReturnType 文本框虛擬鍵盤中return鍵顯示字符-- 含義參見:http://shahdza.blog.51cto.com/2410787/1544213cc.KEYBOARD_RETURNTYPE_GO cc.KEYBOARD_RETURNTYPE_DONE cc.KEYBOARD_RETURNTYPE_SEND cc.KEYBOARD_RETURNTYPE_SEARCH cc.KEYBOARD_RETURNTYPE_DEFAULT-- ScrollView::Direction 滾動方向-- 含義參見:http://shahdza.blog.51cto.com/2410787/1544983cc.SCROLLVIEW_DIRECTION_BOTH cc.SCROLLVIEW_DIRECTION_VERTICAL cc.SCROLLVIEW_DIRECTION_HORIZONTAL-- TableView::VerticalFillOrder 列表視圖排列方式-- 含義參見:http://shahdza.blog.51cto.com/2410787/1545383cc.TABLEVIEW_FILL_TOPDOWN cc.TABLEVIEW_FILL_BOTTOMUP-- ProgressTimer::Type-- 含義參見:http://shahdza.blog.51cto.com/2410787/1546707cc.PROGRESS_TIMER_TYPE_BAR cc.PROGRESS_TIMER_TYPE_RADIAL-- ParticleSystem::PositionType 粒子位置模式-- 含義參見:cc.POSITION_TYPE_FREE cc.POSITION_TYPE_GROUPED cc.POSITION_TYPE_RELATIVE-- ParticleSystem::Mode 粒子發射器類型-- 含義參見:http://shahdza.blog.51cto.com/2410787/1547636cc.PARTICLE_MODE_RADIUS cc.PARTICLE_MODE_GRAVITY-- TransitionScene::Orientation 場景切換方向-- 含義參見:http://shahdza.blog.51cto.com/2410787/1547977cc.TRANSITION_ORIENTATION_UP_OVER cc.TRANSITION_ORIENTATION_DOWN_OVER cc.TRANSITION_ORIENTATION_LEFT_OVER cc.TRANSITION_ORIENTATION_RIGHT_OVER-- TextVAlignment 文本的垂直對其方式-- 含義參見:http://shahdza.blog.51cto.com/2410787/1560612cc.VERTICAL_TEXT_ALIGNMENT_TOP cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM cc.VERTICAL_TEXT_ALIGNMENT_CENTER-- TextHAlignment 文本的水平對其方式-- 含義參見:http://shahdza.blog.51cto.com/2410787/1560612cc.TEXT_ALIGNMENT_LEFT cc.TEXT_ALIGNMENT_RIGHT cc.TEXT_ALIGNMENT_CENTER
五、Lua中的事件回調
cocos2dx中經常使用的事件回調有以下:
動做回調 : CallFunc
定時器刷新 : schedule
菜單項事件回調 : menuItem
按鈕控件事件回調 : ControlButton
在cocos2dx v3.2中,因爲支持了C++ 11,使用 std::bind 集成了 CC_CALLBACK_* 。
在Lua中可不能這樣方便的使用。
5.一、動做回調 CallFunc
在C++中,動做回調參見:http://shahdza.blog.51cto.com/2410787/1553051
在Lua中只剩下一個 CallFunc ,其定義以下:
至於回調函數中有什麼參數,參見下面的例子。
-- hander : 執行的回調函數-- value : 傳遞給回調函數的參數,必須爲一個tablecc.CallFunc:create(hander, value)
使用舉例:
-- node : 執行動做的對象 -- tab : 傳過來的參數, 必須爲一個table local function callbackFunc(node, tab) node:setScale(2) print("x=" .. tab.x .. ",y=" .. tab.y) end local sprite = cc.Sprite:create("normal.png") sprite:setPosition(winSize.width/2, winSize.height/2) self:addChild(sprite) -- CallFunc回調動做 local call = cc.CallFunc:create(callbackFunc, {x=1 , y=2} ) sprite:runAction(call)
5.二、定時器刷新 schedule
在C++中,定時器參見:http://shahdza.blog.51cto.com/2410787/1542014
在Lua中,有兩種方式:
(1)self:scheduleUpdateWithPriorityLua(update, priority)
參數一:刷新函數
參數二:刷新優先級
其中 self 爲 Node類 的子類。
該方法默認爲每幀都刷新一次,沒法自定義刷新時間間隔。
(2)scheduler:scheduleScriptFunc(update, inteval, false)
參數一:刷新函數
參數二:每次刷新的時間間隔
參數三:是否只執行一次。false爲無限次。
其中 scheduler 爲定時器管理:cc.Director:getInstance():getScheduler()
而我更推薦使用第二種方式,由於比較通用。
使用舉例:
local scheduler, myupdate local timer = 0 local function update(dt) cclog("update: " .. dt) -- 輸出log timer = timer + dt if timer >= 3 then -- 執行3秒取消定時器 -- self:unscheduleUpdate() -- 取消定時器 scheduler:unscheduleScriptEntry(myupdate) -- 取消定時器 end end -- 每幀執行一次update,優先級爲0 -- self:scheduleUpdateWithPriorityLua(update, 0); -- 每30/60秒執行一次update,會無限執行 scheduler = cc.Director:getInstance():getScheduler() myupdate = scheduler:scheduleScriptFunc(update, 30.0 / 60.0, false)
5.三、菜單項事件回調 menuItem
在C++中,菜單項回調參見:http://shahdza.blog.51cto.com/2410787/1553051
在Lua中,使用:registerScriptTapHandler(hander) 。
其中 hander 即爲須要綁定的回調函數,至於回調函數中有什麼參數,參見下面的例子。
使用舉例:
local menu local normal, hard -- tag : 爲menuItem設置的標籤setTag -- menuItem : 執行回調的menuItem對象 local function menuCallback(tag, menuItem) print("menuItem: " .. tag) end normal = cc.MenuItemImage:create("normal.png", "normal.png") normal:setPosition(0, 120) normal:setTag(1) hard = cc.MenuItemImage:create("hard.png", "hard.png") hard:setPosition(0, 20) hard:setTag(2) -- 建立菜單,最後不須要加NULL menu = cc.Menu:create(normal, hard) self:addChild(menu) -- 菜單項回調 normal:registerScriptTapHandler(menuCallback) -- 按鈕事件 hard:registerScriptTapHandler(menuCallback) -- 按鈕事件
5.四、按鈕控件事件回調 ControlButton
在C++中,按鈕控件事件回調參見:http://shahdza.blog.51cto.com/2410787/1543349
在Lua中,使用:registerControlEventHandler(hander, type) 。
其中 hander 爲咱們須要綁定的回調函數,而 type 則是按鈕事件的類型。
至於回調函數中有什麼參數,參見下面的例子。
對於 type ,有如下幾種類型:
cc.CONTROL_EVENTTYPE_TOUCH_DOWN -- 剛剛開始觸摸按鈕時cc.CONTROL_EVENTTYPE_DRAG_INSIDE -- 在內部拖動時(保持觸摸狀態下)cc.CONTROL_EVENTTYPE_DRAG_OUTSIDE -- 在外部拖動時(保持觸摸狀態下)cc.CONTROL_EVENTTYPE_DRAG_ENTER -- 拖動剛進入內部時(保持觸摸狀態下)cc.CONTROL_EVENTTYPE_DRAG_EXIT -- 拖動剛離開內部時(保持觸摸狀態下)cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE -- 在內部擡起手指(保持觸摸狀態下)cc.CONTROL_EVENTTYPE_TOUCH_UP_OUTSIDE -- 在外部擡起手指(保持觸摸狀態下)cc.CONTROL_EVENTTYPE_TOUCH_CANCEL -- 取消觸點時cc.CONTROL_EVENTTYPE_VALUE_CHANGED -- 按鈕控件中值發生改變時
使用舉例:
-- node : 執行回調的按鈕對象 -- type : 按鈕事件的類型local function btnCallback(node, type)if type == cc.CONTROL_EVENTTYPE_TOUCH_DOWN thenprint("touch down") elseif type == cc.CONTROL_EVENTTYPE_DRAG_INSIDE thenprint("drag inside") elseif type == cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE thenprint("touch up inside") end end -- 添加一個按鈕 ControlButtonlocal label = cc.Label:createWithSystemFont("button","res/fonts/Marker Felt.ttf",30)local sprite = cc.Scale9Sprite:create("normal.png")local btn = cc.ControlButton:create(label,sprite) btn:setPosition(winSize.width/2, winSize.height/2) self:addChild(btn) -- 按鈕事件回調 btn:registerControlEventHandler(btnCallback,cc.CONTROL_EVENTTYPE_TOUCH_DOWN) btn:registerControlEventHandler(btnCallback,cc.CONTROL_EVENTTYPE_DRAG_INSIDE) btn:registerControlEventHandler(btnCallback,cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE)
六、Lua中的事件分發機制
在C++中,事件分發機制參見:http://shahdza.blog.51cto.com/2410787/1560222
事件分發機制包含:
觸摸事件 : EventListenerTouchOneByOne、EventListenerTouchAllAtOnce
鼠標響應事件 : EventListenerMouse
鍵盤響應事件 : EventListenerKeyboard
加速計事件 : EventListenerAcceleration
自定義事件 : EventListenerCustom
物理碰撞事件 : EventListenerPhysicsContact
遊戲手柄事件 : EventListenerController
而在cocos2dx v3.2版本中,Lua的使用方式與C++有點相似。
PS:在Lua中對於 鼠標事件、自定義事件 的支持有BUG,建議你們暫時不要去使用。
另外因爲博主還未接觸過物理碰撞事件、遊戲手柄事件,因此也沒法講解着兩個事件機制的使用方法,不過能夠肯定的一點是:以上幾個事件處理都是經過監聽器來完成的,因此用法應該都是差很少的。
在這裏我重點講一下:觸摸事件、鍵盤事件、加速計事件。
事件處理的原理能夠參考C++的使用方法,這裏講一下 Lua 中如何使用。
6.一、使用步驟
仍是繼續用代碼來說解吧,通常性都分爲如下四個步驟。
-- 1.獲取事件分發器 : EventDispatcherlocal dispatcher = cc.Director:getInstance():getEventDispatcher()-- 2.建立事件監聽器 : EventListener (這裏以單點觸摸爲例)local listener = cc.EventListenerTouchOneByOne:create() -- 3.註冊事件響應函數: registerScriptHandler -- hander : 響應函數 -- type : 事件類型 listener:registerScriptHandler(hander, type) -- 4.在事件分發器中,添加監聽器。事件響應委託爲self dispatcher:addEventListenerWithSceneGraphPriority(listener, self)
6.二、單點觸摸事件EventListenerTouchOneByOne
使用方法以下:
響應函數的兩個參數 touch , event 分別表示:
touch : cc.Touch 。觸點信息
event : cc.Event 。事件信息
註冊響應函數 registerScriptHandler 中的第二個參數,表示事件類型。
cc.Handler.EVENT_TOUCH_BEGAN : 觸摸開始
cc.Handler.EVENT_TOUCH_MOVED : 觸摸移動
cc.Handler.EVENT_TOUCH_ENDED : 觸摸結束
-- 觸摸開始local function onTouchBegan(touch, event) print("Touch Began") local pos = touch:getLocation() -- 獲取觸點的位置print(pos.x .. " , " .. pos.y) -- 輸出logreturn true -- 必須返回true 後邊move end纔會被處理end -- 觸摸移動 local function onTouchMoved(touch, event) print("Touch Moved") end -- 觸摸結束 local function onTouchEnded(touch, event) print("Touch Ended") end -- 註冊單點觸摸 local dispatcher = cc.Director:getInstance():getEventDispatcher() local listener = cc.EventListenerTouchOneByOne:create() listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) listener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) listener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) dispatcher:addEventListenerWithSceneGraphPriority(listener, self)
6.三、多點觸摸事件EventListenerTouchAllAtOnce
使用方法以下:
響應函數的兩個參數 touches , event 分別表示:
touches : cc.Touch的table數組 。多個觸點信息
event : cc.Event 。事件信息
註冊響應函數 registerScriptHandler 中的第二個參數,表示事件類型。
cc.Handler.EVENT_TOUCHES_BEGAN : 多點觸摸開始
cc.Handler.EVENT_TOUCHES_MOVED : 多點觸摸移動
cc.Handler.EVENT_TOUCHES_ENDED : 多點觸摸結束
-- 觸摸開始local function onTouchesBegan(touches, event) print("Touches Began") local pos1 = touches[1]:getLocation() -- 獲取觸點1的位置local pos2 = touches[2]:getLocation() -- 獲取觸點2的位置local delta = { x = pos2.x - pos1.x , y = pos2.y - pos1.y } print(delta.x .. " , " .. delta.y) -- 輸出logend -- 觸摸移動 local function onTouchesMoved(touches, event) print("Touches Moved") end -- 觸摸結束 local function onTouchesEnded(touches, event) print("Touches Ended") end -- 註冊多點觸摸 local dispatcher = cc.Director:getInstance():getEventDispatcher() local listener = cc.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(onTouchesBegan, cc.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(onTouchesMoved, cc.Handler.EVENT_TOUCHES_MOVED) listener:registerScriptHandler(onTouchesEnded, cc.Handler.EVENT_TOUCHES_ENDED) dispatcher:addEventListenerWithSceneGraphPriority(listener, self)
6.四、鍵盤事件EventListenerKeyboard
EventListenerKeyboard,主要用於監聽鍵盤某個鍵的按下、鬆開的事件。
使用方法以下:
響應函數的兩個參數 keyCode , event 分別表示:
keyCode : number 。鍵盤按鍵枚舉值
event : cc.Event 。事件信息
註冊響應函數 registerScriptHandler 中的第二個參數,表示事件類型。
cc.Handler.EVENT_KEYBOARD_PRESSED : 按下鍵盤的某個鍵
cc.Handler.EVENT_KEYBOARD_RELEASED : 鬆開鍵盤的某個鍵
鍵盤按鍵枚舉值以下:(僅舉例說明)
cc.KeyCode.KEY_A : A鍵
cc.KeyCode.KEY_1 : 1鍵
cc.KeyCode.KEY_F1 : F1鍵
cc.KeyCode.KEY_SPACE : 空格鍵
cc.KeyCode.KEY_ALT : ALT鍵
cc.KeyCode.KEY_SHIFT : SHIFT鍵
local function onKeyPressed(keyCode, event) if keyCode == cc.KeyCode.KEY_A then print("Pressed A !") -- 按下A鍵end end local function onKeyReleased(keyCode, event) if keyCode == cc.KeyCode.KEY_J then print("Released J !") -- 鬆開J鍵 end end -- 註冊鍵盤事件 local dispatcher = cc.Director:getInstance():getEventDispatcher() local listener = cc.EventListenerKeyboard:create() listener:registerScriptHandler(onKeyPressed, cc.Handler.EVENT_KEYBOARD_PRESSED) listener:registerScriptHandler(onKeyReleased, cc.Handler.EVENT_KEYBOARD_RELEASED) dispatcher:addEventListenerWithSceneGraphPriority(listener, self)
6.五、加速計事件EventListenerAcceleration
EventListenerAcceleration,主要用於監聽移動設備的所受重力方向感應事件。
重力感應來自移動設備的加速計,一般支持 (X, Y, Z) 三個方向的加速度感應,因此又稱爲三向加速計。在實際應用中,能夠根據3個方向的力度大小來計算手機傾斜的角度或方向。
EventListenerAcceleration用法和上述幾個有點不一樣。
使用方法以下:
響應函數有五個參數 event , x , y , z , timestamp 分別表示:
event : cc.Event 。事件信息
(x, y, z) : number 。設備在三個方向上的重力加速度感應
timestamp : number 。響應事件的時間戳
建立加速計監聽器時,直接傳入響應函數做爲參數,而不用registerScriptHandler 。
使用加速計事件時,還須要開啓設備的加速計感應:
self:setAccelerometerEnabled(true)
在電腦上看不到效果,須要在設備上才能看到效果。
-- 開啓設備的加速計感應self:setAccelerometerEnabled(true) -- 響應函數 local function onAccelerationEvent(event, x, y, z, timestamp) print("x: " .. x) print("y: " .. y) print("z: " .. z) print("timestamp: " .. timestamp) end -- 註冊加速計監聽器 local dispatcher = cc.Director:getInstance():getEventDispatcher() -- 直接傳入 響應函數 做爲參數 local listener = cc.EventListenerAcceleration:create(onAccelerationEvent) dispatcher:addEventListenerWithSceneGraphPriority(listener, self)
在手機上的運行效果:
七、Lua中的數學類
在C++中,數學類參見:http://shahdza.blog.51cto.com/2410787/1550972
數學類主要有Vec2(座標向量)、Size(尺寸)、Rect(矩形)。
7.一、建立
在Lua中建立的 Vec二、Size、Rect 都是一個table類型。
其中只有相應的成員變量,沒有相關的函數運算。
cc.p(x, y) -- 構造 Vec2cc.size(width, height) -- 構造 Sizecc.rect(x, y, width, height) -- 構造 Rect
7.二、座標向量運算
Lua中經常使用的向量運算以下:
(1)返回值爲bool
-- 直線AB與直線CD是否相交 cc.pIsLineIntersect(pA, pB, pC, pD,float,float) -- 線段AB與線段CD是否相交 cc.pIsSegmentIntersect(pA, pB, pC, pD)
(2)返回值爲float
cc.pDot(p1, p2) -- 點積cc.pCross(p1, p2) -- 叉積cc.pProject(p1, p2) -- 投影: 前point在後point上的投影cc.pGetLength(p) -- 向量長度 cc.pLengthSQ(p) -- 向量長度平方cc.pGetDistance(p1, p2) -- 座標距離cc.pDistanceSQ(p1, p2) -- 座標距離平方cc.pGetAngle(p1, p2) -- 向量夾角:弧度
(3)返回值爲point_table
cc.p(x, y) -- 構造座標pointcc.pAdd(p1, p2) -- 相加cc.pSub(p1, p2) -- 相減cc.pMidpoint(p1, p2) -- 兩向量的中點cc.pNormalize(p1) -- 標準化向量cc.pGetClampPoint(minp, maxp, p) -- 將p值限制在[minp,maxp]區間內cc.pForAngle(float) -- 返回座標 x=cos(a) , y=sin(a)cc.pPerp(p) -- 逆時針旋轉90度(-y, x)cc.RPerp(p) -- 順時針旋轉90度(y, -x)-- 繞p1向量旋轉-- 返回向量: 角度 this.getAngle() +other.getAngle()-- 長度 this.getLength()*other.getLength()cc.pRotate(p1, p2)-- 繞p1向量旋轉前的向量值-- 返回向量: 角度 this.getAngle() -other.getAngle(); -- 長度 this.getLength()*other.getLength();cc.pUnrotate(p1, p2)-- 直線AB與直線CD的交點cc.pGetIntersectPoint(pA, pB, pC, pD)
7.三、矩形運算
Lua中經常使用的矩形運算以下:
cc.rectGetMinX(rect) -- rect.xcc.rectGetMidX(rect) -- (rect.x + rect.width) / 2cc.rectGetMaxX(rect) -- rect.x + rect.widthcc.rectGetMinY(rect) -- rect.ycc.rectGetMidY(rect) -- (rect.y + rect.height) / 2cc.rectGetMaxY(rect) -- rect.y + rect.height-- 判斷是否與rect相同. 原點相同,尺寸相同.cc.rectEqualToRect(rect1, rect2)-- 判斷point是否包含在矩形內cc.rectContainsPoint(rect, point)-- 判斷矩形是否相交. 經常用做碰撞檢測.cc.rectIntersectsRect(rect1, rect2)-- 兩矩形合併cc.rectUnion(rect1, rect2)
八、Lua中的顏色類
在C++的顏色類主要有三個:Color3B、Color4B、Color4F。而且有不少顏色的宏定義。
在Lua中,沒法使用顏色的宏定義,而須要本身設置。
顏色類的使用方法以下:
cc.c3b(byte,byte,byte) -- 構造 Color3B cc.c4b(byte,byte,byte,byte) -- 構造 Color4B cc.c4f(float,float,float,float) -- 構造 Color4F
九、還有什麼?
在最後,我還想講講一些使用Lua開發cocos2dx的注意事項。
9.一、關於getPosition()
先來看看幾個 getXXX() 函數的返回值吧。
getPosition() -- 返回兩個值:x ygetAnchorPoint() -- point_tablegetContentSize() -- size_tablegetBoundingBox() -- rect_table
能夠發現:getPosition() 返回的不是point_table,而是兩個值。 PS:真是一個大坑! 因此接收 getPosition() 時須要處理一下。
-- 方法一 : 用兩個變量接收local x, y = sprite:getPosition()-- 方法二 : 轉換爲point_tablelocal p = cc.p(sprite:getPosition())
9.二、關於 . 和 :
在Lua中,必定要區分這兩個:點. 和 冒號: 的區別,很容易搞混掉。
定義的時候,冒號: 默認接收self參數
調用的時候,冒號: 默認傳遞調用者本身爲參數
而點號. 要顯示傳遞或接收self參數
例如:點號定義,須要顯示傳遞或接收。
tab = { x = 1 }function tab.fun(self) print(self.x) end a.fun(a) -- 須要將a自己作爲參數傳給fun函數
這樣使用函數就要傳遞自身self,用起來很麻煩。
因此Lua給出了一個方便的方法:將函數定義改爲冒號: ,這樣就能夠省略self參數了。
a = { x = 1 }function a:fun() print(self.x) end a:fun()