加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

CC3.2+Lua(9) ——从C++过渡到Lua

发布时间:2020-12-14 22:05:09 所属栏目:大数据 来源:网络整理
导读:本文出自 “ 夏天的风 ” 博客,请务必保留此出处 http://www.voidcn.com/article/p-cmebpzex-wx.html? 本人只是出自学习方便特转到此处 标签: lua? cocos2dx 原创作品,允许转载,转载时请务必以超链接形式标明文章? 原始出处?、作者信息和本声明。否则将
本文出自 “夏天的风” 博客,请务必保留此出处http://www.voidcn.com/article/p-cmebpzex-wx.html? 本人只是出自学习方便特转到此处
标签: lua? cocos2dx
原创作品,允许转载,转载时请务必以超链接形式标明文章? 原始出处?、作者信息和本声明。否则将追究法律责任。 http://www.voidcn.com/article/p-cmebpzex-wx.html

【唠叨】

????现在开始学习Lua了,开始用?Cocos Code IDE?开发cocos2dx的游戏了。

????可是呢,因为 cocos2dx v3.x 刚刚才出来不久,所以网上的教程大部分都是基于C++版本的,

????而针对Lua版本的大部分都是老版本 v2.x 的教程,对于用 v3.x 的我来说,很多都不适用了。

????无奈之下只好自己摸索,经过几天的学习,积累了一些 Lua 与 C++ 开发cocos2dx游戏之间的差异。

????现在就在此总结一下。


【番外】

? ? Cocos2d-X官方就在2014年10月28日,发布了?Cocos引擎v1.0 Preview版?。

????将Cocos StudioCocos Code IDECocos2d-X?三件套进行了集成,一键部署安装。

????看着实在是太酷炫了,这也说明使用脚本语言 Lua 开发cocos2dx游戏必将越发流行。




【从C++过渡到Lua】


1、Lua中如何使用cocos2dx引擎中的类?

? ??在C++中是这样调用的:

1
2
3
4
5
//
???? Sprite*?sprite?=?Sprite::create();
sprite->setPosition(Vec2(100,?100));
???? this ->addChild(sprite);
//

????而在Lua中是这样调用的:

//
???? local? sprite?=?cc.Sprite: create ()
???? sprite:setPosition(cc.p(100,?100))
self:addChild(sprite)
//

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

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

????而调用类的函数,不是双冒号::?,而是一个冒号:?。


2、Lua 与 C++ 使用上有何差异?

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

????PS:我比较懒,所以用代码来代替文字描述了。

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//
winSize?=?cc.Director:getInstance():getWinSize()
?
?
--?继承Layer类
MenuLayer?=?class( "MenuLayer" ,? function ()
return? cc.Layer: ()
end )
?
?
--?初始化函数
function? MenuLayer:ctor()
self. name? =? "hello"????????? --?成员变量
size? =?cc. size (0,?0)??? --?成员变量
end
?
?
--?创建包含GameLayer的场景
MenuLayer:createScene()
scene?=?cc.Scene: ()
layer?=?MenuLayer: ()
scene:addChild(layer)
scene
end
?
?
--?创建GameLayer层
MenuLayer: ()
layer?=?MenuLayer.new()?? --?new()
layer:init()??????????????????? --?init()
layer
end
?
?
--?初始化
MenuLayer:init()
self:ShowUI()??????? --?添加界面元素(Sprite、Label等)
self:addBtn()??????? --?添加菜单按钮
self:addTouches()??? --?添加多点触摸
end
?
?
--?添加界面
MenuLayer:ShowUI()
?
???? --?背景图片Sprite
bg?=?cc.Sprite: ( "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" self.label:setPosition(winSize.width/2,?winSize.height/2)
self:addChild(self.label)
?
end
?
?
--?添加按钮
MenuLayer:addBtn()
?
menu
normal,?hard
?
--?回调函数
--?tag?为menuItem设置的标签setTag?,menuItem为相应对象
local? menuCallback(tag,?menuItem)
???????? print( "menuItem:?"? ..?tag)???? --?Lua中的输出语句
end
?
normal?=?cc.MenuItemImage: "normal.png" )
normal:setPosition(0,?120)
normal:setTag(1)
normal:registerScriptTapHandler(menuCallback)??? --?按钮事件
?
hard?=?cc.MenuItemImage: "hard.png" )
hard:setPosition(0,?20)
hard:setTag(2)
hard:registerScriptTapHandler(menuCallback)????? --?按钮事件
?
--?创建菜单,最后不需要加NULL
menu?=?cc.Menu: (normal,?hard)
self:addChild(menu)
?
end
?
?
--?多点触摸
MenuLayer:addTouches()
?
touch1,?touch2?=?cc.Touch,?cc.Touch
onTouchesBegan(touches,?event)
"Touches?Began" )
touch1?=?touches[1]????? --?第一个触点,下标从1开始
touch2?=?touches[2]????? --?第二个触点
???????? pos1?=?touch1:getLocation()??? --?获取触点1的位置
pos2?=?touch2:getLocation()??? --?获取触点2的位置
delta?=?{
???????????? x?=?pos2.x?-?pos1.x?,
y?=?pos2.y?-?pos1.y
}
print(delta.x?..? "?,?"? ..?delta.y)?? --?输出log
end
?
onTouchesMoved(touches,?event)
"Touches?Moved" )
end
?
onTouchesEnded(touches,?event)
"Touches?Ended" )
end
?
--?注册多点触摸
dispatcher?=?cc.Director:getInstance():getEventDispatcher()
listener?=?cc.EventListenerTouchAllAtOnce: ()
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
//


