cocos2d-x 3.x lua的api与C++的关系

2015年03月23日 16:12 0 点赞 0 评论 更新于 2025-11-21 18:19

\n\t1、Lua中如何使用Cocos2d-x引擎中的类?\n

\n

\n\t在C++中是这样调用的:\n

\n

\n\t//\n

\n

\n\tSprite* sprite = Sprite::create();\n

\n

\n\tsprite->setPosition(Vec2(100, 100));\n

\n

\n\tthis->addChild(sprite);\n

\n

\n\t//\n

\n

\n\t而在Lua中是这样调用的:\n

\n

\n\t//\n

\n

\n\tlocal sprite = cc.Sprite:create()\n

\n

\n\tsprite:setPosition(cc.p(100, 100))\n

\n

\n\tself:addChild(sprite)\n

\n

\n\t//\n

\n

\n\t是不是很简单?差别其实不是很大嘛!\n

\n

\n\tLua中使用引擎中的类,只要在前面多加个 cc. 即可。\n

\n

\n\t而调用类的函数,不是双冒号(::) ,而是一个冒号(:) 。\n

\n

\n\t2、Lua 与 C++ 使用上有何差异?\n

\n

\n\t请耐心看完以下这个类,你或许会有基本上的了解。\n

\n

\n\t//\n

\n

\n\tlocal winSize = cc.Director:getInstance():getWinSize()\n

\n

\n\t— 继承Layer类\n

\n

\n\tMenuLayer = class(“MenuLayer”, function()\n

\n

\n\treturn cc.Layer:create()\n

\n

\n\tend)\n

\n

\n\t— 初始化函数\n

\n

\n\tfunction MenuLayer:ctor()\n

\n

\n\tself.name = “hello”         — 成员变量\n

\n

\n\tself.size = cc.size(0, 0)   — 成员变量\n

\n

\n\tend\n

\n

\n\t— 创建包含GameLayer的场景\n

\n

\n\tfunction MenuLayer:createScene()\n

\n

\n\tlocal scene = cc.Scene:create()\n

\n

\n\tlocal layer = MenuLayer:create()\n

\n

\n\tscene:addChild(layer)\n

\n

\n\treturn scene\n

\n

\n\tend\n

\n

\n\t— 创建GameLayer层\n

\n

\n\tfunction MenuLayer:create()\n

\n

\n\tlocal layer = MenuLayer.new()  — new()\n

\n

\n\tlayer:init()                   — init()\n

\n

\n\treturn layer\n

\n

\n\tend\n

\n

\n\t— 初始化\n

\n

\n\tfunction MenuLayer:init()\n

\n

\n\tself:ShowUI()       — 添加界面元素(Sprite、Label等)\n

\n

\n\tself:addBtn()       — 添加菜单按钮\n

\n

\n\tself:addTouches()   — 添加多点触摸\n

\n

\n\tend\n

\n

\n\t— 添加界面\n

\n

\n\tfunction MenuLayer:ShowUI()\n

\n

\n\t— 背景图片Sprite\n

\n

\n\tlocal bg = cc.Sprite:create(“HelloWorld.png”)\n

\n

\n\tbg:setPosition(cc.p(0, 0))      — 设置位置\n

\n

\n\tbg:setAnchorPoint(0, 0)         — 设置锚点\n

\n

\n\tself:addChild(bg)               — 添加子节点\n

\n

\n\t— 添加文字\n

\n

\n\tself.label = cc.Label:createWithSystemFont(“debug”,”res/fonts/Marker Felt.ttf”,30)\n

\n

\n\tself.label:setPosition(winSize.width/2, winSize.height/2)\n

\n

\n\tself:addChild(self.label)\n

\n

\n\tend\n

\n

\n\t— 添加按钮\n

\n

\n\tfunction MenuLayer:addBtn()\n

\n

\n\tlocal menu\n

\n

\n\tlocal normal, hard\n

\n

\n\t— 回调函数\n

\n

\n\t— tag 为menuItem设置的标签setTag ,menuItem为相应对象\n

\n

\n\tlocal function menuCallback(tag, menuItem)\n

\n

\n\tprint(“menuItem: ” .. tag)    — Lua中的输出语句\n

\n

\n\tend\n

\n

\n\tnormal = cc.MenuItemImage:create(“normal.png”, “normal.png”)\n

\n

\n\tnormal:setPosition(0, 120)\n

\n

\n\tnormal:setTag(1)\n

\n

\n\tnormal:registerScriptTapHandler(menuCallback)   — 按钮事件\n

\n

\n\thard = cc.MenuItemImage:create(“hard.png”, “hard.png”)\n

\n

\n\thard:setPosition(0, 20)\n

\n

\n\thard:setTag(2)\n

\n

\n\thard:registerScriptTapHandler(menuCallback)     — 按钮事件\n

\n

\n\t— 创建菜单,最后不需要加NULL\n

\n

\n\tmenu = cc.Menu:create(normal, hard)\n

\n

\n\tself:addChild(menu)\n

\n

\n\tend\n

\n

\n\t— 多点触摸\n

\n

\n\tfunction MenuLayer:addTouches()\n

\n

\n\tlocal touch1, touch2 = cc.Touch, cc.Touch\n

\n

\n\tlocal function onTouchesBegan(touches, event)\n

\n

\n\tprint(“Touches Began”)\n

\n

\n\ttouch1 = touches[1]     — 第一个触点,下标从1开始\n

\n

\n\ttouch2 = touches[2]     — 第二个触点\n

