![Cocos2d-JS游戏开发快速入门到实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/782/26793782/b_26793782.jpg)
3.2 实现菜单
游戏中最常用的交互方式就是使用菜单按钮了,本节来实现Cocos2d-JS的菜单。Cocos中的菜单分为两部分,一个是Menu,一个是Menu下的MenuItem,一个Menu是由一个或多个MenuItem组成的,MenuItem又有MenuItemFont、MenuItem Image、MenuItemAtlasFont、MenuItemLabel、MenuItemSprite、MenuItemToggle等具体的菜单实现方式。
Menu与MenuItem以及MenuItem的各种实现子类的关系如图3-2所示。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P49_506.jpg?sign=1739356028-9KCGNKVvm21Nsh7kLy2U0eFwwM54gEgv-0-76783503b074deedab71bdd9d1c45722)
图3-2 Menu、MenuItem及其子类关系图
图3-2清楚地描述了菜单中各种类的继承关系,其中Menu相当于一个菜单图层,里面放着各种各样的MenuItem,当然,在Cocos2d-JS中所有类的根都是Node。由该图可以看出,菜单项可以分为三大类,即文字菜单(MenuItemLabel)、精灵菜单(MenuItemSprite)和开关菜单(MenuItemToggle)。
以下通过具体的代码实现,从如何创建一个菜单开始来了解Cocos2d-JS的代码编写,本节的所有代码都在MenuDemo项目中。
3.2.1 实现文字菜单
文字菜单就是MenuItemLabel、MenuItemFont和MenuItemAtlasFont这3种,其中文字菜单的父类是MenuItemLabel,查看源码,可以看到它的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P50_5696.jpg?sign=1739356028-9absGE4Cp6hM8T2YNqhKTnrrhPe30mL3-0-87da0c1949866c110b7b518a80f39a29)
可以看出,它需要的构造方法的参数有label、selector和target,分别代表Label控件、回调方法和添加的节点。以下代码是创建一个MenuItemLabel菜单项,使用LabelTTF标签,文字内容为MenuItemLabel,字体为Aria、字号为50,回调函数在控制台打印输出“LabelTTF, Aria,50”。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P50_5697.jpg?sign=1739356028-SdzLo4zQ3plWcTLSVTtoF8mkh0LbWnrM-0-ce7dee8df0bc83e33164ff492b692442)
同样,MenuItemLabel的子类MenuItemFont的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P51_5698.jpg?sign=1739356028-BsLEDJpLsBFRUqFrqf7AMjeFsPZyXjxA-0-e560e5af866957ccaadfb373d9f31c59)
由源码的构造方法可以看出,它的参数只有value、callback和target,分别代表文字、回调函数和添加的节点。从代码实现可以看出,它实际上也是实例化了Menu ItemLabel,只不过提供了Label的默认实现,简化了文字菜单的生成步骤。以下代码是生成一个MenuItemFont菜单项,文本内容为MenuItemFont,回调函数打印日志输出“MenuItemFont”。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P51_5699.jpg?sign=1739356028-U0MBsXzccVoseH24Bsv7HjO4wJWi5fNM-0-a13c569cb8f1aa77cd205dac437dc8dd)
MenuItemLabel的另一个子类MenuItemAtlasFont相对复杂一点,它的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P51_5700.jpg?sign=1739356028-sOJqDGRRATdY1KVM3HlqvuqMiECI5xi4-0-85df1f10311d349e52d83c7ab09c23ed)
MenuItemAtlasFont是基于图片集的文本菜单项,它的参数value、charMapFile、itemWidth、itemHeight、startCharMap、callback和target分别代表显示文本、图片集合文件、要截取的文字的图片宽度、要截取的文字的图片高度、图片起始字符、回调函数和添加的节点。
MenuItemAtlasFont是以自定义的文字图集来显示,可以用于显示游戏中的特定字体,以下代码创建了一个自定义字体的MenuItemAtlasFont菜单项。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P52_5702.jpg?sign=1739356028-UfxfLcNVr9SiaHkMLLV1ROFMiF3VjGdz-0-35e676057ab990497be4c82b7ef64041)
以上是对所有文字菜单的介绍,在创建好了菜单项之后还需要创建Menu对象,再将这些MenuItem都放在Menu上,最后将Menu放到Layer图层上,代码如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P52_5703.jpg?sign=1739356028-c51u25aDX25cZ7al8cN1iqb1vdnOG2O2-0-9117810e4e9db8277d4c11c9793a989a)
写完以上代码后再运行项目,可以看到如图3-3所示的效果。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P52_583.jpg?sign=1739356028-jv3wMetvzWwcRmitgQHeP7IEInddzP7B-0-f5d569b779d5da8e9078a847e32d6766)
图3-3 文字菜单运行效果
3.2.2 实现精灵菜单
与文字菜单相比,精灵菜单能显示更加丰富的元素,精灵菜单的父类是MenuItemSprite,从源码看,它的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P54_5704.jpg?sign=1739356028-1cPbm20I6cJk7ll2oFWLi9hyMrdyjXrQ-0-f23f316f63f654766b82a463bf5399b5)
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P55_5705.jpg?sign=1739356028-JZ8QaZahBWC2hzvv7UyGuO07MpwHTMo8-0-07c36e7fbd7ec41071bc3b396876ba72)
如代码所示,MenuItemSprite的构造方法需要传5个参数,分别是normalSprite、selectedSprite、three、four、five,它们代表的含义分别是正常状态的Sprite、选中状态的Sprite、禁用状态的Sprite或添加节点、回调函数名字字符串或回调函数实现或添加节点、回调函数名字字符串或回调函数。由构造函数看出可根据需要选择是否构造参数来创建MenuItemSprite对象。
游戏中一些需要不同状态的精灵显示就需要用MenuItemSprite来实现,如下面的代码是创建了一个普通状态为图片是item1的精灵、选中状态为图片是item2的精灵、回调函数在控制台打印输出“MenuItemSprite”的MenuItemSprite菜单项。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P55_5706.jpg?sign=1739356028-p9AVMVqvMnN7mQ2tjdNQrUFntk8knhVM-0-a8746896d4ab997f0af9f9a774c5b4a9)
在很多情况下不需要很复杂的精灵显示,只需要几张图片即可,而使用MenuItemSprite还需要创建几个精灵,再来创建菜单项,如果只想创建几张图片构成的菜单项,就可以使用MenuItemSprite的子类MenuItem Image,它的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P55_5707.jpg?sign=1739356028-IotFflSoM4SBQkFUah3EyDEhDgA0qU3d-0-926dbc021c96be4be4ffb73f04c63dc9)
它的参数是normalImage、selected Image、three、four、five,分别代表正常状态图片、选中状态图片、禁用状态图片、回调函数和添加的节点。与MenuItemSprite相比,MenuItem Image省去了创建精灵的步骤,可以看到创建精灵的步骤都在构造函数中实现了,然后再调用MenuItemSprite,原理一样,但实现会更加容易。
例如,下面的代码创建了一个普通状态为图片是item1、选中状态为图片是item2、回调函数在控制台打印输出“MenuItem Image”的MenuItem Image菜单项。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P56_5709.jpg?sign=1739356028-LLyIrAcfaNDiYBXGV9rkKQLqlYoaiBqI-0-7cb23b52f1079da366ea6bb368d4005d)
将以上代码添加在上面的代码后面,再运行项目,可以看到如图3-4所示的效果。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P56_639.jpg?sign=1739356028-ujJKVx5dxcjwmJ6Q5SEuzmxB6M5p5hW2-0-f04b40527876e309971384d40fcb161e)
图3-4 精灵菜单运行效果
3.2.3 实现开关菜单
开关菜单只有一个实现类,也就是MenuItemToggle,相比文字菜单项和精灵菜单项,开关菜单项相对来说用的比较少。开关菜单项是为了实现两个菜单项之间可以切换的效果。查看源码可以看到MenuItemToggle的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P57_5710.jpg?sign=1739356028-eJnTAIzPpLfqUwwRFiccHsnVJ4fqIhI3-0-1df78e5d0a59e6590ca1ae62c1b547e7)
从构造方法只能看到它把参数直接传递给了this.initWithItems,再具体往下看,看看这个调用的方法又做了什么事情。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P57_5711.jpg?sign=1739356028-A1yuXjiyC2Hzl6dKzfzG4mDIee1IFEM8-0-96da421803c457b48285b59869f447a8)
从这个方法就可以看到从构造方法传进来的参数都做什么了,首先判断参数的个数,参数的前几个是MenuItem子项,然后根据参数中回调方法的位置来调用initWithCallback方法,构造MenuItem,可以再看看initWithCallback方法。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P58_5713.jpg?sign=1739356028-RiYRjlMwhaHhCFuu9hfQ6799e6VdsvHh-0-de3c789045c00f15ad12667fb2e9f7c2)
由以上几段代码可以总结出,创建MenuItemToggle可以带一个MenuItem数组,可以有一个或两个,还需要带一个回调方法。
MenuItemToggle非常适合在游戏中有状态切换的菜单项,如复选框是否选中状态等。例如下面的代码是创建文本“ON”的菜单项和文本“OFF”的菜单项和一个回调方法,单击输出切换状态。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P58_5714.jpg?sign=1739356028-FEPvSVr2SiSU47yky95Xuggb2C18MHwX-0-68661931669fc41448a286a2414967aa)
继续将上面的代码添加到之前的代码后面,运行效果如图3-5所示。