基于cocos2dx的伪立体菜单

基于cocos2dx的伪立体菜单,第1张

概述RotateMenu说明 最终效果图 下面这个引用自乱斗西游   设计说明 1.菜单项(MenuItem)平均分布在椭圆(类似)上 2.椭圆长轴为2/3width,短轴为2/8 height 3.最前面的菜单项Scale=1,opacity=255,最后面Scale=0.5,opacity=129.其它位置根据三角函数变换(updatePosition中实现) 4.默认最前面菜单被选中(selec 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"/* *模仿乱斗西游主界面的旋转菜单 */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的伪立体菜单所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1016795.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-22
下一篇2022-05-23

发表评论

登录后才能评论

评论列表(0条)

    保存