\n

\n\tlocal pos1 = touch1:getLocation()   — 获取触点1的位置\n

\n

\n\tlocal pos2 = touch2:getLocation()   — 获取触点2的位置\n

\n

\n\tlocal delta = {\n

\n

\n\tx = pos2.x – pos1.x ,\n

\n

\n\ty = pos2.y – pos1.y\n

\n

\n\t}\n

\n

\n\tprint(delta.x .. ” , ” .. delta.y)  — 输出log\n

\n

\n\tend\n

\n

\n\tlocal function onTouchesMoved(touches, event)\n

\n

\n\tprint(“Touches Moved”)\n

\n

\n\tend\n

\n

\n\tlocal function onTouchesEnded(touches, event)\n

\n

\n\tprint(“Touches Ended”)\n

\n

\n\tend\n

\n

\n\t— 注册多点触摸\n

\n

\n\tlocal dispatcher = cc.Director:getInstance():getEventDispatcher()\n

\n

\n\tlocal listener = cc.EventListenerTouchAllAtOnce:create()\n

\n

\n\tlistener:registerScriptHandler(onTouchesBegan, cc.Handler.EVENT_TOUCHES_BEGAN)\n

\n

\n\tlistener:registerScriptHandler(onTouchesMoved, cc.Handler.EVENT_TOUCHES_MOVED)\n

\n

\n\tlistener:registerScriptHandler(onTouchesEnded, cc.Handler.EVENT_TOUCHES_ENDED)\n

\n

\n\tdispatcher:addEventListenerWithSceneGraphPriority(listener, self)\n

\n

\n\tend\n

\n

\n\t//.\n

\n

\n\t3、Lua中的字符串格式转换?\n

\n

\n\tC++中是这样使用的:\n

\n

\n\t//\n

\n

\n\tsprintf(str, “hero_d.png”, i)\n

\n

\n\t//\n

\n

\n\t而在Lua中则是使用 string.format() 函数。\n

\n

\n\t//\n

\n

\n\tstring.format(“hero_d.png”, i)\n

\n

\n\t//\n

\n

\n\t4、Lua中的枚举类型\n

\n

\n\t我们都知道C++中的枚举都改成了强枚举类型,形如Control::State::NORMAL。\n

\n

\n\t而在Lua中将其变成形如:cc.CONTROL_STATE_NORMAL。\n

\n

\n\t估计你已经明白了吧?把所有字母都变成大写,然后把双冒号:: 变成下划线 _ 即可。\n

\n

\n\t下面列出一些我自己整理的常见枚举类型在Lua中是如何使用的。\n

\n

\n\t//\n

\n

\n\t— ResolutionPolicy 屏幕适配\n

\n

\n\tcc.ResolutionPolicy.EXACT_FIT\n

\n

\n\tcc.ResolutionPolicy.FIXED_HEIGHT\n

\n

\n\tcc.ResolutionPolicy.FIXED_WIDTH\n

\n

\n\tcc.ResolutionPolicy.NO_BORDER\n

\n

\n\tcc.ResolutionPolicy.SHOW_ALL\n

\n

\n\t— EventKeyboard::KeyCode 键盘按键枚举类型\n

\n

\n\t— 键盘按键比较多,所以就罗列一部分\n

\n

\n\tcc.KeyCode.KEY_A\n

\n

\n\tcc.KeyCode.KEY_1\n

\n

\n\tcc.KeyCode.KEY_F1\n

\n

\n\tcc.KeyCode.KEY_SPACE\n

\n

\n\tcc.KeyCode.KEY_ALT\n

\n

\n\tcc.KeyCode.KEY_SHIFT\n

\n

\n\t— Control::EventType 控件事件类型\n

\n

\n\tcc.CONTROL_EVENTTYPE_TOUCH_DOWN\n

\n

\n\tcc.CONTROL_EVENTTYPE_DRAG_INSIDE\n

\n

\n\tcc.CONTROL_EVENTTYPE_DRAG_OUTSIDE\n

\n

\n\tcc.CONTROL_EVENTTYPE_DRAG_ENTER\n

\n

\n\tcc.CONTROL_EVENTTYPE_DRAG_EXIT\n

\n

\n\tcc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE\n

\n

\n\tcc.CONTROL_EVENTTYPE_TOUCH_UP_OUTSIDE\n

\n

\n\tcc.CONTROL_EVENTTYPE_TOUCH_CANCEL\n

\n

\n\tcc.CONTROL_EVENTTYPE_VALUE_CHANGED\n

\n

\n\t— Control::State 控件状态\n

\n

\n\tcc.CONTROL_STATE_NORMAL\n

\n

\n\tcc.CONTROL_STATE_DISABLED\n

\n

\n\tcc.CONTROL_STATE_SELECTED\n

\n

\n\tcc.CONTROL_STATE_HIGH_LIGHTED\n

\n

\n\t— EditBox::EditBoxInputMode 文本框虚拟键盘的编辑类型\n

\n

\n\tcc.EDITBOX_INPUT_MODE_ANY\n

\n

\n\tcc.EDITBOX_INPUT_MODE_URL\n

\n

\n\tcc.EDITBOX_INPUT_MODE_DECIMAL\n

\n

\n\tcc.EDITBOX_INPUT_MODE_NUMERIC\n

\n

\n\tcc.EDITBOX_INPUT_MODE_EMAILADDR\n

\n

\n\tcc.EDITBOX_INPUT_MODE_SINGLELINE\n

