建议转至该处阅读 https://www.zybuluo.com/tangyikejun/note/21953

 

目标

实现一个按键效果,按下去之前显示normal.png的图,按下去之后显示selected.png的图。selected.png尺寸大于normal.png。效果图如下:

Cocos2d-x 点击菜单按键居中放大(无需修改底层代码)-LMLPHP

 

正文

 

1、原始效果

笔者在这个问题上纠结了一天半,尝试了各种方法,一直以为是自己错误使用菜单类导致不能居中放大。之后查看了源码,源码用两个精灵保存前后两张图片,并设置其锚点为(0,0),因此按键前后的图片都是以左下角点为原点绘制,无法到达居中放大的效果。

Cocos2d-x 点击菜单按键居中放大(无需修改底层代码)-LMLPHP

 

2、类间关系

我们先罗列出绘制一个按键所涉及的类,CCMenu、CCMenuItemSprite、CCSprite。它们在结点树上依次是爷爷、父亲、儿子的关系,当然你也可以认为是外婆、母亲、女儿的关系,随便。上述三个类中,CCMenu和CCSprite的锚点坐标都是(0,0),CCMenuItemSprite的锚点为(0.5,0.5),不建议更改这一默认设置。默认设定CCMenuItemSprite的大小和CCSprite的大小一致。当你没有抚摸屏幕的时候界面是这样的:

Cocos2d-x 点击菜单按键居中放大(无需修改底层代码)-LMLPHP;

在这个图中,只对CCMenuItemSprite的位置进行了设置,其他对象的位置都是默认值。可以看到CCMenu对象的默认位置(position)为(0,0)。CCSprite的位置与CCMenuItemSprite的位置一致,即CCSprite的位置默认也是(0,0)。

 

3、解决方案

接下来我们通过实际的例子来讨论,本例中一些类和对象的关系如下表:

CCSpritepNormalSpritenormal.png
CCSpritepSelectedSpriteselected.png
CCMenuItemSpritepCloseItem

现在我们只把注意力放在CCMenuItemSprite和CCSprite这两个类上。对于本例,pNormalSprite和pSelectedSprite两个对象的默认锚点和位置均为(0,0),也就是说均以pCloseItem的左下角点作为原点。为了达到中心放大的目的,只需要重新设置pSelectedSprite的位置即可,见下图伪代码:

Cocos2d-x 点击菜单按键居中放大(无需修改底层代码)-LMLPHP

 

4、实现

具体的代码如下,直接在HelloWorld工程中的HelloWorld::init()函数中修改即可查看效果(当然要先把图放进去!)。

//start//////////////////下面这些代码都是通用的///////////////

/*新建按键前后两个精灵*/
CCSprite *pNormalSprite = CCSprite::create("normal.png");
CC_BREAK_IF(!pNormalSprite); CCSprite *pSelectedSprite = CCSprite::create("selected.png");
CC_BREAK_IF(!pSelectedSprite); /*计算两张图片的dW,dH*/
float dW = pNormalSprite->getContentSize().width
- pSelectedSprite->getContentSize().width;
float dH = pNormalSprite->getContentSize().height
- pSelectedSprite->getContentSize().height; /*设置pSelectedSprite的位置*/
pSelectedSprite->setPosition(ccp(dW / 2.0f,dH / 2.0f)); /*把精灵添加到菜单项pCloseItem中*/
CCMenuItemSprite *pCloseItem = CCMenuItemSprite::create(pNormalSprite,pSelectedSprite,this,menu_selector(HelloWorld::menuCloseCallback));
CC_BREAK_IF(!pCloseItem);
//end//////////////////////////////////////////////////////// /*设置菜单项的位置。*/
pCloseItem->setPosition(ccp(,)); /*添加菜单项到菜单*/
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
pMenu->setPosition(CCPointZero);
CC_BREAK_IF(! pMenu); // Add the menu to HelloWorld layer as a child layer.
this->addChild(pMenu, );

5、更进一步

上述代码虽然解决了中心放大的问题,但是仍存在一些缺陷。Cocos2d-x引擎处理后,pCloseItem对象的尺寸(content size)与pNormalSprite的尺寸是一样大的。即pSelected的尺寸 大于 pCloseItem对象的尺寸。当我们需要根据菜单项的大小来确定位置的时候,上面这种设置就会出现问题,比如我想把菜单项放在屏幕的左下角,如果直接将位置设置为

pCloseItem->setPosition(ccp(w/,h/));//w,h分别是从pCloseItem获得的宽和高

那么菜单项被按下后selected图片会超出屏幕。
要解决这个问题需要两个步骤:
1、pSelectedSprite保持默认位置,而对pNormalSprite的位置进行设置。
2、将pCloseItem对象的尺寸设置为pSelectedSprite的尺寸。

例子:

CCSprite *pNormalSprite = CCSprite::create(path);       //path为图片路径
CCSprite *pSelectedSprite = CCSprite::create(path); //得到dW和dH
float dW = pSelectedSprite->getContentSize().width - pNormalSprite->getContentSize().width;
float dH = pSelectedSprite->getContentSize().height - pNormalSprite->getContentSize().height; //更改位置
pNormalSprite->setPosition(ccp(dW / 2.0f,dH / 2.0f)); //将菜单项的contentSize设置为selectedSprite对象的大小
CCMenuItemSprite *pItemSprite = CCMenuItemSprite::create(pNormalSprite,pSelectedSprite,this,menu_selector(MainScene::onMenuEnd)); CCSize size = pSelectedSprite->getContentSize();
pItemSprite->setContentSize(size);

本文疏漏错误之处,欢迎大家指正!从而对博文不断改进,更好地为大家服务!

转载请注明出处:

http://www.cnblogs.com/tangyikejun/p/3842000.html

https://www.zybuluo.com/tangyikejun/note/21953

05-28 10:41