一、菜单(CCMenu)
Cocos2d-x提供了菜单功能,学习具体菜单项之前需要先了解一下CCMenu。
CCMenu是Cocos2d-x的菜单类,本身不具备菜单具体属性,将一些具体类型的菜单添加进去达到添加菜单的目的,可以说它是一个容器;在Cocos2d-x中使用菜单功能首先要创建这个容器,之后把我们创建好的菜单项(CCMenuItem)添加到CCMenu容器中,此时才可以使用。
看看它的继承关系:
类中部分代码如下:
class CC_DLL CCMenu : public CCLayerRGBA
{
public:
static CCMenu* create();
static CCMenu* create(CCMenuItem* item, ...);
static CCMenu* createWithArray(CCArray* pArrayOfItems);
static CCMenu* createWithItem(CCMenuItem* item);
void alignItemsVertically();
void alignItemsVerticallyWithPadding(float padding);
void alignItemsHorizontally();
void alignItemsHorizontallyWithPadding(float padding);
};
由此可以看出有四种创建CCMenu的方法:
static CCMenu* create():创建一个空的菜单。
static CCMenu* create(CCMenuItem* item, ...):通过菜单项创建菜单,参数结尾需要添加NULL。
static CCMenu* createWithArray(CCArray* pArrayOfItems):通过一个CCArray容器来创建菜单,CCArray中包含要添加的菜单项。
static CCMenu* createWithItem(CCMenuItem* item):通过单一的菜单项来创建菜单。
void alignItemsVertically():设置为水平排列。
void alignItemsVerticallyWithPadding(float padding):设置为水平排列,并设置菜单项边框间距。
void alignItemsHorizontally():设置为垂直排列。
void alignItemsHorizontallyWithPadding(float padding):设置为垂直排列,并设置菜单项边框间距。
CCMenu的默认触摸优先级是-128。
无论是菜单CCMenu创建还是使用菜单都需要有菜单项CCMenuItem,下面来看看CCMenuItem。
二、菜单项(CCMenuItem)
菜单CCMenu的使用离不开菜单项CCMenuItem,CCMenu是一个容器,其中包含菜单项CCMenuItem后才能使用。
菜单项CCMenuItem的子类定义各种具体的菜单条目,继承关系如下:
菜单项CCMenuItem一般不直接创建使用,而是使用其子类。
(一)CCMenuItemFont
先来看看创建方式:
class CC_DLL CCMenuItemFont : public CCMenuItemLabel
{
public:
static CCMenuItemFont * create(const char *value);
static CCMenuItemFont * create(const char *value, CCObject* target, SEL_MenuHandler selector);
};
const char *value:要显示在菜单项上的字符串。
CCObject* target:调用这个菜单项的对象。
SEL_MenuHandler selector:菜单项点击后的响应函数,一个回调函数。
实例:
bool HelloWorld::init()
{
CCLayer::init();
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCMenuItemFont *itemFont = CCMenuItemFont::create("gong");
itemFont->setFontSize(100);
itemFont->setTag(10);
itemFont->setTarget(this, menu_selector(HelloWorld::menuCallBack));
CCMenu* menu = CCMenu::create();
menu->addChild(itemFont);
addChild(menu);
return true;
}
void HelloWorld::menuCallBack(CCObject* obj)
{
CCMenuItemFont* item = (CCMenuItemFont*)getChildByTag(10);
CCLog("%s", item->fontName());
CCLog("%d", item->fontSize());
}
创建CCMenuItemFont后,通过setTarget给此菜单项添加了一个回调函数。
fontName获取默认字体。
fontSize获取默认字号。
(二)CCMenuItemAtlasFont
先来看看CCMenuItemAtlasFont的create函数:
class CC_DLL CCMenuItemAtlasFont : public CCMenuItemLabel
{
public:
static CCMenuItemAtlasFont* create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap);
static CCMenuItemAtlasFont* create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector);
};
const char *value:要在菜单项中显示的字符串。
const char *charMapFile:包含字符集的图片,.png格式。
int itemWidth:图片中,每个字符所占宽度。
int itemHeight:图片中,每个字符所占高度。
char startCharMap:图片中,第一个字符,实际上需要的是ASCII码。
CCObject* target:调用此菜单项的对象的指针。
SEL_MenuHandler selector:回调函数,单击此菜单项调用的函数。
实例:
bool HelloWorld::init()
{
CCLayer::init();
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCMenuItemAtlasFont* itemAtlas = CCMenuItemAtlasFont::create("123", "Labelatlas.png", 24, 32, '0', this, menu_selector(HelloWorld::menuCallBack));
CCMenu* menu = CCMenu::createWithItem(itemAtlas);
addChild(menu);
return true;
}
void HelloWorld::menuCallBack(CCObject* obj)
{
CCLog("CCMenuItemAtlasFont");
}
(三)CCMenuItemLabel
此CCMenuItemLabel类派生出CCMenuItemAtlasFont与CCMenuItemFont。
先来看看CCMenuItemLabel的create函数。
class CC_DLL CCMenuItemLabel : public CCMenuItem
{
public:
static CCMenuItemLabel * create(CCNode*label, CCObject* target, SEL_MenuHandler selector);
static CCMenuItemLabel* create(CCNode *label);
}
CCNode*label:是一个Label,可以是CCLabelTTF、CCLabelAtlas、CCLabelBMFont三种。
CCObject* target:欲调用此菜单项的对象指针。
SEL_MenuHandler selector:回调函数,菜单项单击后执行。
实例:
bool HelloWorld::init()
{
CCLayer::init();
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCLabelTTF* ttf = CCLabelTTF::create("gong", "New", 30);
CCLabelAtlas* atlas = CCLabelAtlas::create("125", "Labelatlas.png", 24, 32, '0');
CCLabelBMFont* bmfont = CCLabelBMFont::create("JianYiLiGong", "bitmapFontTest.fnt");
CCMenuItemLabel* itemLabelTTF = CCMenuItemLabel::create(ttf, this, menu_selector(HelloWorld::menuCallBack));
CCMenuItemLabel* itemLabelAtlas = CCMenuItemLabel::create(atlas, this, menu_selector(HelloWorld::menuCallBack));
CCMenuItemLabel* itemLabelBmfont = CCMenuItemLabel::create(bmfont, this, menu_selector(HelloWorld::menuCallBack));
CCMenu* menu = CCMenu::create(itemLabelTTF, itemLabelAtlas, itemLabelBmfont, NULL);
menu->alignItemsVerticallyWithPadding(50);
addChild(menu);
return true;
}
void HelloWorld::menuCallBack(CCObject* obj)
{
CCLog("CCMenuItemLabel");
}
CCMenuItemLabel通过CCLabel来创建菜单项。
(四)CCMenuItemImage
这个菜单项通过图片来创建,create函数声明如下:
class CC_DLL CCMenuItemImage : public CCMenuItemSprite
{
public:
static CCMenuItemImage* create();
static CCMenuItemImage* create(const char *normalImage, const char *selectedImage);
static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, const char *disabledImage);
static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, CCObject* target, SEL_MenuHandler selector);
static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector);
}
const char *normalImage:菜单项未选中时候的图片。
const char *selectedImage:菜单项选中后的图片。
const char *disabledImage:菜单项无效的图片。
CCObject* target: 调用此菜单项的对象指针。
SEL_MenuHandler selector:回调函数,点击菜单项后调用。
实例:
bool HelloWorld::init()
{
CCLayer::init();
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCMenuItemImage* itemImage = CCMenuItemImage::create("CloseNormal.png", "CloseSelected.png", "HelloWorld.png", this, menu_selector(HelloWorld::menuCallBack));
CCMenu* menu = CCMenu::create();
menu->addChild(itemImage);
addChild(menu);
return true;
}
void HelloWorld::menuCallBack(CCObject* obj)
{
CCLog("CCMenuItemImage");
}
而如果使用了参数为空的create,这可以使用CCMenuItemImage类中下述方法进行必要的设置。
class CC_DLL CCMenuItemImage : public CCMenuItemSprite
{
public:
/** sets the sprite frame for the normal image */
void setNormalSpriteFrame(CCSpriteFrame* frame);
/** sets the sprite frame for the selected image */
void setSelectedSpriteFrame(CCSpriteFrame* frame);
/** sets the sprite frame for the disabled image */
void setDisabledSpriteFrame(CCSpriteFrame* frame);
}
CCMenuItemImage通过三张图片创建菜单项。
(五)CCMenuItemSprite
CCMenuItemSprite派生出CCMenuItemImage,CCMenuItemSprite的create如下:
class CC_DLL CCMenuItemSprite : public CCMenuItem
{
public:
static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite = NULL);
static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCObject* target, SEL_MenuHandler selector);
static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite, CCObject* target, SEL_MenuHandler selector);
}
CCNode* normalSprite:正常状态下的精灵。
CCNode* selectedSprite:被选中后的精灵。
CCNode* disabledSprite:无效时候的精灵。
CCObject* target:调用此菜单项的对象指针。
SEL_MenuHandler selector:回调函数,单击此菜单项后执行。
实例:
bool HelloWorld::init()
{
CCLayer::init();
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSprite* normal = CCSprite::create("CloseNormal.png");
CCSprite* select = CCSprite::create("CloseSelected.png");
CCSprite* disabled = CCSprite::create("HelloWorld.png");
CCMenuItemSprite* itemSprite = CCMenuItemSprite::create(normal, select, disabled);
itemSprite->setTarget(this, menu_selector(HelloWorld::menuCallBack));
CCMenu* menu = CCMenu::create();
menu->addChild(itemSprite);
addChild(menu);
return true;
}
void HelloWorld::menuCallBack(CCObject* obj)
{
CCLog("CCMenuItemSprite");
}
CCMenuItemSprite通过创建三个精灵来创建菜单项。
(六)CCMenuItemToggle
CCMenuItemToggle用来创建一个滚动的菜单项,创建CCMenuItemToggle需要多个CCMenuItem对象。部分代码如下:
class CC_DLL CCMenuItemToggle : public CCMenuItem
{
public:
/** creates a menu item from a CCArray with a target selector */
static CCMenuItemToggle * createWithTarget(CCObject* target, SEL_MenuHandler selector, CCArray* menuItems);
/** creates a menu item from a list of items with a target/selector */
static CCMenuItemToggle* createWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, ...);
/** creates a menu item with no target/selector and no items
*/
static CCMenuItemToggle* create();
/** creates a menu item with a item */
static CCMenuItemToggle* create(CCMenuItem *item);
/** add more menu item */
void addSubItem(CCMenuItem *item);
/** return the selected item */
CCMenuItem* selectedItem();
};
由上述代码可以看出有四个create来创建CCMenuItemToggle:
static CCMenuItemToggle * createWithTarget(CCObject* target, SEL_MenuHandler selector, CCArray* menuItems);
static CCMenuItemToggle* createWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, ...);
static CCMenuItemToggle* create();
static CCMenuItemToggle* create(CCMenuItem *item);
其中:
CCObject* target:调用此菜单项的对象指针。
SEL_MenuHandler selector:响应此菜单项的回调函数。
CCArray* menuItems:包含一些CCMenuItem子对象的CCArray。
CCMenuItem* item:一个CCMenuItem对象。
实例:
bool HelloWorld::init()
{
CCLayer::init();
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCMenuItemFont* font1 = CCMenuItemFont::create("0");
CCMenuItemFont* font2 = CCMenuItemFont::create("1");
CCMenuItemFont* font3 = CCMenuItemFont::create("2");
CCMenuItemFont* font4 = CCMenuItemFont::create("3");
CCArray* array = CCArray::create();
array->addObject(font1);
array->addObject(font2);
array->addObject(font3);
array->addObject(font4);
CCMenuItemToggle* toggle = CCMenuItemToggle::createWithTarget(this,menu_selector(HelloWorld::menuCallBack), array);
CCMenu* menu = CCMenu::createWithItem(toggle);
addChild(menu);
return true;
}
void HelloWorld::menuCallBack(CCObject* obj)
{
CCMenuItemToggle* item = (CCMenuItemToggle*)obj;
int index = item->getSelectedIndex();
CCLog("%d", index);
}
(六)CCMenu的一些方法
void alignItemsVertically();
void alignItemsVerticallyWithPadding(float padding);
void alignItemsHorizontally();
void alignItemsHorizontallyWithPadding(float padding);
上面的四个函数可以设置菜单按照水平对齐还是垂直对齐,并且可以设置间隔。
三、菜单的坐标
先看下述测试代码:
bool HelloWorld::init()
{
CCLayer::init();
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCMenuItemFont* font = CCMenuItemFont::create("0");
CCMenu* menu = CCMenu::createWithItem(font);
CCSize menuSize = menu->getContentSize();
CCPoint menuPoint = menu->getPosition();
CCPoint anPoint = menu->getAnchorPoint();
CCLog("width = %f, height = %f", menuSize.width, menuSize.height);
CCLog("x = %f, y = %f",menuPoint.x, menuPoint.y);
CCLog("Anchor x = %f, y = %f", anPoint.x, anPoint.y);
addChild(menu);
return true;
}
得到的结果:
width = 480.000000, height = 320.000000
x = 240.000000, y = 160.000000
Anchor x = 0.500000, y = 0.500000
由此可知菜单位置设置为屏幕的中点位置,并且菜单的大小与屏幕大小相同,菜单的锚点为0.5与0.5。
而通过之前的例子可以知道菜单中的菜单项是以菜单的锚点为坐标原点。