
下面这个引用自乱斗西游
设计说明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"/* *模仿乱斗西游主界面的旋转菜单 */class RotateMenu :public cocos2d::Layer{public: //构造方法 CREATE_FUNC(RotateMenu); //添加菜单项 voID addMenuItem(cocos2d::MenuItem *item); //更新位置 voID updateposition(); //更新位置,有动画 voID updatepositionWithAnimation(); //位置矫正 修改角度 forward为移动方向 当超过1/3,进1 //true 为正向 false 负 voID rectify(bool forward); //初始化 virtual bool init(); //重置 *** 作有旋转角度设为0 voID reset();private: //设置角度 弧度 voID setAngle(float angle); float getAngle(); //设置单位角度 弧度 voID setUnitAngle(float angle); float getUnitAngle(); //滑动距离转换角度,转换策略为 移动半个Menu.wIDth等于_unitAngle float disToAngle(float dis); //返回被选中的item cocos2d::MenuItem * getCurrentItem();private: //菜单已经旋转角度 弧度 float _angle; //菜单项集合,_children顺序会变化,新建数组保存顺序 cocos2d::Vector<cocos2d::MenuItem *> _items; //单位角度 弧度 float _unitAngle; //监听函数 virtual bool ontouchBegan(cocos2d::touch* touch,cocos2d::Event* event); virtual voID ontouchended(cocos2d::touch* touch,cocos2d::Event* event); virtual voID ontouchmoved(cocos2d::touch* touch,cocos2d::Event* event); //动画完结调用函数 voID actionEndCallBack(float dx); //当前被选择的item cocos2d::MenuItem *_selectedItem; //动画运行时间 float animationDuration = 0.3f;};#endif 实现
#include "RotateMenu.h"#include <math.h>#define PI acos(-1)USING_NS_CC;bool RotateMenu::init(){ if (!Layer::init()) return false; _angle = 0.0; this->ignoreAnchorPointForposition(false); _selectedItem = nullptr; Size s = Director::getInstance()->getWinSize(); this->setContentSize(s/3*2); this->setAnchorPoint(Vec2(0.5f,0.5f)); auto Listener = EventListenertouchOneByOne::create(); Listener->ontouchBegan = CC_CALLBACK_2(RotateMenu::ontouchBegan,this); Listener->ontouchmoved = CC_CALLBACK_2(RotateMenu::ontouchmoved,this); Listener->ontouchended = CC_CALLBACK_2(RotateMenu::ontouchended,this); getEventdispatcher()->addEventListenerWithSceneGraPHPriority(Listener,this); return true;};voID RotateMenu::addMenuItem(cocos2d::MenuItem *item){ item->setposition(this->getContentSize() / 2); this->addChild(item); _items.pushBack(item); setUnitAngle(2 * PI / _items.size()); reset(); updatepositionWithAnimation(); return;}voID RotateMenu::updateposition(){ auto menuSize = getContentSize(); auto disY = menuSize.height / 8; auto disX = menuSize.wIDth / 3; for (int i = 0; i < _items.size(); i++){ float x = menuSize.wIDth / 2 + disX*sin(i*_unitAngle+getAngle()); float y = menuSize.height / 2 - disY*cos(i*_unitAngle + getAngle()); _items.at(i)->setposition(Vec2(x,y)); _items.at(i)->setZOrder(-(int)y); //Opacity 129~255 _items.at(i)->setopacity(192 + 63 * cos(i*_unitAngle + getAngle())); _items.at(i)->setScale(0.75 + 0.25*cos(i*_unitAngle + getAngle())); } return;}voID RotateMenu::updatepositionWithAnimation(){ //先停止所有可能存在的动作 for (int i = 0; i < _items.size(); i++) _items.at(i)->stopAllActions(); auto menuSize = getContentSize(); auto disY = menuSize.height / 8; auto disX = menuSize.wIDth / 3; for (int i = 0; i < _items.size(); i++){ float x = menuSize.wIDth / 2 + disX*sin(i*_unitAngle + getAngle()); float y = menuSize.height / 2 - disY*cos(i*_unitAngle + getAngle()); auto moveto = Moveto::create(animationDuration,Vec2(x,y)); _items.at(i)->runAction(moveto); //Opacity 129~255 auto fadeto = Fadeto::create(animationDuration,(192 + 63 * cos(i*_unitAngle + getAngle()))); _items.at(i)->runAction(fadeto); //缩放比例 0.5~1 auto scaleto = 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); return;}voID RotateMenu::reset(){ _angle = 0;}voID RotateMenu::setAngle(float angle){ this->_angle = angle;}float RotateMenu::getAngle(){ return _angle;}voID RotateMenu::setUnitAngle(float angle){ _unitAngle = angle;}float RotateMenu::getUnitAngle(){ return _unitAngle;}float RotateMenu::disToAngle(float dis){ float wIDth = this->getContentSize().wIDth / 2; return dis / wIDth*getUnitAngle();}MenuItem * RotateMenu::getCurrentItem(){ if (_items.size() == 0) return nullptr; //这里实际加上了0.1getAngle(),用来防止精度丢失 int index = (int)((2 * PI - getAngle()) / getUnitAngle()+0.1*getUnitAngle()); index %= _items.size(); return _items.at(index);}bool RotateMenu::ontouchBegan(touch* touch,Event* event){ //先停止所有可能存在的动作 for (int i = 0; i < _items.size(); i++) _items.at(i)->stopAllActions(); if (_selectedItem) _selectedItem->unselected(); auto position = this->convertToNodeSpace(touch->getLocation()); auto size = this->getContentSize(); auto rect = Rect(0,size.wIDth,size.height); if (rect.containsPoint(position)){ return true; } return false;}voID RotateMenu::ontouchended(touch* touch,Event* event){ auto xDelta = touch->getLocation().x - touch->getStartLocation().x; rectify(xDelta>0); if (disToAngle(fabs(xDelta))<getUnitAngle() / 6&&_selectedItem) _selectedItem->activate(); updatepositionWithAnimation(); return;}voID RotateMenu::ontouchmoved(touch* touch,Event* event){ auto angle = disToAngle(touch->getDelta().x); setAngle(getAngle() + angle); updateposition(); return;}voID RotateMenu::rectify(bool forward){ auto angle = 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 angle = ((int)((angle + getUnitAngle() / 3 ) / getUnitAngle()))*getUnitAngle(); setAngle(angle);}voID RotateMenu::actionEndCallBack(float dx){ _selectedItem = getCurrentItem(); if(_selectedItem) _selectedItem->selected();} 一个糟糕的Demo
声明
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"class HelloWorld : public cocos2d::Layer{public: // there's no 'ID' in cpp,so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'ID' in cocos2d-iphone virtual bool init(); // a selector callback voID menuCloseCallback(cocos2d::Ref* pSender); voID menuItem1Callback(cocos2d::Ref* pSender); voID menuItem2Callback(cocos2d::Ref* pSender); voID menuItem3Callback(cocos2d::Ref* pSender); voID menuItem4Callback(cocos2d::Ref* pSender); voID menuItem5Callback(cocos2d::Ref* pSender); voID hIDeAllSprite(); cocos2d::Sprite *sprite[5]; // implement the "static create()" method manually CREATE_FUNC(HelloWorld);};#endif // __HELLOWORLD_SCENE_H__ 声明
#include "HelloWorldScene.h"#include "RotateMenu.h"USING_NS_CC;typedef struct SceneList{ const char *name; std::function<cocos2d::Scene*()> callback;}SceneList;SceneList sceneList[] = { { "Demo1",[](){return HelloWorld::createScene(); } }};const unsigned int sceneCount = sizeof(sceneList) / sizeof(SceneList);#define liNE_SPACE 40Scene* HelloWorld::createScene(){ // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene;}// on "init" you need to initialize your instancebool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image,which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object auto closeItem = MenuItemImage::create( "Closenormal.png","CloseSelected.png",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this)); closeItem->setposition(Vec2(origin.x + visibleSize.wIDth - closeItem->getContentSize().wIDth/2,origin.y + closeItem->getContentSize().height/2)); // create menu,it's an autorelease object /* auto menu = Menu::create(closeItem,NulL); menu->setposition(Vec2::ZERO); this->addChild(menu,1);*/ auto item1 = MenuItemImage::create("Demo1/item1_1.png","Demo1/item1_0.png",CC_CALLBACK_1(HelloWorld::menuItem1Callback,this)); auto item2 = MenuItemImage::create("Demo1/item2_1.png","Demo1/item2_0.png",CC_CALLBACK_1(HelloWorld::menuItem2Callback,this)); auto item3 = MenuItemImage::create("Demo1/item3_1.png","Demo1/item3_0.png",CC_CALLBACK_1(HelloWorld::menuItem3Callback,this)); auto item4 = MenuItemImage::create("Demo1/item4_1.png","Demo1/item4_0.png",CC_CALLBACK_1(HelloWorld::menuItem4Callback,this)); auto item5 = MenuItemImage::create("Demo1/item5_1.png","Demo1/item5_0.png",CC_CALLBACK_1(HelloWorld::menuItem5Callback,this)); 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); for (int i = 0; i < 5; i++){ char str[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. add your codes below... // add a label shows "Hello World" // create and initialize a label auto label = LabelTTF::create("Hello World","Arial",24); // position the label on the center of the screen label->setposition(Vec2(origin.x + visibleSize.wIDth/2,origin.y + visibleSize.height - label->getContentSize().height)); // add the label as a child to this layer this->addChild(label,1); return true;}voID HelloWorld::menuCloseCallback(Ref* pSender){#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. windows Store Apps do not implement a close button.","Alert"); return;#endif Director::getInstance()->end();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0);#endif}voID HelloWorld::menuItem1Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[0]->setVisible(true);}voID HelloWorld::menuItem2Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[1]->setVisible(true);}voID HelloWorld::menuItem3Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[2]->setVisible(true);}voID HelloWorld::menuItem4Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[3]->setVisible(true);}voID HelloWorld::menuItem5Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[4]->setVisible(true);}voID HelloWorld::hIDeAllSprite(){ for (auto p : sprite){ if (p->isVisible()) p->setVisible(false); }} 可运行的程序下载地址
作者:CCY
联系方式:810278677@qq.com
总结以上是内存溢出为你收集整理的基于cocos2dx的伪立体菜单全部内容,希望文章能够帮你解决基于cocos2dx的伪立体菜单所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)