\n

\n\tcc.EDITBOX_INPUT_MODE_PHONENUMBER\n

\n

\n\t— EditBox::EditBoxInputFlag 文本框文本类型\n

\n

\n\tcc.EDITBOX_INPUT_FLAG_PASSWORD\n

\n

\n\tcc.EDITBOX_INPUT_FLAG_SENSITIVE\n

\n

\n\tcc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD\n

\n

\n\tcc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE\n

\n

\n\tcc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS\n

\n

\n\t— EditBox::KeyboardReturnType 文本框虚拟键盘中return键显示字符\n

\n

\n\tcc.KEYBOARD_RETURNTYPE_GO\n

\n

\n\tcc.KEYBOARD_RETURNTYPE_DONE\n

\n

\n\tcc.KEYBOARD_RETURNTYPE_SEND\n

\n

\n\tcc.KEYBOARD_RETURNTYPE_SEARCH\n

\n

\n\tcc.KEYBOARD_RETURNTYPE_DEFAULT\n

\n

\n\t— ScrollView::Direction 滚动方向\n

\n

\n\tcc.SCROLLVIEW_DIRECTION_BOTH\n

\n

\n\tcc.SCROLLVIEW_DIRECTION_VERTICAL\n

\n

\n\tcc.SCROLLVIEW_DIRECTION_HORIZONTAL\n

\n

\n\t— TableView::VerticalFillOrder 列表视图排列方式\n

\n

\n\tcc.TABLEVIEW_FILL_TOPDOWN\n

\n

\n\tcc.TABLEVIEW_FILL_BOTTOMUP\n

\n

\n\t— ProgressTimer::Type\n

\n

\n\tcc.PROGRESS_TIMER_TYPE_BAR\n

\n

\n\tcc.PROGRESS_TIMER_TYPE_RADIAL\n

\n

\n\t— ParticleSystem::PositionType 粒子位置模式\n

\n

\n\tcc.POSITION_TYPE_FREE\n

\n

\n\tcc.POSITION_TYPE_GROUPED\n

\n

\n\tcc.POSITION_TYPE_RELATIVE\n

\n

\n\t— ParticleSystem::Mode 粒子发射器类型\n

\n

\n\tcc.PARTICLE_MODE_RADIUS\n

\n

\n\tcc.PARTICLE_MODE_GRAVITY\n

\n

\n\t— TransitionScene::Orientation 场景切换方向\n

\n

\n\tcc.TRANSITION_ORIENTATION_UP_OVER\n

\n

\n\tcc.TRANSITION_ORIENTATION_DOWN_OVER\n

\n

\n\tcc.TRANSITION_ORIENTATION_LEFT_OVER\n

\n

\n\tcc.TRANSITION_ORIENTATION_RIGHT_OVER\n

\n

\n\t— TextVAlignment 文本的垂直对其方式\n

\n

\n\tcc.VERTICAL_TEXT_ALIGNMENT_TOP\n

\n

\n\tcc.VERTICAL_TEXT_ALIGNMENT_BOTTOM\n

\n

\n\tcc.VERTICAL_TEXT_ALIGNMENT_CENTER\n

\n

\n\t— TextHAlignment 文本的水平对其方式\n

\n

\n\tcc.TEXT_ALIGNMENT_LEFT\n

\n

\n\tcc.TEXT_ALIGNMENT_RIGHT\n

\n

\n\tcc.TEXT_ALIGNMENT_CENTER\n

\n

\n\t//\n

\n

\n\t5、Lua中的事件回调\n

\n

\n\tCocos2d-x中常用的事件回调有如下:\n

\n

\n\t动作回调 : CallFunc\n

\n

\n\t定时器刷新 : schedule\n

\n

\n\t菜单项事件回调 : menuItem\n

\n

\n\t按钮控件事件回调 : ControlButton\n

\n

\n\t在Cocos2d-x v3.2中,由于支持了C++ 11,使用 std::bind 集成了 CC_CALLBACK_* 。\n

\n

\n\t在Lua中可不能这样方便的使用。\n

\n

\n\t5.1、动作回调 CallFunc\n

\n

\n\t在C++中,动作回调参见:《Cocos2d-x 3.x回调函数std::bind总结》\n

\n

\n\t在Lua中只剩下一个 CallFunc ,其定义如下:\n

\n

\n\t至于回调函数中有什么参数,参见下面的例子。\n

\n

\n\t//\n

\n

\n\t— hander : 执行的回调函数\n

\n

\n\t— value  : 传递给回调函数的参数,必须为一个table\n

\n

\n\tcc.CallFunc:create(hander, value)\n

\n

\n\t//\n

\n

\n\t使用举例:\n

\n

\n\t//\n

\n

\n\t— node : 执行动作的对象\n

\n

\n\t— tab  : 传过来的参数, 必须为一个table\n

\n

\n\tlocal function callbackFunc(node, tab)\n

\n

\n\tnode:setScale(2)\n

\n

\n\tprint(“x=” .. tab.x .. “,y=” .. tab.y)\n

\n

\n\tend\n

\n

\n\tlocal sprite = cc.Sprite:create(“normal.png”)\n

\n

\n\tsprite:setPosition(winSize.width/2, winSize.height/2)\n

\n

\n\tself:addChild(sprite)\n

\n

\n\t— CallFunc回调动作\n

\n

\n\tlocal call = cc.CallFunc:create(callbackFunc, {x=1 , y=2} )\n

\n

\n\tsprite:runAction(call)\n

