移动(Moveto),伸缩(Scaleto),倾斜(OrbitCamera)
实现目标所需要函数(这是一个数学函数)x/(x+a)
其中a为常量,用来计算上面三个动作的值
大小与原版Menu不同,大小不是全屏的,默认是屏幕的(2/3),可以通过setContentSize()函数设置
_index变量
将所有的菜单项平铺构成一个长方形,_index表示目前在中间位置的点,如下图
显示方式将菜单项距中心的距离(i-_indxe)作为函数变量x,具体内容查看LolMenu::updateposition();
*** 作说明滑动四分之一菜单宽的距离为一个单位的_index,距离大于0.6小于1.0的部分进1
使用使用这个菜单只要知道两个函数
1.构造函数LolMenu::create()(由CREATE_FUNC创建)
2.添加MenuItemvoIDaddMenuItem(cocos2d::MenuItem*item);
其它函数可以看代码
菜单代码 LolMenu.h#ifndef __Lol__TE_MENU_H__#define __Lol__TE_MENU_H__#include "cocos2d.h"/**模仿英雄联盟的皮肤选择菜单*不同点在于,英雄联盟当皮肤过多时,部分皮肤会移出边缘,不显示*我会显示所以菜单项,向边缘移动会不断减缓*/class LolMenu :public cocos2d::Layer{public: //构造方法 CREATE_FUNC(LolMenu); //添加菜单项 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 setIndex(int index); //设置当前显示菜单项的索引号 float getIndex(); //返回被选中的item cocos2d::MenuItem * getCurrentItem(); //数学计算式wIDth*index/(abs(index)+CALC_A),其中CALC_A为常数 float calcFunction(float index,float wIDth);private: //菜单菜单项的索引号 float _index; //上一次菜单项的索引号 float _lastIndex; //菜单项集合,_children顺序会变化,新建数组保存顺序 cocos2d::Vector<cocos2d::MenuItem *> _items; //监听函数 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;};#endif
LolMenu.cpp
#include "LolMenu.h"#include <math.h>#define PI acos(-1)//菜单的缩小比例 最小的比例是1-MENU_SCALE#define MENU_SCALE 0.3//菜单的倾斜度 最多为45度#define MENU_ASLOPE 60.0//calcFunction(x) 为 x/(x+a),其中a为常数#define CALC_A 1//动画运行时间#define ANIMATION_DURATION 0.3f //菜单项的大小与屏幕的比例,当然可以通过setContentSize设置#define CONTENT_SIZE_SCALE (2.0/3)//菜单项长度与菜单长度的比例 滑动一个菜单项长度,菜单项变化一个#define ITEM_SIZE_SCALE (1.0/4)/* 代码里面还有可以设置的参数,这里没有一一例出或给出函数 */USING_NS_CC;bool LolMenu::init(){ if (!Layer::init()) return false; _index=0; _lastIndex = 0; this->ignoreAnchorPointForposition(false); _selectedItem = nullptr; auto size = Director::getInstance()->getWinSize(); this->setContentSize(size*CONTENT_SIZE_SCALE); this->setAnchorPoint(Vec2(0.5f,0.5f)); auto Listener = EventListenertouchOneByOne::create(); Listener->ontouchBegan = CC_CALLBACK_2(LolMenu::ontouchBegan,this); Listener->ontouchmoved = CC_CALLBACK_2(LolMenu::ontouchmoved,this); Listener->ontouchended = CC_CALLBACK_2(LolMenu::ontouchended,this); getEventdispatcher()->addEventListenerWithSceneGraPHPriority(Listener,this); return true;};voID LolMenu::addMenuItem(cocos2d::MenuItem *item){ item->setposition(this->getContentSize() / 2); this->addChild(item); _items.pushBack(item); reset(); //如果希望开始没有移动效果,改成updateposition函数即可 updatepositionWithAnimation(); return;}voID LolMenu::updateposition(){ auto menuSize = getContentSize(); for (int i = 0; i < _items.size(); i++){ //设置位置 float x = calcFunction(i - _index,menuSize.wIDth / 2); _items.at(i)->setposition(Vec2(menuSize.wIDth/2+x,menuSize.height/2)); //设置zOrder,即绘制顺序 _items.at(i)->setZOrder(-abs((i - _index) * 100)); //设置伸缩比例 _items.at(i)->setScale(1.0-abs(calcFunction(i - _index,MENU_SCALE))); //设置倾斜,Node没有setCamera函数,将OrbitCamera的运行时间设为0来达到效果 auto orbit1 = OrbitCamera::create(0,1,calcFunction(i - _lastIndex,MENU_ASLOPE),MENU_ASLOPE) - calcFunction(i - _index,0); _items.at(i)->runAction(orbit1); } return;}voID LolMenu::updatepositionWithAnimation(){ //先停止所有可能存在的动作 for (int i = 0; i < _items.size(); i++) _items.at(i)->stopAllActions(); auto menuSize = getContentSize(); for (int i = 0; i < _items.size(); i++){ _items.at(i)->setZOrder(-abs((i - _index)*100)); float x = calcFunction(i - _index,menuSize.wIDth / 2); auto moveto = Moveto::create(ANIMATION_DURATION,Vec2(menuSize.wIDth / 2 + x,menuSize.height / 2)); _items.at(i)->runAction(moveto); auto scaleto = Scaleto::create(ANIMATION_DURATION,(1 - abs(calcFunction(i - _index,MENU_SCALE)))); _items.at(i)->runAction(scaleto); auto orbit1 = OrbitCamera::create(ANIMATION_DURATION,calcFunction(i - _index,MENU_ASLOPE) - calcFunction(i - _lastIndex,0); _items.at(i)->runAction(orbit1); } scheduleOnce(schedule_selector(LolMenu::actionEndCallBack),ANIMATION_DURATION); return;}voID LolMenu::reset(){ _lastIndex = 0; _index = 0;}voID LolMenu::setIndex(int index){ _lastIndex = _index; this->_index = index;}float LolMenu::getIndex(){ return _index;}MenuItem * LolMenu::getCurrentItem(){ if (_items.size() == 0) return nullptr; return _items.at(_index);}bool LolMenu::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 LolMenu::ontouchended(touch* touch,Event* event){ auto size = getContentSize(); auto xDelta = touch->getLocation().x - touch->getStartLocation().x; rectify(xDelta>0); if (abs(xDelta)<size.wIDth / 24 && _selectedItem) _selectedItem->activate(); updatepositionWithAnimation(); return;}voID LolMenu::ontouchmoved(touch* touch,Event* event){ auto xDelta = touch->getDelta().x; auto size = getContentSize(); _lastIndex = _index; _index -= xDelta / (size.wIDth *ITEM_SIZE_SCALE); updateposition(); return;}voID LolMenu::rectify(bool forward){ auto index = getIndex(); if (index < 0) index = 0; if (index>_items.size() - 1) index = _items.size() - 1; if (forward){ index = (int)(index + 0.4); } else index = (int)(index + 0.6); setIndex((int)index);}voID LolMenu::actionEndCallBack(float dx){ _selectedItem = getCurrentItem(); if (_selectedItem) _selectedItem->selected();}float LolMenu::calcFunction(float index,float wIDth){ return wIDth*index / (abs(index) + CALC_A);}
演示代码 LolMenuDemo.h
#ifndef __LolMenu_SCENE_H__#define __LolMenu_SCENE_H__#include "cocos2d.h"class LolMenuDemo : 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(LolMenuDemo);};#endif // __HELLOWORLD_SCENE_H__
LolMenuDemo.cpp
#include "LolMenuDemo.h"#include "LolMenu.h"USING_NS_CC;Scene* LolMenuDemo::createScene(){ // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = LolMenuDemo::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene;}// on "init" you need to initialize your instancebool LolMenuDemo::init(){ ////////////////////////////// // 1. super init first if (!Layer::init()) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto item1 = MenuItemImage::create("4_Lol_MENU/item1_0.png","4_Lol_MENU/item1_0.png",CC_CALLBACK_1(LolMenuDemo::menuItem1Callback,this)); auto item2 = MenuItemImage::create("4_Lol_MENU/item2_0.png","4_Lol_MENU/item2_0.png",CC_CALLBACK_1(LolMenuDemo::menuItem2Callback,this)); auto item3 = MenuItemImage::create("4_Lol_MENU/item3_0.png","4_Lol_MENU/item3_0.png",CC_CALLBACK_1(LolMenuDemo::menuItem3Callback,this)); auto item4 = MenuItemImage::create("4_Lol_MENU/item4_0.png","4_Lol_MENU/item4_0.png",CC_CALLBACK_1(LolMenuDemo::menuItem4Callback,this)); auto item5 = MenuItemImage::create("4_Lol_MENU/item5_0.png","4_Lol_MENU/item5_0.png",CC_CALLBACK_1(LolMenuDemo::menuItem5Callback,this)); LolMenu *menu = LolMenu::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[100]; sprintf(str,"4_Lol_MENU/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(); return true;}voID LolMenuDemo::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 LolMenuDemo::menuItem1Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[0]->setVisible(true);}voID LolMenuDemo::menuItem2Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[1]->setVisible(true);}voID LolMenuDemo::menuItem3Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[2]->setVisible(true);}voID LolMenuDemo::menuItem4Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[3]->setVisible(true);}voID LolMenuDemo::menuItem5Callback(cocos2d::Ref* pSender){ hIDeAllSprite(); sprite[4]->setVisible(true);}voID LolMenuDemo::hIDeAllSprite(){ for (auto p : sprite){ if (p->isVisible()) p->setVisible(false); }}
可运行的程序(需要安装vs2013或相关dll文件)
所有源代码
有任何问题可以发邮件给我 810278677@qq.com
PS 这种类型的菜单在网页里会常见一些,比如优酷的动漫专题或者App Store都可以看到类似的影子,由于是平面的,菜单项的切换不是很自然,我通过倾斜来变得自然。 总结
以上是内存溢出为你收集整理的基于cocos2dx的英雄联盟皮肤选择菜单全部内容,希望文章能够帮你解决基于cocos2dx的英雄联盟皮肤选择菜单所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)