Lua回调函数小结
2016-01-05 19:07
387 查看
转自:小塔博客
1、菜单按钮的回调。这二者的回调是这么实现的,新建一个菜单或者是按钮,为了点击菜单或者按钮以后实现程序的逻辑,我们需要为菜单和按钮来绑定一个回调函数,于是乎,我们有了以下的代码。
在这里我们使用了一个重要的回调注册函数registerScriptTapHandler,Tap就是按下的意思,所以调用这个函数的时候是对菜单和按钮进行绑定的,这个函数的调用者是菜单项,需要传入一个参数,这个参数就是绑定的函数。接下来我们看下绑定的函数,我绑定的函数并没有接受任何传递过来的参数,这个就是Lua,你可以选择接受或者不接受,但是参数就在那里。为了看看这货是什么鸟,我们写上俩个参数,打印一下,发现一个值是-1,一个值是UserData,有图为证。
![](https://img-blog.csdn.net/20160105190422353?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
打印的结果是-1和userdata,userdata我们可以理解,你绑定的谁那么就传递过来谁嘛,但是第一个传递过来的参数是-1肿么回事?原来第一个参数代表的是tag,如果你没有给你的菜单项设置tag,那么它就是-1,如果设置了tag,那么这个值就是tag的值,OK,这样的话就清楚了。以下的代码是添加button的代码,一共添加了三个button,大家可以参考一下。
--添加按钮
function GameScene:addButton(layer)
--创建button
local function scale9_normal()
return cc.Scale9Sprite:create("buttonBackground.png")
end
local function scale9_press()
return cc.Scale9Sprite:create("buttonHighlighted.png")
end
--文本信息
self.button1_label = cc.Label:createWithTTF("Ready","fonts/label.TTF",32)
self.button2_label = cc.Label:createWithTTF("Ready","fonts/label.TTF",32)
self.button3_label = cc.Label:createWithTTF("Ready","fonts/label.TTF",32)
--button1
local button1 = cc.ControlButton:create(self.button1_label,scale9_normal())
button1:setBackgroundSpriteForState(scale9_press(),cc.CONTROL_EVENTTYPE_TOUCH_DOWN)
button1:setTag(1)
button1:setPosition(self.size.width*0.2,self.size.height*0.2)
--button2
local button2 = cc.ControlButton:create(self.button2_label,scale9_normal())
button2:setBackgroundSpriteForState(scale9_press(),cc.CONTROL_EVENTTYPE_TOUCH_DOWN)
button2:setTag(2)
button2:setPosition(self.size.width*0.5,self.size.height*0.2)
--button3
local button3 = cc.ControlButton:create(self.button3_label,scale9_normal())
button3:setBackgroundSpriteForState(scale9_press(),cc.CONTROL_EVENTTYPE_TOUCH_DOWN)
button3:setTag(3)
button3:setPosition(self.size.width*0.8,self.size.height*0.2)
--设置button的回调函数
local button_callback = function (ref,button)
--如果正确跟新分数
if self.correct == ref:getTag() then
self:correct_callback()
else
self:wrong_callback()
end
end
--设置回调函数
button1:registerControlEventHandler(button_callback,cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE)
button2:registerControlEventHandler(button_callback,cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE)
button3:registerControlEventHandler(button_callback,cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE)
--添加到层中
layer:addChild(button1)
layer:addChild(button2)
layer:addChild(button3)
end
2、添加Android返回键的响应代码,Android返回键同样需要回调函数来做这件事情,在Cocos中使用的是事件监听和分发机制,所以我们需要先注册一下事件类型,然后绑定回调,代码如下。
--监听手机返回键
local key_listener = cc.EventListenerKeyboard:create()
--返回键回调
local function key_return()
--结束游戏
cc.Director:getInstance():endToLua()
end
--lua中得回调,分清谁绑定,监听谁,事件类型是什么
key_listener:registerScriptHandler(key_return,cc.Handler.EVENT_KEYBOARD_RELEASED)
local eventDispatch = layer:getEventDispatcher()
eventDispatch:addEventListenerWithSceneGraphPriority(key_listener,layer)
这次我们使用的注册回调函数是registerScriptHandler,没有Tap,显然就不是为菜单和按钮回调准备的,所以这个函数是用来注册一般的回调函数所使用的。其中注释有句话说的比较好,就是一定要明白谁绑定,监听谁,事件类型是什么,在这个例子看来,是事件监听器去绑定了一个回调函数key_return,然后事件的类型是放到了一个Handler表中的,我们的事件类型是keyBoard,可以到Handler中看看都有哪些事件类型,然后所有你熟悉的东西都会看到了,比如以下的代码所代表的事件类型。
3、动作的回调,3.x以后在c++层的动作回调函数只剩下Callfunc和CallfuncN了,其他的都可以用c++11的std::bind解决,而在Lua中就剩下一个了,这个是由Lua的特性决定的,用法如下。
CallFunc中有俩个参数,一个是绑定的回调函数,另一个是table表,这个表中可以存放一些命名参数,把你想要传递的东西统统通过这个表传递过去,然后在回调函数中,我们有俩个参数来接受,第一个当然是动作的执行者了,第二个就是传递过来的这张表,里边有所有我们要得参数,是不是很高大上啊!
4、看完了以上的这些东西,我们基本明白了怎么使用,所谓知其然更要知其所以然,这些回调函数是怎么分发到Lua层的代码中的,我们就需要看一个文件了。打开你引擎目录的cocos/scripting/lua-bindings/manual/CCLuaEngine.cpp文件,我们需要找到这样一处代码。
sendEvent顾名思义,这段代码就是向Lua层来分发回调事件的代码,在这段代码中,我们看到了很多熟悉的身影,比如说node的分发,menu的分发,schedule的分发,touch的分发等等都在这里,但是却没有事件监听器的分发,没错,事件监听器的回调Lua并没有写在这个文件中,而是在其他的文件中处理的,大家可以自行研究。我们以node回调Lua层的代码为例,看看是怎么回调Lua层的函数的,关键的代码在这里。
根据action的类型,我们将不同的字符串压入了栈中,然后执行了executeFunctionByHandler函数,第一个参数handler就是回调的函数,第二个参数代表传递到回调函数中的参数个数。其他的回调Lua层的函数大同小异,大家自行研究吧。那么在Lua层,这个回调函数是怎么被注册的呢?我们新建工程由系统创建了一个GameScene.lua文件,这个文件中的这段代码,不知道大家是否留意过。
1、菜单按钮的回调。这二者的回调是这么实现的,新建一个菜单或者是按钮,为了点击菜单或者按钮以后实现程序的逻辑,我们需要为菜单和按钮来绑定一个回调函数,于是乎,我们有了以下的代码。
--定义菜单项的回调函数 local function item1_callback() --切换场景 local gameScene = require("GameScene") cc.Director:getInstance():replaceScene(gameScene:createScene()) end local function item2_callback() --切换场景 local aboutScene = require("AboutScene") cc.Director:getInstance():pushScene(aboutScene:createScene()) end local item1 = cc.MenuItemLabel:create(cc.Label:createWithTTF("开始游戏","fonts/menu.ttf",42)) item1:registerScriptTapHandler(item1_callback) local item2 = cc.MenuItemLabel:create(cc.Label:createWithTTF("关于游戏","fonts/menu.ttf",42)) item2:registerScriptTapHandler(item2_callback) --创建菜单 local menu = cc.Menu:create(item1,item2) menu:alignItemsVerticallyWithPadding(size.height*0.15) --添加菜单到游戏中 layer:addChild(menu)
在这里我们使用了一个重要的回调注册函数registerScriptTapHandler,Tap就是按下的意思,所以调用这个函数的时候是对菜单和按钮进行绑定的,这个函数的调用者是菜单项,需要传入一个参数,这个参数就是绑定的函数。接下来我们看下绑定的函数,我绑定的函数并没有接受任何传递过来的参数,这个就是Lua,你可以选择接受或者不接受,但是参数就在那里。为了看看这货是什么鸟,我们写上俩个参数,打印一下,发现一个值是-1,一个值是UserData,有图为证。
--定义菜单项的回调函数 local function item1_callback(para1,para2) print(para1,para2) --切换场景 local gameScene = require("GameScene") cc.Director:getInstance():replaceScene(gameScene:createScene()) end
打印的结果是-1和userdata,userdata我们可以理解,你绑定的谁那么就传递过来谁嘛,但是第一个传递过来的参数是-1肿么回事?原来第一个参数代表的是tag,如果你没有给你的菜单项设置tag,那么它就是-1,如果设置了tag,那么这个值就是tag的值,OK,这样的话就清楚了。以下的代码是添加button的代码,一共添加了三个button,大家可以参考一下。
--添加按钮
function GameScene:addButton(layer)
--创建button
local function scale9_normal()
return cc.Scale9Sprite:create("buttonBackground.png")
end
local function scale9_press()
return cc.Scale9Sprite:create("buttonHighlighted.png")
end
--文本信息
self.button1_label = cc.Label:createWithTTF("Ready","fonts/label.TTF",32)
self.button2_label = cc.Label:createWithTTF("Ready","fonts/label.TTF",32)
self.button3_label = cc.Label:createWithTTF("Ready","fonts/label.TTF",32)
--button1
local button1 = cc.ControlButton:create(self.button1_label,scale9_normal())
button1:setBackgroundSpriteForState(scale9_press(),cc.CONTROL_EVENTTYPE_TOUCH_DOWN)
button1:setTag(1)
button1:setPosition(self.size.width*0.2,self.size.height*0.2)
--button2
local button2 = cc.ControlButton:create(self.button2_label,scale9_normal())
button2:setBackgroundSpriteForState(scale9_press(),cc.CONTROL_EVENTTYPE_TOUCH_DOWN)
button2:setTag(2)
button2:setPosition(self.size.width*0.5,self.size.height*0.2)
--button3
local button3 = cc.ControlButton:create(self.button3_label,scale9_normal())
button3:setBackgroundSpriteForState(scale9_press(),cc.CONTROL_EVENTTYPE_TOUCH_DOWN)
button3:setTag(3)
button3:setPosition(self.size.width*0.8,self.size.height*0.2)
--设置button的回调函数
local button_callback = function (ref,button)
--如果正确跟新分数
if self.correct == ref:getTag() then
self:correct_callback()
else
self:wrong_callback()
end
end
--设置回调函数
button1:registerControlEventHandler(button_callback,cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE)
button2:registerControlEventHandler(button_callback,cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE)
button3:registerControlEventHandler(button_callback,cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE)
--添加到层中
layer:addChild(button1)
layer:addChild(button2)
layer:addChild(button3)
end
2、添加Android返回键的响应代码,Android返回键同样需要回调函数来做这件事情,在Cocos中使用的是事件监听和分发机制,所以我们需要先注册一下事件类型,然后绑定回调,代码如下。
--监听手机返回键
local key_listener = cc.EventListenerKeyboard:create()
--返回键回调
local function key_return()
--结束游戏
cc.Director:getInstance():endToLua()
end
--lua中得回调,分清谁绑定,监听谁,事件类型是什么
key_listener:registerScriptHandler(key_return,cc.Handler.EVENT_KEYBOARD_RELEASED)
local eventDispatch = layer:getEventDispatcher()
eventDispatch:addEventListenerWithSceneGraphPriority(key_listener,layer)
这次我们使用的注册回调函数是registerScriptHandler,没有Tap,显然就不是为菜单和按钮回调准备的,所以这个函数是用来注册一般的回调函数所使用的。其中注释有句话说的比较好,就是一定要明白谁绑定,监听谁,事件类型是什么,在这个例子看来,是事件监听器去绑定了一个回调函数key_return,然后事件的类型是放到了一个Handler表中的,我们的事件类型是keyBoard,可以到Handler中看看都有哪些事件类型,然后所有你熟悉的东西都会看到了,比如以下的代码所代表的事件类型。
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 ) local eventDispatcher = layerFarm:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layerFarm)
3、动作的回调,3.x以后在c++层的动作回调函数只剩下Callfunc和CallfuncN了,其他的都可以用c++11的std::bind解决,而在Lua中就剩下一个了,这个是由Lua的特性决定的,用法如下。
--ready和go的回调函数 函数可以有俩个参数,第一个代表接受动作的对象,就是谁执行了动作,第二个是传过来的参数,全部放到了表中 local ready_action = function(actionSelf,tab) end local go_action = function() end cc.CallFunc:create(ready_action,{x=1})
CallFunc中有俩个参数,一个是绑定的回调函数,另一个是table表,这个表中可以存放一些命名参数,把你想要传递的东西统统通过这个表传递过去,然后在回调函数中,我们有俩个参数来接受,第一个当然是动作的执行者了,第二个就是传递过来的这张表,里边有所有我们要得参数,是不是很高大上啊!
4、看完了以上的这些东西,我们基本明白了怎么使用,所谓知其然更要知其所以然,这些回调函数是怎么分发到Lua层的代码中的,我们就需要看一个文件了。打开你引擎目录的cocos/scripting/lua-bindings/manual/CCLuaEngine.cpp文件,我们需要找到这样一处代码。
int LuaEngine::sendEvent(ScriptEvent* evt) { if (NULL == evt) return 0; switch (evt->type) { case kNodeEvent: { return handleNodeEvent(evt->data); } break; case kMenuClickedEvent: { return handleMenuClickedEvent(evt->data); } break; case kCallFuncEvent: { return handleCallFuncActionEvent(evt->data); } break; case kScheduleEvent: { return handleScheduler(evt->data); } break; case kTouchEvent: { return handleTouchEvent(evt->data); } break; case kTouchesEvent: { return handleTouchesEvent(evt->data); } break; case kKeypadEvent: { return handleKeypadEvent(evt->data); } break; case kAccelerometerEvent: { return handleAccelerometerEvent(evt->data); } break; case kCommonEvent: { return handleCommonEvent(evt->data); } break; case kControlEvent: { return handlerControlEvent(evt->data); } break; default: break; } return 0; }
sendEvent顾名思义,这段代码就是向Lua层来分发回调事件的代码,在这段代码中,我们看到了很多熟悉的身影,比如说node的分发,menu的分发,schedule的分发,touch的分发等等都在这里,但是却没有事件监听器的分发,没错,事件监听器的回调Lua并没有写在这个文件中,而是在其他的文件中处理的,大家可以自行研究。我们以node回调Lua层的代码为例,看看是怎么回调Lua层的函数的,关键的代码在这里。
int action = *((int*)(basicScriptData->value)); switch (action) { case kNodeOnEnter: _stack->pushString("enter"); break; case kNodeOnExit: _stack->pushString("exit"); break; case kNodeOnEnterTransitionDidFinish: _stack->pushString("enterTransitionFinish"); break; case kNodeOnExitTransitionDidStart: _stack->pushString("exitTransitionStart"); break; case kNodeOnCleanup: _stack->pushString("cleanup"); break; default: return 0; } int ret = _stack->executeFunctionByHandler(handler, 1); _stack->clean();
根据action的类型,我们将不同的字符串压入了栈中,然后执行了executeFunctionByHandler函数,第一个参数handler就是回调的函数,第二个参数代表传递到回调函数中的参数个数。其他的回调Lua层的函数大同小异,大家自行研究吧。那么在Lua层,这个回调函数是怎么被注册的呢?我们新建工程由系统创建了一个GameScene.lua文件,这个文件中的这段代码,不知道大家是否留意过。
local function onNodeEvent(event) if "exit" == event then cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.schedulerID) end end layerFarm:registerScriptHandler(onNodeEvent)
相关文章推荐
- 在FreeSWITCH中执行长期运行的嵌入式脚本--Lua语言例子
- Scala and Evaluation Strategy
- Lua学习之路-3
- Lua学习之路-2
- vs2010编译lua-5.3.2
- Lua学习之路-1
- lua和c的交互
- lua中table总结
- LUA凝视语法
- Mac平台下搭建和配置Lua环境及相关问题
- VS2013+LUA配置教程
- lua 播放帧动画
- lua tutorial 06
- lua tutorial 05
- lua tutorial 04
- sublime添加直接运行语言的方法
- lua tutorial 03
- lua tutorial 02
- lua tutorial 01
- Lua脚本语言入门