\n

\n\t//\n

\n

\n\t5.2、定时器刷新 schedule\n

\n

\n\t在C++中,定时器参见:《Cocos2d-x 3.x基础总结 — 定时器更新schedule/update》\n

\n

\n\t在Lua中,有两种方式:\n

\n

\n\t(1)self:scheduleUpdateWithPriorityLua(update, priority)\n

\n

\n\t参数一:刷新函数\n

\n

\n\t参数二:刷新优先级\n

\n

\n\t其中 self 为 Node类 的子类。\n

\n

\n\t该方法默认为每帧都刷新一次,无法自定义刷新时间间隔。\n

\n

\n\t(2)scheduler:scheduleScriptFunc(update, inteval, false)\n

\n

\n\t参数一:刷新函数\n

\n

\n\t参数二:每次刷新的时间间隔\n

\n

\n\t参数三:是否只执行一次。false为无限次。\n

\n

\n\t其中 scheduler 为定时器管理:cc.Director:getInstance():getScheduler()\n

\n

\n\t而我更推荐使用第二种方式,因为比较通用。\n

\n

\n\t使用举例:\n

\n

\n\t//\n

\n

\n\tlocal scheduler, myupdate\n

\n

\n\tlocal timer = 0\n

\n

\n\tlocal function update(dt)\n

\n

\n\tcclog(“update: ” .. dt) — 输出log\n

\n

\n\ttimer = timer + dt\n

\n

\n\tif timer >= 3 then                                  — 执行3秒取消定时器\n

\n

\n\t— self:unscheduleUpdate()                  — 取消定时器\n

\n

\n\tscheduler:unscheduleScriptEntry(myupdate)   — 取消定时器\n

\n

\n\tend\n

\n

\n\tend\n

\n

\n\t— 每帧执行一次update,优先级为0\n

\n

\n\t— self:scheduleUpdateWithPriorityLua(update, 0);\n

\n

\n\t— 每30/60秒执行一次update,会无限执行\n

\n

\n\tscheduler = cc.Director:getInstance():getScheduler()\n

\n

\n\tmyupdate = scheduler:scheduleScriptFunc(update, 30.0 / 60.0, false)\n

\n

\n\t//\n

\n

\n\t5.3、菜单项事件回调 menuItem\n

\n

\n\t在C++中,菜单项回调参见:《Cocos2d-x 3.x回调函数std::bind总结》\n

\n

\n\t在Lua中,使用:registerScriptTapHandler(hander) 。\n

\n

\n\t其中 hander 即为需要绑定的回调函数,至于回调函数中有什么参数,参见下面的例子。\n

\n

\n\t使用举例:\n

\n

\n\t//\n

\n

\n\tlocal menu\n

\n

\n\tlocal normal, hard\n

\n

\n\t— tag      : 为menuItem设置的标签setTag\n

\n

\n\t— menuItem : 执行回调的menuItem对象\n

\n

\n\tlocal function menuCallback(tag, menuItem)\n

\n

\n\tprint(“menuItem: ” .. tag)\n

\n

\n\tend\n

\n

\n\tnormal = cc.MenuItemImage:create(“normal.png”, “normal.png”)\n

\n

\n\tnormal:setPosition(0, 120)\n

\n

\n\tnormal:setTag(1)\n

\n

\n\thard = cc.MenuItemImage:create(“hard.png”, “hard.png”)\n

\n

\n\thard:setPosition(0, 20)\n

\n

\n\thard:setTag(2)\n

\n

\n\t— 创建菜单,最后不需要加NULL\n

\n

\n\tmenu = cc.Menu:create(normal, hard)\n

\n

\n\tself:addChild(menu)\n

\n

\n\t— 菜单项回调\n

\n

\n\tnormal:registerScriptTapHandler(menuCallback)   — 按钮事件\n

\n

\n\thard:registerScriptTapHandler(menuCallback)     — 按钮事件\n

\n

\n\t//\n

\n

\n\t5.4、按钮控件事件回调 ControlButton\n

\n

\n\t在C++中,按钮控件事件回调参见:《Cocos2d-x 3.x基础总结 — 按钮控件CCControlButton总结》\n

\n

\n\t在Lua中,使用:registerControlEventHandler(hander, type) 。\n

\n

\n\t其中 hander 为我们需要绑定的回调函数,而 type 则是按钮事件的类型。\n

\n

\n\t至于回调函数中有什么参数,参见下面的例子。\n

\n

\n\t对于 type ,有以下几种类型:\n

\n

\n\t//\n

\n

\n\tcc.CONTROL_EVENTTYPE_TOUCH_DOWN         — 刚刚开始触摸按钮时\n

\n

\n\tcc.CONTROL_EVENTTYPE_DRAG_INSIDE        — 在内部拖动时(保持触摸状态下)\n

\n

\n\tcc.CONTROL_EVENTTYPE_DRAG_OUTSIDE       — 在外部拖动时(保持触摸状态下)\n

\n

\n\tcc.CONTROL_EVENTTYPE_DRAG_ENTER         — 拖动刚进入内部时(保持触摸状态下)\n

\n

\n\tcc.CONTROL_EVENTTYPE_DRAG_EXIT          — 拖动刚离开内部时(保持触摸状态下)\n

\n

\n\tcc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE    — 在内部抬起手指(保持触摸状态下)\n

\n

\n\tcc.CONTROL_EVENTTYPE_TOUCH_UP_OUTSIDE   — 在外部抬起手指(保持触摸状态下)\n

