基于cocos2dx的英雄联盟皮肤选择菜单

最终效果图

英雄联盟皮肤选择

设计说明实现目标所需要的动作

移动

实现目标所需要函数(这是一个数学函数)

x/(x+a)

其中a为常量,用来计算上面三个动作的值

大小

与原版

_index变量

将所有的菜单项平铺构成一个长方形,_index表示目前在中间位置的点,如下图

显示方式

将菜单项距中心的距离

操作说明

滑动四分之一菜单宽的距离为一个单位的

使用

使用这个菜单只要知道两个函数

1.构造函数

LOLMenu::create()(由CREATE_FUNC创建)

2.添加MenuItem

voidaddMenuItem(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();//重置 显示所引号设置为0void reset();private://设置当前显示索引void setIndex(int index);//设置当前显示菜单项的索引号float getIndex();//返回被选中的itemcocos2d::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);//当前被选择的itemcocos2d::MenuItem *_selectedItem;};#endifLOLMenu.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, 0, calcFunction(i – _lastIndex, MENU_ASLOPE), calcFunction(i – _lastIndex, MENU_ASLOPE) – calcFunction(i – _index, MENU_ASLOPE), 0, 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, 1, 0, calcFunction(i – _lastIndex, MENU_ASLOPE), calcFunction(i – _index, MENU_ASLOPE) – calcFunction(i – _lastIndex, MENU_ASLOPE), 0, 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, 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);}elseindex = (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我知道我不是一个很好的记录者,但我比任何人都喜欢回首自己来时的路,

基于cocos2dx的英雄联盟皮肤选择菜单

相关文章:

你感兴趣的文章:

标签云: