• 基于cocos2dx的伪立体菜单


    RotateMenu说明

    最终效果图


    下面这个引用自乱斗西游

     

    设计说明

    1.菜单项(MenuItem)平均分布在椭圆(类似)上

    2.椭圆长轴为2/3width,短轴为2/8 height

    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

    void addMenuItem(cocos2d::MenuItem *item);

    其它函数可以看代码

    相关参数的函数设置还未添加

    代码

    声明

    [cpp] view plain copy
    1. #ifndef __ROTA__TE_MENU_H__  
    2. #define __ROTA__TE_MENU_H__  
    3. #include "cocos2d.h"  
    4. /* 
    5.  *模仿乱斗西游主界面的旋转菜单 
    6.  */  
    7. class RotateMenu :public cocos2d::Layer{  
    8. public:  
    9.     //构造方法  
    10.     CREATE_FUNC(RotateMenu);  
    11.     //添加菜单项  
    12.     void addMenuItem(cocos2d::MenuItem *item);  
    13.     //更新位置  
    14.     void updatePosition();  
    15.     //更新位置,有动画  
    16.     void updatePositionWithAnimation();  
    17.     //位置矫正  修改角度 forward为移动方向  当超过1/3,进1  
    18.     //true 为正向  false 负  
    19.     void rectify(bool forward);  
    20.     //初始化  
    21.     virtual bool init();  
    22.     //重置  操作有旋转角度设为0  
    23.     void reset();  
    24. private:  
    25.     //设置角度 弧度  
    26.     void setAngle(float angle);  
    27.     float getAngle();  
    28.     //设置单位角度 弧度  
    29.     void setUnitAngle(float angle);  
    30.     float getUnitAngle();  
    31.     //滑动距离转换角度,转换策略为  移动半个Menu.width等于_unitAngle  
    32.     float disToAngle(float dis);  
    33.     //返回被选中的item  
    34.     cocos2d::MenuItem * getCurrentItem();  
    35. private:  
    36.     //菜单已经旋转角度 弧度  
    37.     float _angle;  
    38.     //菜单项集合,_children顺序会变化,新建数组保存顺序  
    39.     cocos2d::Vector<cocos2d::MenuItem *> _items;  
    40.     //单位角度 弧度  
    41.     float _unitAngle;  
    42.     //监听函数  
    43.     virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);  
    44.     virtual void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event);      
    45.     virtual void onTouchMoved(cocos2d::Touch* touch, cocos2d::Event* event);  
    46.     //动画完结调用函数  
    47.     void actionEndCallBack(float dx);  
    48.     //当前被选择的item  
    49.     cocos2d::MenuItem *_selectedItem;  
    50.     //动画运行时间  
    51.      float animationDuration = 0.3f;  
    52. };  
    53. #endif  

    实现

    [cpp] view plain copy
    1. #include "RotateMenu.h"  
    2. #include <math.h>  
    3. #define PI acos(-1)  
    4. USING_NS_CC;  
    5. bool RotateMenu::init(){  
    6.     if (!Layer::init())  
    7.         return false;  
    8.     _angle = 0.0;  
    9.     this->ignoreAnchorPointForPosition(false);  
    10.     _selectedItem = nullptr;  
    11.     Size s = Director::getInstance()->getWinSize();  
    12.     this->setContentSize(s/3*2);  
    13.     this->setAnchorPoint(Vec2(0.5f, 0.5f));  
    14.     auto listener = EventListenerTouchOneByOne::create();  
    15.     listener->onTouchBegan = CC_CALLBACK_2(RotateMenu::onTouchBegan,this);  
    16.     listener->onTouchMoved = CC_CALLBACK_2(RotateMenu::onTouchMoved, this);  
    17.     listener->onTouchEnded = CC_CALLBACK_2(RotateMenu::onTouchEnded, this);  
    18.     getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);  
    19.     return true;  
    20. };  
    21.   
    22. void RotateMenu::addMenuItem(cocos2d::MenuItem *item){  
    23.     item->setPosition(this->getContentSize() / 2);  
    24.     this->addChild(item);  
    25.     _items.pushBack(item);  
    26.     setUnitAngle(2 * PI / _items.size());  
    27.     reset();  
    28.     updatePositionWithAnimation();  
    29.     return;  
    30. }  
    31. void RotateMenu::updatePosition(){  
    32.     auto menuSize = getContentSize();  
    33.     auto disY = menuSize.height / 8;  
    34.     auto disX = menuSize.width / 3;  
    35.     for (int i = 0; i < _items.size(); i++){  
    36.         float x = menuSize.width / 2 + disX*sin(i*_unitAngle+getAngle());  
    37.         float y = menuSize.height / 2 - disY*cos(i*_unitAngle + getAngle());  
    38.         _items.at(i)->setPosition(Vec2(x, y));  
    39.         _items.at(i)->setZOrder(-(int)y);  
    40.         //Opacity  129~255  
    41.         _items.at(i)->setOpacity(192 + 63 * cos(i*_unitAngle + getAngle()));  
    42.         _items.at(i)->setScale(0.75 + 0.25*cos(i*_unitAngle + getAngle()));  
    43.     }  
    44.     return;  
    45. }  
    46. void RotateMenu::updatePositionWithAnimation(){  
    47.     //先停止所有可能存在的动作  
    48.     for (int i = 0; i < _items.size(); i++)  
    49.         _items.at(i)->stopAllActions();  
    50.     auto menuSize = getContentSize();  
    51.     auto disY = menuSize.height / 8;  
    52.     auto disX = menuSize.width / 3;  
    53.     for (int i = 0; i < _items.size(); i++){  
    54.         float x = menuSize.width / 2 + disX*sin(i*_unitAngle + getAngle());  
    55.         float y = menuSize.height / 2 - disY*cos(i*_unitAngle + getAngle());  
    56.         auto moveTo = MoveTo::create(animationDuration, Vec2(x, y));  
    57.         _items.at(i)->runAction(moveTo);  
    58.         //Opacity  129~255  
    59.         auto fadeTo = FadeTo::create(animationDuration, (192 + 63 * cos(i*_unitAngle + getAngle())));  
    60.         _items.at(i)->runAction(fadeTo);  
    61.         //缩放比例  0.5~1  
    62.         auto scaleTo = ScaleTo::create(animationDuration, 0.75 + 0.25*cos(i*_unitAngle + getAngle()));  
    63.         _items.at(i)->runAction(scaleTo);  
    64.         _items.at(i)->setZOrder(-(int)y);  
    65.     }  
    66.     scheduleOnce(schedule_selector(RotateMenu::actionEndCallBack), animationDuration);  
    67.     return;  
    68. }  
    69. void RotateMenu::reset(){  
    70.     _angle = 0;  
    71. }  
    72. void RotateMenu::setAngle(float angle){  
    73.     this->_angle = angle;  
    74. }  
    75. float RotateMenu::getAngle(){  
    76.     return _angle;  
    77. }  
    78. void RotateMenu::setUnitAngle(float angle){  
    79.     _unitAngle = angle;  
    80. }  
    81. float RotateMenu::getUnitAngle(){  
    82.     return _unitAngle;  
    83. }  
    84.   
    85. float RotateMenu::disToAngle(float dis){  
    86.     float width = this->getContentSize().width / 2;  
    87.     return dis / width*getUnitAngle();  
    88. }  
    89.   
    90. MenuItem * RotateMenu::getCurrentItem(){  
    91.     if (_items.size() == 0)  
    92.         return nullptr;  
    93.     //这里实际加上了0.1getAngle(),用来防止精度丢失  
    94.     int  index = (int)((2 * PI - getAngle()) / getUnitAngle()+0.1*getUnitAngle());  
    95.     index %= _items.size();  
    96.     return _items.at(index);  
    97. }  
    98.   
    99.   
    100. bool RotateMenu::onTouchBegan(Touch* touch, Event* event){  
    101.     //先停止所有可能存在的动作  
    102.     for (int i = 0; i < _items.size(); i++)  
    103.         _items.at(i)->stopAllActions();  
    104.     if (_selectedItem)  
    105.         _selectedItem->unselected();  
    106.     auto position = this->convertToNodeSpace(touch->getLocation());  
    107.     auto size = this->getContentSize();  
    108.     auto rect = Rect(0, 0, size.width, size.height);  
    109.     if (rect.containsPoint(position)){  
    110.         return true;  
    111.     }  
    112.     return false;  
    113. }  
    114. void RotateMenu::onTouchEnded(Touch* touch, Event* event){  
    115.     auto xDelta = touch->getLocation().x - touch->getStartLocation().x;  
    116.     rectify(xDelta>0);  
    117.     if (disToAngle(fabs(xDelta))<getUnitAngle() / 6&&_selectedItem)  
    118.         _selectedItem->activate();  
    119.     updatePositionWithAnimation();  
    120.     return;  
    121. }  
    122. void RotateMenu::onTouchMoved(Touch* touch, Event* event){  
    123.     auto angle = disToAngle(touch->getDelta().x);  
    124.     setAngle(getAngle() + angle);  
    125.     updatePosition();  
    126.     return;  
    127. }  
    128.   
    129. void RotateMenu::rectify(bool forward){  
    130.     auto angle = getAngle();  
    131.     while (angle<0)  
    132.         angle += PI * 2;  
    133.     while (angle>PI * 2)  
    134.         angle -= PI * 2;  
    135.     if(forward>0)  
    136.         angle = ((int)((angle + getUnitAngle() / 3*2) / getUnitAngle()))*getUnitAngle();  
    137.     else  
    138.         angle = ((int)((angle + getUnitAngle() / 3 ) / getUnitAngle()))*getUnitAngle();  
    139.     setAngle(angle);  
    140. }  
    141.   
    142. void RotateMenu::actionEndCallBack(float dx){  
    143.     _selectedItem = getCurrentItem();  
    144.     if(_selectedItem)  
    145.         _selectedItem->selected();  
    146. }  

    一个糟糕的Demo

    声明

    [cpp] view plain copy
    1. #ifndef __HELLOWORLD_SCENE_H__  
    2. #define __HELLOWORLD_SCENE_H__  
    3. #include "cocos2d.h"  
    4. class HelloWorld : public cocos2d::Layer  
    5. {  
    6. public:  
    7.     // there's no 'id' in cpp, so we recommend returning the class instance pointer  
    8.     static cocos2d::Scene* createScene();  
    9.     // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone  
    10.     virtual bool init();       
    11.     // a selector callback  
    12.     void menuCloseCallback(cocos2d::Ref* pSender);  
    13.     void menuItem1Callback(cocos2d::Ref* pSender);  
    14.     void menuItem2Callback(cocos2d::Ref* pSender);  
    15.     void menuItem3Callback(cocos2d::Ref* pSender);  
    16.     void menuItem4Callback(cocos2d::Ref* pSender);  
    17.     void menuItem5Callback(cocos2d::Ref* pSender);  
    18.     void hideAllSprite();  
    19.     cocos2d::Sprite *sprite[5];    
    20.     // implement the "static create()" method manually  
    21.     CREATE_FUNC(HelloWorld);  
    22. };  
    23. #endif // __HELLOWORLD_SCENE_H__  

    声明

    [cpp] view plain copy
    1. #include "HelloWorldScene.h"  
    2. #include "RotateMenu.h"  
    3.   
    4.   
    5. USING_NS_CC;  
    6. typedef struct SceneList{  
    7.     const char *name;  
    8.     std::function<cocos2d::Scene*()> callback;  
    9. }SceneList;  
    10. SceneList sceneList[] = {  
    11.     { "Demo1", [](){return HelloWorld::createScene(); } }  
    12. };  
    13. const unsigned int sceneCount = sizeof(sceneList) / sizeof(SceneList);  
    14. #define LINE_SPACE 40  
    15.   
    16. Scene* HelloWorld::createScene()  
    17. {  
    18.     // 'scene' is an autorelease object  
    19.     auto scene = Scene::create();  
    20.       
    21.     // 'layer' is an autorelease object  
    22.     auto layer = HelloWorld::create();  
    23.   
    24.     // add layer as a child to scene  
    25.     scene->addChild(layer);  
    26.   
    27.     // return the scene  
    28.     return scene;  
    29. }  
    30.   
    31. // on "init" you need to initialize your instance  
    32. bool HelloWorld::init()  
    33. {  
    34.     //////////////////////////////  
    35.     // 1. super init first  
    36.     if ( !Layer::init() )  
    37.     {  
    38.         return false;  
    39.     }  
    40.       
    41.     Size visibleSize = Director::getInstance()->getVisibleSize();  
    42.     Vec2 origin = Director::getInstance()->getVisibleOrigin();  
    43.   
    44.     /////////////////////////////  
    45.     // 2. add a menu item with "X" image, which is clicked to quit the program  
    46.     //    you may modify it.  
    47.   
    48.     // add a "close" icon to exit the progress. it's an autorelease object  
    49.     auto closeItem = MenuItemImage::create(  
    50.                                            "CloseNormal.png",  
    51.                                            "CloseSelected.png",  
    52.                                            CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));  
    53.       
    54.     closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,  
    55.                                 origin.y + closeItem->getContentSize().height/2));  
    56.   
    57.    //  create menu, it's an autorelease object  
    58.   /*  auto menu = Menu::create(closeItem, NULL); 
    59.     menu->setPosition(Vec2::ZERO); 
    60.     this->addChild(menu, 1);*/  
    61.     auto item1 = MenuItemImage::create("Demo1/item1_1.png""Demo1/item1_0.png", CC_CALLBACK_1(HelloWorld::menuItem1Callback, this));  
    62.     auto item2 = MenuItemImage::create("Demo1/item2_1.png""Demo1/item2_0.png", CC_CALLBACK_1(HelloWorld::menuItem2Callback, this));  
    63.     auto item3 = MenuItemImage::create("Demo1/item3_1.png""Demo1/item3_0.png", CC_CALLBACK_1(HelloWorld::menuItem3Callback, this));  
    64.     auto item4 = MenuItemImage::create("Demo1/item4_1.png""Demo1/item4_0.png", CC_CALLBACK_1(HelloWorld::menuItem4Callback, this));  
    65.     auto item5 = MenuItemImage::create("Demo1/item5_1.png""Demo1/item5_0.png", CC_CALLBACK_1(HelloWorld::menuItem5Callback, this));  
    66.   
    67.     RotateMenu *menu = RotateMenu::create();  
    68.       
    69.     menu->addMenuItem(item1);  
    70.     menu->addMenuItem(item2);  
    71.     menu->addMenuItem(item3);  
    72.     menu->addMenuItem(item4);  
    73.     menu->addMenuItem(item5);  
    74.       
    75.     menu->setPosition(visibleSize/2);  
    76.     this->addChild(menu, 2);  
    77.   
    78.   
    79.     for (int i = 0; i < 5; i++){  
    80.         char str[20];  
    81.         sprintf(str, "Demo1/item%d.jpg", i + 1);  
    82.         sprite[i] = Sprite::create(str);  
    83.         sprite[i]->setAnchorPoint(Vec2(0.5f, 0.5f));  
    84.         sprite[i]->setPosition(visibleSize / 2);  
    85.         this->addChild(sprite[i]);  
    86.     }  
    87.     hideAllSprite();  
    88.   
    89.     /////////////////////////////  
    90.     // 3. add your codes below...  
    91.   
    92.   
    93.     // add a label shows "Hello World"  
    94.     // create and initialize a label  
    95.       
    96.     auto label = LabelTTF::create("Hello World""Arial", 24);  
    97.       
    98.     // position the label on the center of the screen  
    99.     label->setPosition(Vec2(origin.x + visibleSize.width/2,  
    100.                             origin.y + visibleSize.height - label->getContentSize().height));  
    101.   
    102.     // add the label as a child to this layer  
    103.     this->addChild(label, 1);  
    104.   
    105.     
    106.   
    107.       
    108.     return true;  
    109. }  
    110.   
    111.   
    112. void HelloWorld::menuCloseCallback(Ref* pSender)  
    113. {  
    114. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)  
    115.     MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");  
    116.     return;  
    117. #endif  
    118.       
    119.     Director::getInstance()->end();  
    120.   
    121. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)  
    122.     exit(0);  
    123. #endif  
    124. }  
    125.   
    126. void HelloWorld::menuItem1Callback(cocos2d::Ref* pSender){  
    127.     hideAllSprite();  
    128.     sprite[0]->setVisible(true);  
    129. }  
    130. void HelloWorld::menuItem2Callback(cocos2d::Ref* pSender){  
    131.     hideAllSprite();  
    132.     sprite[1]->setVisible(true);  
    133. }  
    134. void HelloWorld::menuItem3Callback(cocos2d::Ref* pSender){  
    135.     hideAllSprite();  
    136.     sprite[2]->setVisible(true);  
    137. }  
    138. void HelloWorld::menuItem4Callback(cocos2d::Ref* pSender){  
    139.     hideAllSprite();  
    140.     sprite[3]->setVisible(true);  
    141. }  
    142. void HelloWorld::menuItem5Callback(cocos2d::Ref* pSender){  
    143.     hideAllSprite();  
    144.     sprite[4]->setVisible(true);  
    145. }  
    146.   
    147. void HelloWorld::hideAllSprite(){  
    148.     for (auto p : sprite){  
    149.         if (p->isVisible())  
    150.             p->setVisible(false);  
    151.     }  
    152. }  

    可运行的程序下载地址
  • 相关阅读:
    Oracle优化器:星型转换
    Latches and Tuning:Buffer Cache
    [转]Oracle销售人员普遍腐败?
    Veritas ODM Async and Oracle
    How to set LOGSOURCE PATHMAP on GoldenGate
    Merry Christmas Sql Statement
    Goldengate OGG常见问题与错误列表
    Sqlserver 2005 配置 数据库镜像:1418错误:该错误很可能是安全方面的配置问题引起的
    Sqlserver 2005 配置 数据库镜像:为镜像准备镜像数据库 (TransactSQL)
    Sqlserver 2005 配置 数据库镜像:概述
  • 原文地址:https://www.cnblogs.com/Anzhongliu/p/6091758.html
Copyright © 2020-2023  润新知