本篇博客讲解:
1.使用菜单
2.文本菜单
3.精灵菜单和图片菜单
4.开关菜单
使用菜单
Menu - 菜单
MenuItem - 菜单项
菜单分类实际上是按照菜单项分类的
菜单和菜单项的继承关系图:
文本菜单,精灵菜单,图片菜单和开关菜单其实准确来讲,应该是:
文本菜单项,精灵菜单项,图片菜单项和开关菜单项
继承MenuItemLabel的菜单其实都是文本菜单
精灵菜单:MenuItemSprite的子类是图片菜单MenuItemImage
开关菜单:MenuItemToggle
文本菜单
文本菜单是菜单项只是显示文本
文本菜单类包括了MenuItemLabel、MenuItemFont和MenuItemAtlasFont。MenuItemLabel是个抽象类,具体使用的时候是使用MenuItemFont和MenuItemAtlasFont两个类。
文本菜单类MenuItemFont,它的其中一个创建函数create定义如下:
1
2
3
static MenuItemFont * create ( const std :: string & value , //要显示的文本
const ccMenuCallback & callback //菜单操作的回调函数指针,菜单项被点击之后回调的函数
);
cocos2d帮我们做了一个宏来帮助我们传递回调函数的参数,CC_CALLBACK_n,n为回调的参数个数
1
2
3
4
5
// new callbacks based on C++11
#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)
文本菜单类MenuItemAtlasFont是基于图片集的文本菜单项,它的其中一个创建函数create定义如下:
1
2
3
4
5
6
7
8
static MenuItemAtlasFont * create ( const std :: string & value , //要显示的文本
const std :: string & charMapFile , //图片集文件
int itemWidth , //要截取的文字在图片中的宽度
int itemHeight , //要截取的文字在图片中的高度
char startCharMap , //文字之间的间隔符
const ccMenuCallback & callback //菜单操作的回调函数指针
);
实例:
1
2
3
4
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
bool HelloWorld :: init ()
{
if ( ! Layer :: init ())
{
return false ;
}
Size visibleSize = Director :: getInstance () -> getVisibleSize ();
Vec2 origin = Director :: getInstance () -> getVisibleOrigin ();
Sprite * bg = Sprite :: create ( "menu/background.png" ); //背景图片精灵
bg -> setPosition ( Vec2 ( origin . x + visibleSize . width / 2 ,
origin . y + visibleSize . height / 2 ));
this -> addChild ( bg );
MenuItemFont :: setFontName ( "Times New Roman" ); //使用系统字体,设置系统字体的名字
MenuItemFont :: setFontSize ( 86 ); //设置系统字体的大小
MenuItemFont * item1 = MenuItemFont :: create ( "Start" ,
CC_CALLBACK_1 ( HelloWorld :: menuItem1Callback , this )); //创建基于系统字体的MenuItemFont
MenuItemAtlasFont * item2 = MenuItemAtlasFont :: create ( "Help" ,
"menu/tuffy_bold_italic-charmap.png" , 48 , 65 , ' ' ,
CC_CALLBACK_1 ( HelloWorld :: menuItem2Callback , this ));
Menu * mn = Menu :: create ( item1 , item2 , NULL ); //把MenuItem放到Menu里,不能直接把MenuItem放到层里
mn -> alignItemsVertically (); //设置菜单位置,垂直对齐
this -> addChild ( mn ); //把菜单放到层里
return true ;
}
void HelloWorld :: menuItem1Callback ( Ref * pSender )
{
//实际上这里传进来的参数是MenuItem类型,所以在这里可以强转,也可以直接把形参类型写成MenuItem,不写成Ref
MenuItem * item = ( MenuItem * ) pSender ;
//一般情况下,我们不需要这个参数,只有在需要一些特定的信息的情况下,我们才需要进行转换拿值
log ( "Touch Start Menu Item %p" , item ); //这个输出是输出指针的地址,没有意义,在这里只是掩饰回调函数起作用了!且对象传过来了
}
void HelloWorld :: menuItem2Callback ( Ref * pSender )
{
MenuItem * item = ( MenuItem * ) pSender ;
log ( "Touch Help Menu Item %p" , item );
}
显示效果:
源代码下载地址:
GITHUB源码下载地址:【点我进行下载 】
精灵菜单和图片菜单
精灵菜单项类MenuItemSprite
创建函数create定义:
1
2
3
4
5
6
7
static MenuItemSprite * create ( Node * normalSprite , Node * selectedSprite , Node * disabledSprite = nullptr );
static MenuItemSprite * create ( Node * normalSprite , //菜单项正常显示时候的精灵
Node * selectedSprite , //选择菜单项时候的精灵
Node * disableSprite , //菜单项禁用时候的精灵
const ccMenuCallback & callback //菜单操作的回调函数指针
)
static MenuItemSprite * create ( Node * normalSprite , Node * selectedSprite , const ccMenuCallback & callback );
图片菜单项类MenuIemImage
创建函数create定义:
1
2
3
4
5
static MenuItemImage * create ( const std :: string & normallmage , //菜单项正常显示时候的图片
const std :: string & selectedImage , //选择菜单项时候的图片
const std :: string & disabledImage , //菜单项禁用时候的图片
const ccMenuCallback & callback //菜单操作的回调函数指针
)
精灵菜单和图片菜单都有三种状态,也就是正常状态,选中状态,还有禁用状态。
实例
1
2
3
4
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
bool HelloWorld :: init ()
{
if ( ! Layer :: init () )
{
return false ;
}
Size visibleSize = Director :: getInstance () -> getVisibleSize ();
Vec2 origin = Director :: getInstance () -> getVisibleOrigin ();
Sprite * bg = Sprite :: create ( "menu/background.png" );
bg -> setPosition ( Vec2 ( origin . x + visibleSize . width / 2 ,
origin . y + visibleSize . height / 2 ));
this -> addChild ( bg );
//开始精灵
Sprite * startSpriteNormal = Sprite :: create ( "menu/start-up.png" );
Sprite * startSpriteSelected = Sprite :: create ( "menu/start-down.png" );
//创建精灵菜单 添加精灵以及回调函数
MenuItemSprite * startMenuItem = MenuItemSprite :: create ( startSpriteNormal ,
startSpriteSelected ,
CC_CALLBACK_1 ( HelloWorld :: menuItemStartCallback , this ));
startMenuItem -> setPosition ( Director :: getInstance () -> convertToGL ( Vec2 ( 700 , 170 )));
//指定坐标 convertToGL转换-将左上角为原点的UI坐标转换为OpenGL坐标,cocos2d默认坐标为OpenGL坐标
//700, 170为UI坐标
// 设置 图片菜单 图片菜单的好处就是直接使用图片就好了
MenuItemImage * settingMenuItem = MenuItemImage :: create (
"menu/setting-up.png" ,
"menu/setting-down.png" ,
CC_CALLBACK_1 ( HelloWorld :: menuItemSettingCallback , this ));
settingMenuItem -> setPosition ( Director :: getInstance () -> convertToGL ( Vec2 ( 480 , 400 )));
// 帮助 图片菜单
MenuItemImage * helpMenuItem = MenuItemImage :: create (
"menu/help-up.png" ,
"menu/help-down.png" ,
CC_CALLBACK_1 ( HelloWorld :: menuItemHelpCallback , this ));
helpMenuItem -> setPosition ( Director :: getInstance () -> convertToGL ( Vec2 ( 860 , 480 )));
//在这里,精灵菜单和图片菜单没什么区别,视觉效果一样,也一样有回调函数
Menu * mu = Menu :: create ( startMenuItem , settingMenuItem , helpMenuItem , NULL ); //指定菜单 NULL指定菜单列表的结束
mu -> setPosition ( Vec2 :: ZERO ); //菜单处于坐标原点 - 因为菜单项已经都指定位置了
this -> addChild ( mu );
return true ;
}
//回调函数
void HelloWorld :: menuItemHelpCallback ( Ref * pSender )
{
MenuItem * item = ( MenuItem * ) pSender ;
log ( "Touch Help %p" , item );
}
void HelloWorld :: menuItemStartCallback ( Ref * pSender )
{
MenuItem * item = ( MenuItem * ) pSender ;
log ( "Touch Start %p" , item );
}
void HelloWorld :: menuItemSettingCallback ( Ref * pSender )
{
MenuItem * item = ( MenuItem * ) pSender ;
log ( "Touch Setting %p" , item );
}
小提示:这里图片的UI坐标可以通过画图工具或者PhotoShop获得坐标
显示效果
源代码下载地址:
GITHUB源码下载地址:【点我进行下载 】
开关菜单MenulItemToggle
开关菜单有两种状态,这两种状态可以用任何的图片来替代(比如精灵-只要是菜单项就可以)
函数创建:(也是菜单项)
1
2
3
4
5
static MenulItemToggle * createWithCallback (
const ccMenuCallback & callback , //菜单操作的回调函数指针 - 状态切换时调用的函数,菜单的事件处理
MenuItem * item , //进行切换的菜单项 MenuItem的集合,将其他菜单项放在开关菜单中
...
)
简单形式的文本类型的开关菜单:
1
2
3
4
5
6
7
8
auto toggleMenuItem = MenuItemToggle :: createWithCallback (
CC_CALLBACK_1 ( HelloWorld :: menuItem1Callback , this ),
MenuItemFont :: create ( "On" ),
MenuItemFont :: create ( "Off" ),
NULL ); //最后记得加NULL(Object-c中区分元素集合的结束),在开关菜单中,其实只能放两个子菜单项,多菜单项没意义,因为只是两个状态的切换
Menu * mn = Menu :: create ( toggleMenuItem , NULL ); //把菜单项放入菜单中
this -> addChhild ( mn ); //把菜单放入层中
这里只是简单的文本菜单,当然也可以是精灵菜单,也可以是图片菜单…
实例
1
2
3
4
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
bool HelloWorld :: init ()
{
if ( ! Layer :: init ()){
return false ;
}
Size visibleSize = Director :: getInstance () -> getVisibleSize (); //大小
Vec2 origin = Director :: getInstance () -> getVisibleOrigin (); //锚点 默认为0.5 0.5
//Sprite* bg = Sprite::create("menu/setting-back.png");
auto bg = Sprite :: create ( "menu/setting-back.png" ); // auto-自动推断类型
bg -> setPosition ( Vec2 ( origin . x + visibleSize . width / 2 , origin . y + visibleSize . height / 2 ));
this -> addChild ( bg );
//音效菜单项
auto soundOnMenuItem = MenuItemImage :: create ( "menu/on.png" , "menu/on.png" ); //正常和按下是同一张图片 - 开
auto soundOffMenuItem = MenuItemImage :: create ( "menu/off.png" , "menu/off.png" ); //关
//音效开关菜单项
auto soundToggleMenuItem = MenuItemToggle :: createWithCallback ( CC_CALLBACK_1 ( HelloWorld :: menuSoundToggleCallback , this ), //函数指针
soundOnMenuItem , soundOffMenuItem , //菜单项集合
NULL //集合结束
);
//设置坐标 - UI坐标(原点为左上角)转换为OpenGL坐标(原点为左下角)
soundToggleMenuItem -> setPosition ( Director :: getInstance () -> convertToGL ( Vec2 ( 818 , 220 )));
//音乐菜单项
auto musicOnMenuItem = MenuItemImage :: create (
"menu/on.png" ,
"menu/on.png" );
auto musicOffMenuItem = MenuItemImage :: create (
"menu/off.png" ,
"menu/off.png" );
//音乐开关菜单项
auto musicToggleMenuItem = MenuItemToggle :: createWithCallback ( CC_CALLBACK_1 ( HelloWorld :: menuMusicToggleCallback , this ),
musicOnMenuItem ,
musicOffMenuItem ,
NULL );
musicToggleMenuItem -> setPosition ( Director :: getInstance () -> convertToGL ( Vec2 ( 818 , 362 )));
//OK按钮
auto okMenuItem = MenuItemImage :: create ( "menu/ok-up.png" , "menu/ok-down.png" );
okMenuItem -> setPosition ( Director :: getInstance () -> convertToGL ( Vec2 ( 600 , 510 )));
Menu * mn = Menu :: create ( soundToggleMenuItem , musicToggleMenuItem , okMenuItem , NULL );
mn -> setPosition ( Vec2 :: ZERO );
this -> addChild ( mn );
return true ;
}
void HelloWorld :: menuSoundToggleCallback ( Ref * pSender )
{
log ( "menuSoundToggleCallback" );
}
void HelloWorld :: menuMusicToggleCallback ( Ref * pSender )
{
log ( "menuMusicToggleCallback" );
}
先是创建On和Off图片惨淡项->创建开关菜单->Menu
Menu 放入 Layer
显示效果
源代码下载地址:
GITHUB源码下载地址:【点我进行下载 】
本文章由[谙忆] 编写, 所有权利保留。
欢迎转载,分享是进步的源泉。
转载请注明出处:http://chenhaoxiang.cn
本文源自【人生之旅_谙忆的博客 】