\n

\n\tcc.CONTROL_EVENTTYPE_TOUCH_CANCEL       — 取消触点时\n

\n

\n\tcc.CONTROL_EVENTTYPE_VALUE_CHANGED      — 按钮控件中值发生改变时\n

\n

\n\t//\n

\n

\n\t使用举例:\n

\n

\n\t//\n

\n

\n\t— node : 执行回调的按钮对象\n

\n

\n\t— type : 按钮事件的类型\n

\n

\n\tlocal function btnCallback(node, type)\n

\n

\n\tif type == cc.CONTROL_EVENTTYPE_TOUCH_DOWN then\n

\n

\n\tprint(“touch down”)\n

\n

\n\telseif type == cc.CONTROL_EVENTTYPE_DRAG_INSIDE then\n

\n

\n\tprint(“drag inside”)\n

\n

\n\telseif type == cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE then\n

\n

\n\tprint(“touch up inside”)\n

\n

\n\tend\n

\n

\n\tend\n

\n

\n\t— 添加一个按钮 ControlButton\n

\n

\n\tlocal label = cc.Label:createWithSystemFont(“button”,”res/fonts/Marker Felt.ttf”,30)\n

\n

\n\tlocal sprite = cc.Scale9Sprite:create(“normal.png”)\n

\n

\n\tlocal btn = cc.ControlButton:create(label,sprite)\n

\n

\n\tbtn:setPosition(winSize.width/2, winSize.height/2)\n

\n

\n\tself:addChild(btn)\n

\n

\n\t— 按钮事件回调\n

\n

\n\tbtn:registerControlEventHandler(btnCallback,cc.CONTROL_EVENTTYPE_TOUCH_DOWN)\n

\n

\n\tbtn:registerControlEventHandler(btnCallback,cc.CONTROL_EVENTTYPE_DRAG_INSIDE)\n

\n

\n\tbtn:registerControlEventHandler(btnCallback,cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE)\n

\n

\n\t//\n

\n

\n\t6、Lua中的事件分发机制\n

\n

\n\t在C++中,事件分发机制参见:《Cocos2d-x 3.x新事件分发机制总结》\n

\n

\n\t事件分发机制包含:\n

\n

\n\t触摸事件 : EventListenerTouchOneByOne、EventListenerTouchAllAtOnce\n

\n

\n\t鼠标响应事件 : EventListenerMouse\n

\n

\n\t键盘响应事件 : EventListenerKeyboard\n

\n

\n\t加速计事件 : EventListenerAcceleration\n

\n

\n\t自定义事件 : EventListenerCustom\n

\n

\n\t物理碰撞事件 : EventListenerPhysicsContact\n

\n

\n\t游戏手柄事件 : EventListenerController\n

\n

\n\t而在Cocos2d-x v3.2版本中,Lua的使用方式与C++有点类似。\n

\n

\n\tPS:在Lua中对于鼠标事件、自定义事件的支持有BUG,建议大家暂时不要去使用。\n

\n

\n\t另外由于博主还未接触过物理碰撞事件、游戏手柄事件,所以也无法讲解着两个事件机制的使用方法,不过可以确定的一点是:以上几个事件处理都是通过监听器来完成的,所以用法应该都是差不多的。\n

\n

\n\t在这里我重点讲一下:触摸事件、键盘事件、加速计事件。\n

\n

\n\t事件处理的原理可以参考C++的使用方法,这里讲一下Lua中如何使用。\n

\n

\n\t6.1、使用步骤\n

\n

\n\t还是继续用代码来讲解吧,一般性都分为以下四个步骤。\n

\n

\n\t— 1.获取事件分发器  : EventDispatcher\n

\n

\n\tlocal dispatcher = cc.Director:getInstance():getEventDispatcher()\n

\n

\n\t— 2.创建事件监听器  : EventListener (这里以单点触摸为例)\n

\n

\n\tlocal listener = cc.EventListenerTouchOneByOne:create()\n

\n

\n\t— 3.注册事件响应函数: registerScriptHandler\n

\n

\n\t— hander : 响应函数\n

\n

\n\t— type   : 事件类型\n

\n

\n\tlistener:registerScriptHandler(hander, type)\n

\n

\n\t— 4.在事件分发器中,添加监听器。事件响应委托为self\n

\n

\n\tdispatcher:addEventListenerWithSceneGraphPriority(listener, self)\n

\n

\n\t//\n

\n

\n\t6.2、单点触摸事件EventListenerTouchOneByOne\n

\n

\n\t使用方法如下:\n

\n

\n\t响应函数的两个参数 touch , event 分别表示:\n

\n

\n\ttouch : cc.Touch 。触点信息\n

\n

\n\tevent : cc.Event 。事件信息\n

\n

\n\t注册响应函数 registerScriptHandler 中的第二个参数,表示事件类型。\n

\n

\n\tcc.Handler.EVENT_TOUCH_BEGAN : 触摸开始\n

\n

\n\tcc.Handler.EVENT_TOUCH_MOVED : 触摸移动\n

\n

\n\tcc.Handler.EVENT_TOUCH_ENDED : 触摸结束\n

\n

\n\t//\n

\n

\n\t— 触摸开始\n

\n

\n\tlocal function onTouchBegan(touch, event)\n

\n

\n\tprint(“Touch Began”)\n

\n

\n\tlocal pos = touch:getLocation() — 获取触点的位置\n

\n

\n\tprint(pos.x .. ” , ” .. pos.y)  — 输出log\n

