![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=1739149452-6bxad0keYLlWIAnXnB736Bs1xqfq0k5x-0-0bc1467c26e95a9cc762a23551db274b)
图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=1739149452-y7JrGdpv4ixiKYS36PBX5rXeCGBgGPr4-0-84f180cba3bfb4028b700a588608aceb)
可以看出,它需要的构造方法的参数有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=1739149452-FFAozE1gAL1BAhhi7Pzq9zaNFxLxprvX-0-f683224adaf4f4882e29f23fd1ca9e9f)
同样,MenuItemLabel的子类MenuItemFont的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P51_5698.jpg?sign=1739149452-bFdfja6fbFqFQIR7nzOW7msJ3Yjevbam-0-1caebeb62df5cd5ebb71d0b8517b4d50)
由源码的构造方法可以看出,它的参数只有value、callback和target,分别代表文字、回调函数和添加的节点。从代码实现可以看出,它实际上也是实例化了Menu ItemLabel,只不过提供了Label的默认实现,简化了文字菜单的生成步骤。以下代码是生成一个MenuItemFont菜单项,文本内容为MenuItemFont,回调函数打印日志输出“MenuItemFont”。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P51_5699.jpg?sign=1739149452-TbGekSDkZjp4Dl9EZtzSHepQ2YvrifGY-0-90580aa6501f77526a3ee10605c2eeb6)
MenuItemLabel的另一个子类MenuItemAtlasFont相对复杂一点,它的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P51_5700.jpg?sign=1739149452-sD1tNNnjHpDPiapjlHP8oyDk9TKc6lHq-0-35b10d6ff789ff63e18d6752ab50842c)
MenuItemAtlasFont是基于图片集的文本菜单项,它的参数value、charMapFile、itemWidth、itemHeight、startCharMap、callback和target分别代表显示文本、图片集合文件、要截取的文字的图片宽度、要截取的文字的图片高度、图片起始字符、回调函数和添加的节点。
MenuItemAtlasFont是以自定义的文字图集来显示,可以用于显示游戏中的特定字体,以下代码创建了一个自定义字体的MenuItemAtlasFont菜单项。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P52_5702.jpg?sign=1739149452-ZmLepUKXlcbsCxzzc1GA0GZUYYF88aiv-0-840c9acd60906f09bcce77d11d40487e)
以上是对所有文字菜单的介绍,在创建好了菜单项之后还需要创建Menu对象,再将这些MenuItem都放在Menu上,最后将Menu放到Layer图层上,代码如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P52_5703.jpg?sign=1739149452-5uyZ0ZmEkO8ktFXYi43T48GdVJrs4PFH-0-8df6fbbd3683b92ebc3a42abd164f028)
写完以上代码后再运行项目,可以看到如图3-3所示的效果。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P52_583.jpg?sign=1739149452-tQJLcdLzsr6UR7Gf3TTVrPShgvF8rvNN-0-bef42b2919a43a6d541827864c1b54b3)
图3-3 文字菜单运行效果
3.2.2 实现精灵菜单
与文字菜单相比,精灵菜单能显示更加丰富的元素,精灵菜单的父类是MenuItemSprite,从源码看,它的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P54_5704.jpg?sign=1739149452-LNJwRzNq44Yoi0SG5VCoKZo8uztYyBuU-0-187b214a616a680292b4bc9345454d9b)
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P55_5705.jpg?sign=1739149452-V4Z090Biw3h3UGPCINGQlOZJPKDsMHVT-0-ce0b06712e431b72be356c970229cbda)
如代码所示,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=1739149452-CWTRdTDlmriPfuezaHfavt1mWcXRhr4m-0-d082498a8c30ec998de9f24b367fc125)
在很多情况下不需要很复杂的精灵显示,只需要几张图片即可,而使用MenuItemSprite还需要创建几个精灵,再来创建菜单项,如果只想创建几张图片构成的菜单项,就可以使用MenuItemSprite的子类MenuItem Image,它的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P55_5707.jpg?sign=1739149452-LnUD1kOxwrPuDlWXn3eMKAorNMgP9ACo-0-70e5d6e8cf9517fa50d59f6fc2730aac)
它的参数是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=1739149452-8vydC7hr9JWzDDyjwTZZ7ClFr176IsZW-0-9bc117914e6d305b70f0f68569f8b6d1)
将以上代码添加在上面的代码后面,再运行项目,可以看到如图3-4所示的效果。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P56_639.jpg?sign=1739149452-Y96ZboRHwAAdRNILptiQNrKWy6pzFboc-0-2175a49d3b7d90c907c19dc0953f33e1)
图3-4 精灵菜单运行效果
3.2.3 实现开关菜单
开关菜单只有一个实现类,也就是MenuItemToggle,相比文字菜单项和精灵菜单项,开关菜单项相对来说用的比较少。开关菜单项是为了实现两个菜单项之间可以切换的效果。查看源码可以看到MenuItemToggle的构造方法如下。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P57_5710.jpg?sign=1739149452-K1bXMcVVsg1VDAwwXEFXLdnJ0uPvB2dv-0-b0e5ad9485638e6929c6acaf09a044ff)
从构造方法只能看到它把参数直接传递给了this.initWithItems,再具体往下看,看看这个调用的方法又做了什么事情。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P57_5711.jpg?sign=1739149452-i32yn2KeF0xSdEKLpcUmgVslaoJ1vBzW-0-58892aa1adcc2daa20265b0eb3ab82de)
从这个方法就可以看到从构造方法传进来的参数都做什么了,首先判断参数的个数,参数的前几个是MenuItem子项,然后根据参数中回调方法的位置来调用initWithCallback方法,构造MenuItem,可以再看看initWithCallback方法。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P58_5713.jpg?sign=1739149452-98hE0fzefG2w17LhvNehQ5tiyarObSMK-0-4ecf79abf2f9ba8363910685808cd2b0)
由以上几段代码可以总结出,创建MenuItemToggle可以带一个MenuItem数组,可以有一个或两个,还需要带一个回调方法。
MenuItemToggle非常适合在游戏中有状态切换的菜单项,如复选框是否选中状态等。例如下面的代码是创建文本“ON”的菜单项和文本“OFF”的菜单项和一个回调方法,单击输出切换状态。
![](https://epubservercos.yuewen.com/C005C7/15253388705242106/epubprivate/OEBPS/Images/Figure-P58_5714.jpg?sign=1739149452-yw61FrwNPjTHWVoHZGPDbpqgLLC4xFLB-0-53bde7dc2d343933ed392d0af5838cd8)
继续将上面的代码添加到之前的代码后面,运行效果如图3-5所示。