3、Lua中的字符串格式转换?

????C++中是这样使用的:

3
????
sprintf (str,? "hero_%02d.png" 而在Lua中则是使用?string.format()?函数。

string.format( "hero_%02d.png" 4、Lua中的枚举类型

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

????而在Lua中将其变成形如:cc.CONTROL_STATE_NORMAL?。

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

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

119
--?ResolutionPolicy?屏幕适配(就这个比较奇葩。。。)
--?含义参见:http://shahdza.blog.51cto.com/2410787/1550089
cc.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/1543349
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
?
--?Control::State?控件状态
--?含义参见:http://shahdza.blog.51cto.com/2410787/1543349
cc.CONTROL_STATE_NORMAL
cc.CONTROL_STATE_DISABLED
cc.CONTROL_STATE_SELECTED
cc.CONTROL_STATE_HIGH_LIGHTED
?
?
--?EditBox::EditBoxInputMode?文本框虚拟键盘的编辑类型
--?含义参见:http://shahdza.blog.51cto.com/2410787/1544213
cc.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/1544213
cc.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/1544213
cc.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/1544983
cc.SCROLLVIEW_DIRECTION_BOTH
cc.SCROLLVIEW_DIRECTION_VERTICAL
cc.SCROLLVIEW_DIRECTION_HORIZONTAL
?
?
--?TableView::VerticalFillOrder?列表视图排列方式
--?含义参见:http://shahdza.blog.51cto.com/2410787/1545383
cc.TABLEVIEW_FILL_TOPDOWN
cc.TABLEVIEW_FILL_BOTTOMUP
?
?
--?ProgressTimer::Type
--?含义参见:http://shahdza.blog.51cto.com/2410787/1546707
cc.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/1547636
cc.PARTICLE_MODE_RADIUS
cc.PARTICLE_MODE_GRAVITY
?
?
--?TransitionScene::Orientation?场景切换方向
--?含义参见:http://shahdza.blog.51cto.com/2410787/1547977
cc.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/1560612
cc.VERTICAL_TEXT_ALIGNMENT_TOP
cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM
cc.VERTICAL_TEXT_ALIGNMENT_CENTER
?
--?TextHAlignment?文本的水平对其方式
--?含义参见:http://shahdza.blog.51cto.com/2410787/1560612
cc.TEXT_ALIGNMENT_LEFT
cc.TEXT_ALIGNMENT_RIGHT
cc.TEXT_ALIGNMENT_CENTER
//


5、Lua中的事件回调

????cocos2dx中常用的事件回调有如下:

????????> 动作回调 ? ? ? ? :?CallFunc

????????> 定时器刷新 ? ? ? :?schedule

????????> 菜单项事件回调 ? :?menuItem

????????> 按钮控件事件回调 :?ControlButton

????在cocos2dx v3.2中,由于支持了C++ 11,使用 std::bind 集成了?CC_CALLBACK_*?。

? ? 在Lua中可不能这样方便的使用。


??5.1、动作回调 CallFunc

????在C++中,动作回调参见:http://www.voidcn.com/article/p-kiicpnup-wx.html

? ? 在Lua中只剩下一个 CallFunc?,其定义如下:

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

--?hander?:?执行的回调函数
--?value??:?传递给回调函数的参数,必须为一个table
cc.CallFunc: (hander,?value)
//

????使用举例:

16
--?node?:?执行动作的对象
--?tab??:?传过来的参数,?必须为一个table
callbackFunc(node,?tab)
node:setScale(2)
"x="? ..?tab.x?..? ",y="? ..?tab.y)
end
?
)
sprite:setPosition(winSize.width/2,?winSize.height/2)
self:addChild(sprite)
?
--?CallFunc回调动作
call?=?cc.CallFunc: (callbackFunc,?{x=1?,?y=2}?)
sprite:runAction(call)
//


??5.2、定时器刷新 schedule

????在C++中,定时器参见:http://www.voidcn.com/article/p-hdoaqjqx-wx.html

? ??在Lua中,有两种方式:

????(1)self:scheduleUpdateWithPriorityLua(update,priority)

????????> 参数一:刷新函数

????????> 参数二:刷新优先级

????????其中 self 为 Node类 的子类。

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

????(2)scheduler:scheduleScriptFunc(update,inteval,false)