\n

\n\treturn true                     — 必须返回true 后边move end才会被处理\n

\n

\n\tend\n

\n

\n\t— 触摸移动\n

\n

\n\tlocal function onTouchMoved(touch, event)\n

\n

\n\tprint(“Touch Moved”)\n

\n

\n\tend\n

\n

\n\t— 触摸结束\n

\n

\n\tlocal function onTouchEnded(touch, event)\n

\n

\n\tprint(“Touch Ended”)\n

\n

\n\tend\n

\n

\n\t— 注册单点触摸\n

\n

\n\tlocal dispatcher = cc.Director:getInstance():getEventDispatcher()\n

\n

\n\tlocal listener = cc.EventListenerTouchOneByOne:create()\n

\n

\n\tlistener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)\n

\n

\n\tlistener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED)\n

\n

\n\tlistener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED)\n

\n

\n\tdispatcher:addEventListenerWithSceneGraphPriority(listener, self)\n

\n

\n\t//\n

\n

\n\t6.3、多点触摸事件EventListenerTouchAllAtOnce\n

\n

\n\t使用方法如下:\n

\n

\n\t响应函数的两个参数 touches , event 分别表示:\n

\n

\n\ttouches : cc.Touch的table数组 。多个触点信息\n

\n

\n\tevent : cc.Event 。事件信息\n

\n

\n\t注册响应函数 registerScriptHandler 中的第二个参数,表示事件类型。\n

\n

\n\tcc.Handler.EVENT_TOUCHES_BEGAN : 多点触摸开始\n

\n

\n\tcc.Handler.EVENT_TOUCHES_MOVED : 多点触摸移动\n

\n

\n\tcc.Handler.EVENT_TOUCHES_ENDED : 多点触摸结束\n

\n

\n\t//\n

\n

\n\t— 触摸开始\n

\n

\n\tlocal function onTouchesBegan(touches, event)\n

\n

\n\tprint(“Touches Began”)\n

\n

\n\tlocal pos1 = touches[1]:getLocation()   — 获取触点1的位置\n

\n

\n\tlocal pos2 = touches[2]:getLocation()   — 获取触点2的位置\n

\n

\n\tlocal delta = {\n

\n

\n\tx = pos2.x – pos1.x ,\n

\n

\n\ty = pos2.y – pos1.y\n

\n

\n\t}\n

\n

\n\tprint(delta.x .. ” , ” .. delta.y)      — 输出log\n

\n

\n\tend\n

\n

\n\t— 触摸移动\n

\n

\n\tlocal function onTouchesMoved(touches, event)\n

\n

\n\tprint(“Touches Moved”)\n

\n

\n\tend\n

\n

\n\t— 触摸结束\n

\n

\n\tlocal function onTouchesEnded(touches, event)\n

\n

\n\tprint(“Touches Ended”)\n

\n

\n\tend\n

\n

\n\t— 注册多点触摸\n

\n

\n\tlocal dispatcher = cc.Director:getInstance():getEventDispatcher()\n

\n

\n\tlocal listener = cc.EventListenerTouchAllAtOnce:create()\n

\n

\n\tlistener:registerScriptHandler(onTouchesBegan, cc.Handler.EVENT_TOUCHES_BEGAN)\n

\n

\n\tlistener:registerScriptHandler(onTouchesMoved, cc.Handler.EVENT_TOUCHES_MOVED)\n

\n

\n\tlistener:registerScriptHandler(onTouchesEnded, cc.Handler.EVENT_TOUCHES_ENDED)\n

\n

\n\tdispatcher:addEventListenerWithSceneGraphPriority(listener, self)\n

\n

\n\t//\n

\n

\n\t6.4、键盘事件EventListenerKeyboard\n

\n

\n\tEventListenerKeyboard,主要用于监听键盘某个键的按下、松开的事件。\n

\n

\n\t使用方法如下:\n

\n

\n\t响应函数的两个参数 keyCode , event 分别表示:\n

\n

\n\tkeyCode : number 。键盘按键枚举值\n

\n

\n\tevent : cc.Event 。事件信息\n

\n

\n\t注册响应函数 registerScriptHandler 中的第二个参数,表示事件类型。\n

\n

\n\tcc.Handler.EVENT_KEYBOARD_PRESSED : 按下键盘的某个键\n

\n

\n\tcc.Handler.EVENT_KEYBOARD_RELEASED : 松开键盘的某个键\n

\n

\n\t键盘按键枚举值如下:(仅举例说明)\n

\n

\n\tcc.KeyCode.KEY_A : A键\n

\n

\n\tcc.KeyCode.KEY_1 : 1键\n

\n

\n\tcc.KeyCode.KEY_F1 : F1键\n

\n

\n\tcc.KeyCode.KEY_SPACE : 空格键\n

\n

\n\tcc.KeyCode.KEY_ALT : ALT键\n

\n

\n\tcc.KeyCode.KEY_SHIFT : SHIFT键\n

\n

\n\t//\n

\n

\n\tlocal function onKeyPressed(keyCode, event)\n

\n

\n\tif keyCode == cc.KeyCode.KEY_A then\n

\n

\n\tprint(“Pressed A !”)  — 按下A键\n

\n

\n\tend\n

\n

\n\tend\n

\n

\n\tlocal function onKeyReleased(keyCode, event)\n

\n

\n\tif keyCode == cc.KeyCode.KEY_J then\n

\n

\n\tprint(“Released J !”) — 松开J键\n

