RotateMenu说明
最终效果图
下面这个引用自乱斗西游
设计说明
1.菜单项(MenuItem)平均分布在椭圆(类似)上
2.椭圆长轴为2/3width,短轴为2/8height
3.最前面的菜单项Scale=1,opacity=255,最后面Scale=0.5,opacity=129.其它位置根据三角函数变换(updatePosition中实现)
4.默认最前面菜单被选中(selected)
5.单位角度(unitAngle)是2*PI/菜单项的数量
6.滑动一个width,菜单旋转两个单位角度
7.Touch结束会自动调整位置,保证最前面位置有菜单项
8.滑动超过1/3单位角度会向前舍入
9.移动小于1/6单位角度会判定点击菜单
10.默认菜单大小不是全屏,而是屏幕的2/3,通过Node::setContentSize()设置
使用
使用这个菜单只要知道两个函数
1.构造函数
RotateMenu::create()(由CREATE_FUNC创建)
2.添加MenuItem
voidaddMenuItem(cocos2d::MenuItem*item);
其它函数可以看代码
相关参数的函数设置还未添加
代码
声明
- #ifndef__ROTA__TE_MENU_H__
- #define__ROTA__TE_MENU_H__
- #include"cocos2d.h"
-
-
- */
- classRotateMenu:publiccocos2d::Layer{
- public:
- //构造方法
- CREATE_FUNC(RotateMenu);
- //添加菜单项
- voidaddMenuItem(cocos2d::MenuItem*item);
- //更新位置
- voidupdatePosition();
- //更新位置,有动画
- voidupdatePositionWithAnimation();
- //位置矫正修改角度forward为移动方向当超过1/3,进1
- //true为正向false负
- voidrectify(boolforward);
- //初始化
- virtualboolinit();
- //重置操作有旋转角度设为0
- voidreset();
- private:
- //设置角度弧度
- voidsetAngle(floatangle);
- floatgetAngle();
- //设置单位角度弧度
- voidsetUnitAngle(floatangle);
- floatgetUnitAngle();
- //滑动距离转换角度,转换策略为移动半个Menu.width等于_unitAngle
- floatdisToAngle(floatdis);
- //返回被选中的item
- cocos2d::MenuItem*getCurrentItem();
- private:
- //菜单已经旋转角度弧度
- float_angle;
- //菜单项集合,_children顺序会变化,新建数组保存顺序
- cocos2d::Vector<cocos2d::MenuItem*>_items;
- //单位角度弧度
- float_unitAngle;
- //监听函数
- boolonTouchBegan(cocos2d::Touch*touch,cocos2d::Event*event);
- virtualvoidonTouchEnded(cocos2d::Touch*touch,cocos2d::Event*event);
- voidonTouchMoved(cocos2d::Touch*touch,0); background-color:inherit">//动画完结调用函数
- voidactionEndCallBack(floatdx);
- //当前被选择的item
- cocos2d::MenuItem*_selectedItem;
- //动画运行时间
- floatanimationDuration=0.3f;
- };
- #endif
实现
#include"RotateMenu.h"
- #include<math.h>
- #definePIacos(-1)
- USING_NS_CC;
- boolRotateMenu::init(){
- if(!Layer::init())
- returnfalse;
- _angle=0.0;
- this->ignoreAnchorPointForPosition(false);
- _selectedItem=nullptr;
- Sizes=Director::getInstance()->getWinSize();
- this->setContentSize(s/3*2);
- this->setAnchorPoint(Vec2(0.5f,0.5f));
- autolistener=EventListenerTouchOneByOne::create();
- listener->onTouchBegan=CC_CALLBACK_2(RotateMenu::onTouchBegan,this);
- listener->onTouchMoved=CC_CALLBACK_2(RotateMenu::onTouchMoved,153); font-weight:bold; background-color:inherit">this);
- listener->onTouchEnded=CC_CALLBACK_2(RotateMenu::onTouchEnded,248)"> getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,153); font-weight:bold; background-color:inherit">true;
-
- voidRotateMenu::addMenuItem(cocos2d::MenuItem*item){
- item->setPosition(this->getContentSize()/2);
- this->addChild(item);
- _items.pushBack(item);
- setUnitAngle(2*PI/_items.size());
- reset();
- updatePositionWithAnimation();
- return;
- }
- voidRotateMenu::updatePosition(){
- automenuSize=getContentSize();
- autodisY=menuSize.height/8;
- autodisX=menuSize.width/3;
- for(inti=0;i<_items.size();i++){
- floatx=menuSize.width/2+disX*sin(i*_unitAngle+getAngle());
- floaty=menuSize.height/2-disY*cos(i*_unitAngle+getAngle());
- _items.at(i)->setPosition(Vec2(x,y));
- _items.at(i)->setZOrder(-(int)y);
- //Opacity129~255
- _items.at(i)->setOpacity(192+63*cos(i*_unitAngle+getAngle()));
- _items.at(i)->setScale(0.75+0.25*cos(i*_unitAngle+getAngle()));
- }
- return;
- voidRotateMenu::updatePositionWithAnimation(){
- //先停止所有可能存在的动作
- inti=0;i<_items.size();i++)
- _items.at(i)->stopAllActions();
- automoveTo=MoveTo::create(animationDuration,Vec2(x,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> _items.at(i)->runAction(moveTo);
- autofadeTo=FadeTo::create(animationDuration,(192+63*cos(i*_unitAngle+getAngle())));
- _items.at(i)->runAction(fadeTo);
- //缩放比例0.5~1
- autoscaleTo=ScaleTo::create(animationDuration,0.75+0.25*cos(i*_unitAngle+getAngle()));
- _items.at(i)->runAction(scaleTo);
- _items.at(i)->setZOrder(-(int)y);
- scheduleOnce(schedule_selector(RotateMenu::actionEndCallBack),animationDuration);
- voidRotateMenu::reset(){
- _angle=0;
- voidRotateMenu::setAngle(floatangle){
- this->_angle=angle;
- floatRotateMenu::getAngle(){
- return_angle;
- voidRotateMenu::setUnitAngle( _unitAngle=angle;
- floatRotateMenu::getUnitAngle(){
- return_unitAngle;
-
- floatRotateMenu::disToAngle(floatdis){
- floatwidth=this->getContentSize().width/2;
- returndis/width*getUnitAngle();
- MenuItem*RotateMenu::getCurrentItem(){
- if(_items.size()==0)
- returnnullptr;
- //这里实际加上了0.1getAngle(),用来防止精度丢失
- intindex=(int)((2*PI-getAngle())/getUnitAngle()+0.1*getUnitAngle());
- index%=_items.size();
- return_items.at(index);
- boolRotateMenu::onTouchBegan(Touch*touch,Event*event){
- if(_selectedItem)
- _selectedItem->unselected();
- autoposition=this->convertToNodeSpace(touch->getLocation());
- autosize=this->getContentSize();
- autorect=Rect(0,size.width,size.height);
- if(rect.containsPoint(position)){
- true;
- false;
- voidRotateMenu::onTouchEnded(Touch*touch,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> autoxDelta=touch->getLocation().x-touch->getStartLocation().x;
- rectify(xDelta>0);
- if(disToAngle(fabs(xDelta))<getUnitAngle()/6&&_selectedItem)
- _selectedItem->activate();
- updatePositionWithAnimation();
- voidRotateMenu::onTouchMoved(Touch*touch,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> autoangle=disToAngle(touch->getDelta().x);
- setAngle(getAngle()+angle);
- updatePosition();
- voidRotateMenu::rectify(boolforward){
- autoangle=getAngle();
- while(angle<0)
- angle+=PI*2;
- while(angle>PI*2)
- angle-=PI*2;
- if(forward>0)
- angle=((int)((angle+getUnitAngle()/3*2)/getUnitAngle()))*getUnitAngle();
- else
- int)((angle+getUnitAngle()/3)/getUnitAngle()))*getUnitAngle();
- setAngle(angle);
- voidRotateMenu::actionEndCallBack(floatdx){
- _selectedItem=getCurrentItem();
- _selectedItem->selected();
- }
一个糟糕的Demo
声明
#ifndef__HELLOWORLD_SCENE_H__
- #define__HELLOWORLD_SCENE_H__
- classHelloWorld:publiccocos2d::Layer
- {
- //there'sno'id'incpp,sowerecommendreturningtheclassinstancepointer
- staticcocos2d::Scene*createScene();
- //Here'sadifference.Method'init'incocos2d-xreturnsbool,insteadofreturning'id'incocos2d-iphone
- boolinit();
- //aselectorcallback
- voidmenuCloseCallback(cocos2d::Ref*pSender);
- voidmenuItem1Callback(cocos2d::Ref*pSender);
- voidmenuItem2Callback(cocos2d::Ref*pSender);
- voidmenuItem3Callback(cocos2d::Ref*pSender);
- voidmenuItem4Callback(cocos2d::Ref*pSender);
- voidmenuItem5Callback(cocos2d::Ref*pSender);
- voidhideAllSprite();
- cocos2d::Sprite*sprite[5];
- //implementthe"staticcreate()"methodmanually
- CREATE_FUNC(HelloWorld);
- #endif//__HELLOWORLD_SCENE_H__
声明
#include"HelloWorldScene.h"
- #include"RotateMenu.h"
- USING_NS_CC;
- typedefstructSceneList{
- constchar*name;
- std::function<cocos2d::Scene*()>callback;
- }SceneList;
- SceneListsceneList[]={
- {"Demo1",[](){returnHelloWorld::createScene();}}
- constunsignedintsceneCount=sizeof(sceneList)/sizeof(SceneList);
- #defineLINE_SPACE40
- Scene*HelloWorld::createScene()
- //'scene'isanautoreleaSEObject
- autoscene=Scene::create();
- //'layer'isanautoreleaSEObject
- autolayer=HelloWorld::create();
- //addlayerasachildtoscene
- scene->addChild(layer);
- //returnthescene
- returnscene;
- //on"init"youneedtoinitializeyourinstance
- boolHelloWorld::init()
- //////////////////////////////
- //1.superinitfirst
- SizevisibleSize=Director::getInstance()->getVisibleSize();
- Vec2origin=Director::getInstance()->getVisibleOrigin();
- /////////////////////////////
- //2.addamenuitemwith"X"image,whichisclickedtoquittheprogram
- //youmaymodifyit.
- //adda"close"icontoexittheprogress.it'sanautoreleaSEObject
- autocloseItem=MenuItemImage::create(
- "CloseNormal.png",
- "CloseSelected.png",
- CC_CALLBACK_1(HelloWorld::menuCloseCallback,153); font-weight:bold; background-color:inherit">this));
- closeItem->setPosition(Vec2(origin.x+visibleSize.width-closeItem->getContentSize().width/2,
- origin.y+closeItem->getContentSize().height/2));
- //createmenu,it'sanautoreleaSEObject
- /*automenu=Menu::create(closeItem,NULL);
- menu->setPosition(Vec2::ZERO);
- this->addChild(menu,1);*/
- autoitem1=MenuItemImage::create("Demo1/item1_1.png","Demo1/item1_0.png",CC_CALLBACK_1(HelloWorld::menuItem1Callback,this));
- autoitem2=MenuItemImage::create("Demo1/item2_1.png","Demo1/item2_0.png",CC_CALLBACK_1(HelloWorld::menuItem2Callback,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> autoitem3=MenuItemImage::create("Demo1/item3_1.png","Demo1/item3_0.png",CC_CALLBACK_1(HelloWorld::menuItem3Callback,248)"> autoitem4=MenuItemImage::create("Demo1/item4_1.png","Demo1/item4_0.png",CC_CALLBACK_1(HelloWorld::menuItem4Callback,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> autoitem5=MenuItemImage::create("Demo1/item5_1.png","Demo1/item5_0.png",CC_CALLBACK_1(HelloWorld::menuItem5Callback,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> RotateMenu*menu=RotateMenu::create();
- menu->addMenuItem(item1);
- menu->addMenuItem(item2);
- menu->addMenuItem(item3);
- menu->addMenuItem(item4);
- menu->addMenuItem(item5);
- menu->setPosition(visibleSize/2);
- this->addChild(menu,2);
- inti=0;i<5;i++){
- charstr[20];
- sprintf(str,"Demo1/item%d.jpg",i+1);
- sprite[i]=Sprite::create(str);
- sprite[i]->setAnchorPoint(Vec2(0.5f,0.5f));
- sprite[i]->setPosition(visibleSize/2);
- this->addChild(sprite[i]);
- hideAllSprite();
- /////////////////////////////
- //3.addyourcodesbelow...
- //addalabelshows"HelloWorld"
- //createandinitializealabel
- autolabel=LabelTTF::create("HelloWorld","Arial",24);
- //positionthelabelonthecenterofthescreen
- label->setPosition(Vec2(origin.x+visibleSize.width/2,
- origin.y+visibleSize.height-label->getContentSize().height));
- //addthelabelasachildtothislayer
- this->addChild(label,1);
- voidHelloWorld::menuCloseCallback(Ref*pSender)
- #if(CC_TARGET_PLATFORM==CC_PLATFORM_WP8)||(CC_TARGET_PLATFORM==CC_PLATFORM_WINRT)
- MessageBox("Youpressedtheclosebutton.WindowsStoreAppsdonotimplementaclosebutton.","Alert");
- #endif
- Director::getInstance()->end();
- #if(CC_TARGET_PLATFORM==CC_PLATFORM_IOS)
- exit(0);
- voidHelloWorld::menuItem1Callback(cocos2d::Ref*pSender){
- sprite[0]->setVisible(true);
- voidHelloWorld::menuItem2Callback(cocos2d::Ref*pSender){
- sprite[1]->setVisible(voidHelloWorld::menuItem3Callback(cocos2d::Ref*pSender){
- sprite[2]->setVisible(voidHelloWorld::menuItem4Callback(cocos2d::Ref*pSender){
- sprite[3]->setVisible(voidHelloWorld::menuItem5Callback(cocos2d::Ref*pSender){
- sprite[4]->setVisible(voidHelloWorld::hideAllSprite(){
- for(autop:sprite){
- if(p->isVisible())
- p->setVisible(false);
- }
可运行的程序下载地址 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|