????????> 参数一:刷新函数

????????> 参数二:每次刷新的时间间隔

????????> 参数三:是否只执行一次。false为无限次。

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

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

????使用举例:

20
scheduler,?myupdate
timer?=?0
?????
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( false )
5.3、菜单项事件回调 menuItem

????在C++中,菜单项回调参见:http://www.voidcn.com/article/p-kiicpnup-wx.html

? ? 在Lua中,使用:registerScriptTapHandler(hander)?。

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

????使用举例:

27
menu
?
--?tag??????:?为menuItem设置的标签setTag
--?menuItem?:?执行回调的menuItem对象
..?tag)
end
?
)
normal:setTag(1)
?
)
hard:setTag(2)
?
--?创建菜单,最后不需要加NULL
self:addChild(menu)
?
?????
--?菜单项回调
--?按钮事件
--?按钮事件
5.4、按钮控件事件回调 ControlButton

????在C++中,按钮控件事件回调参见:http://www.voidcn.com/article/p-azrzmrlp-wx.html

? ? 在Lua中,使用:registerControlEventHandler(hander,type)?。

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

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

? ??对于?type?,有以下几种类型:

11
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?????? --?按钮控件中值发生改变时
使用举例:

25
--?node?:?执行回调的按钮对象
--?type?:?按钮事件的类型
btnCallback(node,?type)
if?type?==?cc.CONTROL_EVENTTYPE_TOUCH_DOWN? then
"touch?down" )
elseif?type?==?cc.CONTROL_EVENTTYPE_DRAG_INSIDE? then
"drag?inside" )
elseif?type?==?cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE? then
"touch?up?inside" )
--?添加一个按钮?ControlButton
label?=?cc.Label:createWithSystemFont( "button" sprite?=?cc.Scale9Sprite: )
btn?=?cc.ControlButton: (label,sprite)
btn:setPosition(winSize.width/2,?winSize.height/2)
self:addChild(btn)
?
--?按钮事件回调
btn:registerControlEventHandler(btnCallback,cc.CONTROL_EVENTTYPE_TOUCH_DOWN)
6、Lua中的事件分发机制

????在C++中,事件分发机制参见:http://www.voidcn.com/article/p-zwifwspg-wx.html

????事件分发机制包含:

? ? ????>?触摸事件 ? ??:?EventListenerTouchOneByOneEventListenerTouchAllAtOnce

????????>?鼠标响应事件?:?EventListenerMouse

????????>?键盘响应事件?:?EventListenerKeyboard

????????>?加速计事件 ??:?EventListenerAcceleration

????????>?自定义事件 ??:?EventListenerCustom

????????>?物理碰撞事件?:?EventListenerPhysicsContact

????????>?游戏手柄事件?:?EventListenerController

????而在cocos2dx v3.2版本中,Lua的使用方式与C++有点类似。

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

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

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

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

????

??6.1、使用步骤

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

15
--?1.获取事件分发器??:?EventDispatcher
dispatcher?=?cc.Director:getInstance():getEventDispatcher()
?
--?2.创建事件监听器??:?EventListener?(这里以单点触摸为例)
listener?=?cc.EventListenerTouchOneByOne: ()
?
--?3.注册事件响应函数:?registerScriptHandler
--?hander?:?响应函数
--?type???:?事件类型
listener:registerScriptHandler(hander,?type)
?
--?4.在事件分发器中,添加监听器。事件响应委托为self
6.2、单点触摸事件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?: 触摸结束

29
--?触摸开始
onTouchBegan(touch,?event)
"Touch?Began" )
pos?=?touch:getLocation()? --?获取触点的位置
print(pos.x?..? ..?pos.y)?? return? true????????????????????? --?必须返回true?后边move?end才会被处理
end
?
--?触摸移动
onTouchMoved(touch,?event)
"Touch?Moved" )
end
?
--?触摸结束
onTouchEnded(touch,?event)
"Touch?Ended" )
end?
?
--?注册单点触摸
dispatcher?=?cc.Director:getInstance():getEventDispatcher()
()
?
listener:registerScriptHandler(onTouchBegan,?cc.Handler.EVENT_TOUCH_BEGAN)
listener:registerScriptHandler(onTouchMoved,?cc.Handler.EVENT_TOUCH_MOVED)
listener:registerScriptHandler(onTouchEnded,?cc.Handler.EVENT_TOUCH_ENDED)
?
6.3、多点触摸事件EventListenerTouchAllAtOnce

? ??touches?,0)">touches?:?cc.Touch的table数组?。多个触点信息

????????????>?event ??:?cc.Event ? ? ? ? ? ?。事件信息

????????> 注册响应函数?cc.Handler.EVENT_TOUCHES_BEGAN?: 多点触摸开始

????????????>?cc.Handler.EVENT_TOUCHES_MOVED?: 多点触摸移动

????????????>?cc.Handler.EVENT_TOUCHES_ENDED?: 多点触摸结束

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!