\n

\n\tend\n

\n

\n\tend\n

\n

\n\t— 注册键盘事件\n

\n

\n\tlocal dispatcher = cc.Director:getInstance():getEventDispatcher()\n

\n

\n\tlocal listener = cc.EventListenerKeyboard:create()\n

\n

\n\tlistener:registerScriptHandler(onKeyPressed, cc.Handler.EVENT_KEYBOARD_PRESSED)\n

\n

\n\tlistener:registerScriptHandler(onKeyReleased, cc.Handler.EVENT_KEYBOARD_RELEASED)\n

\n

\n\tdispatcher:addEventListenerWithSceneGraphPriority(listener, self)\n

\n

\n\t//\n

\n

\n\t6.5、加速计事件EventListenerAcceleration\n

\n

\n\tEventListenerAcceleration,主要用于监听移动设备的所受重力方向感应事件。\n

\n

\n\t重力感应来自移动设备的加速计,通常支持 (X, Y, Z) 三个方向的加速度感应,所以又称为三向加速计。在实际应用中,可以根据3个方向的力度大小来计算手机倾斜的角度或方向。\n

\n

\n\tEventListenerAcceleration用法和上述几个有点不同。\n

\n

\n\t使用方法如下:\n

\n

\n\t响应函数有五个参数 event , x , y , z , timestamp 分别表示:\n

\n

\n\tevent : cc.Event事件信息\n

\n

\n\t(x, y, z) : number 设备在三个方向上的重力加速度感应\n

\n

\n\ttimestamp : number 响应事件的时间戳\n

\n

\n\t创建加速计监听器时,直接传入响应函数作为参数,而不用registerScriptHandler 。\n

\n

\n\t使用加速计事件时,还需要开启设备的加速计感应:\n

\n

\n\tself:setAccelerometerEnabled(true)\n

\n

\n\t在电脑上看不到效果,需要在设备上才能看到效果。\n

\n

\n\t//\n

\n

\n\t— 开启设备的加速计感应\n

\n

\n\tself:setAccelerometerEnabled(true)\n

\n

\n\t— 响应函数\n

\n

\n\tlocal function onAccelerationEvent(event, x, y, z, timestamp)\n

\n

\n\tprint(“x: ” .. x)\n

\n

\n\tprint(“y: ” .. y)\n

\n

\n\tprint(“z: ” .. z)\n

\n

\n\tprint(“timestamp: ” .. timestamp)\n

\n

\n\tend\n

\n

\n\t— 注册加速计监听器\n

\n

\n\tlocal dispatcher = cc.Director:getInstance():getEventDispatcher()\n

\n

\n\t— 直接传入 响应函数 作为参数\n

\n

\n\tlocal listener = cc.EventListenerAcceleration:create(onAccelerationEvent)\n

\n

\n\tdispatcher:addEventListenerWithSceneGraphPriority(listener, self)\n

\n

\n\t//\n

\n

\n\t7、Lua中的数学类\n

\n

\n\t在C++中,数学类参见:《Cocos2d-x 3.2 — 总结数学类Vec2/Size/Rect》\n

\n

\n\t数学类主要有Vec2(坐标向量)、Size(尺寸)、Rect(矩形)。\n

\n

\n\t7.1、创建\n

\n

\n\t在Lua中创建的 Vec2、Size、Rect 都是一个table类型。\n

\n

\n\t其中只有相应的成员变量,没有相关的函数运算。\n

\n

\n\t//\n

\n

\n\tcc.p(x, y)                    — 构造 Vec2\n

\n

\n\tcc.size(width, height)        — 构造 Size\n

\n

\n\tcc.rect(x, y, width, height)  — 构造 Rect\n

\n

\n\t//\n

\n

\n\t7.2、坐标向量运算\n

\n

\n\tLua中常用的向量运算如下:\n

\n

\n\t(1)返回值为bool\n

\n

\n\t//\n

\n

\n\t— 直线AB与直线CD是否相交\n

\n

\n\tcc.pIsLineIntersect(pA, pB, pC, pD,float,float)\n

\n

\n\t— 线段AB与线段CD是否相交\n

\n

\n\tcc.pIsSegmentIntersect(pA, pB, pC, pD)\n

\n

\n\t//\n

\n

\n\t(2)返回值为float\n

\n

\n\t//\n

\n

\n\tcc.pDot(p1, p2)         — 点积\n

\n

\n\tcc.pCross(p1, p2)       — 叉积\n

\n

\n\tcc.pProject(p1, p2)     — 投影: 前point在后point上的投影\n

\n

\n\tcc.pGetLength(p)        — 向量长度\n

\n

\n\tcc.pLengthSQ(p)         — 向量长度平方\n

\n

\n\tcc.pGetDistance(p1, p2) — 坐标距离\n

\n

\n\tcc.pDistanceSQ(p1, p2)  — 坐标距离平方\n

\n

\n\tcc.pGetAngle(p1, p2)    — 向量夹角:弧度\n

\n

\n\t//\n

\n

\n\t3)返回值为point_table\n

\n

\n\t//\n

\n

\n\tcc.p(x, y)                       — 构造坐标point\n

\n

\n\tcc.pAdd(p1, p2)                  — 相加\n

\n

\n\tcc.pSub(p1, p2)                  — 相减\n

\n

\n\tcc.pMidpoint(p1, p2)             — 两向量的中点\n

\n

\n\tcc.pNormalize(p1)                — 标准化向量\n

\n

\n\tcc.pGetClampPoint(minp, maxp, p) — 将p值限制在[minp,maxp]区间内\n

\n

\n\tcc.pForAngle(float)              — 返回坐标 x=cos(a) , y=sin(a)\n

\n

\n\tcc.pPerp(p)                      — 逆时针旋转90度(-y, x)\n

\n

\n\tcc.RPerp(p)                      — 顺时针旋转90度(y, -x)\n

\n

\n\t— 绕p1向量旋转\n

\n

\n\t— 返回向量: 角度 this.getAngle() +other.getAngle()\n

\n

\n\t—           长度 this.getLength()*other.getLength()\n

\n

\n\tcc.pRotate(p1, p2)\n

\n

\n\t— 绕p1向量旋转前的向量值\n

\n

\n\t— 返回向量: 角度 this.getAngle() -other.getAngle();\n

\n

\n\t—           长度 this.getLength()*other.getLength();\n

\n

\n\tcc.pUnrotate(p1, p2)\n

\n

\n\t— 直线AB与直线CD的交点\n

\n

\n\tcc.pGetIntersectPoint(pA, pB, pC, pD)\n

\n

\n\t//\n

\n

\n\t7.3、矩形运算\n

\n

\n\tLua中常用的矩形运算如下:\n

\n

\n\t//\n

\n

\n\tcc.rectGetMinX(rect)    — rect.x\n

\n

\n\tcc.rectGetMidX(rect)    — (rect.x + rect.width) / 2\n

\n

\n\tcc.rectGetMaxX(rect)    — rect.x + rect.width\n

\n

\n\tcc.rectGetMinY(rect)    — rect.y\n

\n

\n\tcc.rectGetMidY(rect)    — (rect.y + rect.height) / 2\n

\n

\n\tcc.rectGetMaxY(rect)    — rect.y + rect.height\n

\n

\n\t— 判断是否与rect相同. 原点相同,尺寸相同.\n

\n

\n\tcc.rectEqualToRect(rect1, rect2)\n

\n

\n\t— 判断point是否包含在矩形内\n

\n

\n\tcc.rectContainsPoint(rect, point)\n

\n

\n\t— 判断矩形是否相交. 常常用作碰撞检测.\n

\n

\n\tcc.rectIntersectsRect(rect1, rect2)\n

\n

\n\t— 两矩形合并\n

\n

\n\tcc.rectUnion(rect1, rect2)\n

\n

\n\t//\n

\n

\n\t8、Lua中的颜色类\n

\n

\n\t在C++的颜色类主要有三个:Color3B、Color4B、Color4F。并且有很多颜色的宏定义。\n

\n

\n\t在Lua中,无法使用颜色的宏定义,而需要自己设置。\n

\n

\n\t颜色类的使用方法如下:\n

\n

\n\t//\n

\n

\n\tcc.c3b(byte,byte,byte)              — 构造 Color3B\n

\n

\n\tcc.c4b(byte,byte,byte,byte)         — 构造 Color4B\n

\n

\n\tcc.c4f(float,float,float,float)     — 构造 Color4F\n

\n

\n\t//\n

\n

\n\t9、最后,我还想讲讲一些使用Lua开发Cocos2d-x的注意事项\n

\n

\n\t9.1、关于getPosition()\n

\n

\n\t先来看看几个 getXXX() 函数的返回值吧。\n

\n

\n\t//\n

\n

\n\tgetPosition()      — 返回两个值:x y\n

\n

\n\tgetAnchorPoint()   — point_table\n

\n

\n\tgetContentSize()   — size_table\n

\n

\n\tgetBoundingBox()   — rect_table\n

\n

\n\t//\n

\n

\n\t可以发现:getPosition() 返回的不是point_table,而是两个值。\n

\n

\n\tPS:真是一个大坑!\n

\n

\n\t所以接收 getPosition() 时需要处理一下。\n

\n

\n\t//\n

\n

\n\t— 方法一 : 用两个变量接收\n

\n

\n\tlocal x, y = sprite:getPosition()\n

\n

\n\t— 方法二 : 转换为point_table\n

\n

\n\tlocal p = cc.p(sprite:getPosition())\n

\n

\n\t//\n

\n

\n\t9.2、关于(.)和(:)\n

\n

\n\t在Lua中,一定要区分这两个:点(.)和冒号(:)的区别,很容易搞混掉。\n

\n

\n\t定义的时候,冒号(:)默认接收self参数\n

\n

\n\t调用的时候,冒号(:)默认传递调用者自己为参数\n

\n

\n\t而点号(.)要显示传递或接收self参数\n

\n

\n\t例如:点号定义,需要显示传递或接收。\n

\n

\n\t//\n

\n

\n\ttab = { x = 1 }\n

\n

\n\tfunction tab.fun(self)\n

\n

\n\tprint(self.x)\n

\n

\n\tend\n

\n

\n\ta.fun(a)    — 需要将a本身做为参数传给fun函数\n

\n

\n\t//\n

\n

\n\t这样使用函数就要传递自身self,用起来很麻烦。\n

\n

\n\t所以Lua给出了一个方便的方法:将函数定义改成冒号: ,这样就可以省略self参数了。\n

\n

\n\t//\n

\n

\n\ta = { x = 1 }\n

\n

\n\tfunction a:fun()\n

\n

\n\tprint(self.x)\n

\n

\n\tend\n

\n

\n\ta:fun()\n

\n

\n\t//\n

作者信息

menghao

menghao

共发布了 3994 篇文章