我想制作一个滑动菜单,就像水平菜单一样,在一个屏幕上会有40个精灵分别标记为1级2级,最多40个。 在右下角会有另一个带箭头的精灵,当我点击它时应该滑到其他屏幕并显示41到80级别。请给我一个基本概念如何使用它。我将感谢你。 注意:我正在使用C ++
在cocos2d-x中使用Xcode和ony want解决方案答案 0 :(得分:3)
这就是我过去这样做的方式......我有一个游戏,玩家可以选择多个太空船,每页4个,每页还有后退/前进箭头。
创建CCScene派生类。
放置所有菜单项,包括所有页面的控制箭头。您必须将所有项目分开,以便第一页的项目位于屏幕的可见部分,下一组是右侧100%折扣,第三组是右侧200%,等等。
场景上的控制按钮开始动作,将图层向左移动100%(如果向右移动)或向右移动100%(如果向左移动)。
所有这些都附加到单个“菜单”,这是应用操作的内容。如果需要,可以将菜单放入图层(因此它具有移动的背景)。这取决于你。
在下面的示例场景中,我只使用了一个简单的菜单。
<强> MainScene.h 强>
#ifndef __MainScene__
#define __MainScene__
#include "cocos2d.h"
using namespace cocos2d;
class MainScene : public CCScene
{
private:
// This class follows the "create"/"autorelease" pattern.
// Private constructor.
MainScene();
CCMenu* _menu;
bool _sliding;
void MenuCallback(CCObject* sender);
void PageLeft();
void PageRight();
void SlidingDone();
protected:
// This is protected so that derived classes can call it
// in their create methods.
bool init();
private:
void CreateMenu();
public:
static MainScene* create();
~MainScene();
virtual void onEnter();
virtual void onExit();
virtual void onEnterTransitionDidFinish();
virtual void onExitTransitionDidStart();
};
#endif /* defined(__MainScene__) */
<强> MainScene.cpp 强>
#include "MainScene.h"
#define ARROW_LEFT (-1)
#define ARROW_RIGHT (-2)
#define MENU_ITEMS_ACROSS 4
#define MENU_ITEMS_DOWN 5
#define MENU_ITEMS_PAGE (MENU_ITEMS_ACROSS*MENU_ITEMS_DOWN)
#define MENU_ITEMS_TOTAL 50
#define MENU_PAGES ((MENU_ITEMS_TOTAL/MENU_ITEMS_PAGE)+1)
#define MENU_FRACTION (ccp(0.8,0.8))
#define MENU_ANCHOR (ccp(0.5,0.5))
#define SLIDE_DURATION 1.0
MainScene::MainScene() :
_menu(NULL)
_sliding(false)
{
}
MainScene::~MainScene()
{
}
static CCPoint CalculatePosition(int itemNum)
{
CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
float Xs = scrSize.width;
float Ys = scrSize.height;
int gRows = MENU_ITEMS_DOWN;
int gCols = MENU_ITEMS_ACROSS;
int gBins = gRows*gCols;
float Xb = MENU_FRACTION.x*Xs/gCols;
float Yb = MENU_FRACTION.y*Ys/gRows;
float Xa = MENU_ANCHOR.x * Xs;
float Ya = MENU_ANCHOR.y * Ys;
int page = itemNum / gBins;
int binCol = itemNum % gCols;
int binRow = (itemNum-page*gBins) / gCols;
float xPos = binCol * Xb + Xb/2 + Xa - MENU_FRACTION.x*Xs/2 + page * Xs;
float yPos = Ya - binRow*Yb - Yb/2 + MENU_FRACTION.y * Ys/2;
CCPoint pos = ccp(xPos,yPos);
return pos;
}
void MainScene::CreateMenu()
{
if(_menu == NULL)
{
CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
_menu = CCMenu::create();
_menu->setPosition(ccp(0,0));
addChild(_menu);
CCMenuItemFont* pItem;
CCPoint position;
// Create the next/back menu items.
for(int page = 0; page < MENU_PAGES; page++)
{
// Create the Back/Forward buttons for the page.
// Back arrow if there is a previous page.
if(page > 0)
{
pItem = CCMenuItemFont::create("Back", this, menu_selector(MainScene::MenuCallback));
pItem->setTag(ARROW_LEFT);
position = ccp(page*scrSize.width + scrSize.width*0.1,scrSize.height*0.1);
pItem->setPosition(position);
pItem->setFontSize(35);
pItem->setFontName("Arial");
_menu->addChild(pItem);
}
if(page < (MENU_PAGES-1))
{
pItem = CCMenuItemFont::create("Next", this, menu_selector(MainScene::MenuCallback));
pItem->setTag(ARROW_RIGHT);
position = ccp(page*scrSize.width + scrSize.width*0.9,scrSize.height*0.1);
pItem->setPosition(position);
pItem->setFontSize(35);
pItem->setFontName("Arial");
_menu->addChild(pItem);
}
}
// Create the actual items
for(int idx = 0; idx < MENU_ITEMS_TOTAL; idx++)
{
char buffer[256];
sprintf(buffer,"Item #%d",idx);
pItem = CCMenuItemFont::create(buffer, this, menu_selector(MainScene::MenuCallback));
pItem->setFontSize(35);
pItem->setFontName("Arial");
pItem->setTag(idx);
position = CalculatePosition(idx);
pItem->setPosition(position);
_menu->addChild(pItem);
}
}
}
bool MainScene::init()
{
return true;
}
MainScene* MainScene::create()
{
MainScene *pRet = new MainScene();
if (pRet && pRet->init())
{
pRet->autorelease();
return pRet;
}
else
{
CC_SAFE_DELETE(pRet);
return NULL;
}
}
void MainScene::onEnter()
{
CCScene::onEnter();
CreateMenu();
}
void MainScene::onExit()
{
CCScene::onExit();
}
void MainScene::onEnterTransitionDidFinish()
{
CCScene::onEnterTransitionDidFinish();
}
void MainScene::onExitTransitionDidStart()
{
CCScene::onExitTransitionDidStart();
}
void MainScene::SlidingDone()
{
_sliding = false;
}
void MainScene::PageLeft()
{
if(_sliding)
return;
_sliding = true;
CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
CCFiniteTimeAction* act1 = CCMoveBy::create(SLIDE_DURATION, ccp(scrSize.width,0));
CCFiniteTimeAction* act2 = CCCallFunc::create(this, callfunc_selector(MainScene::SlidingDone));
_menu->runAction(CCSequence::create(act1,act2,NULL));
}
void MainScene::PageRight()
{
if(_sliding)
return;
_sliding = true;
CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
CCFiniteTimeAction* act1 = CCMoveBy::create(SLIDE_DURATION, ccp(-scrSize.width,0));
CCFiniteTimeAction* act2 = CCCallFunc::create(this, callfunc_selector(MainScene::SlidingDone));
_menu->runAction(CCSequence::create(act1,act2,NULL));
}
void MainScene::MenuCallback(CCObject* sender)
{
// This is a very contrived example
// for handling the menu items.
// -1 ==> Left Arrow
// -2 ==> Right Arrow
// Anything else is a selection
CCMenuItem* pMenuItem = (CCMenuItem*)sender;
switch(pMenuItem->getTag())
{
case ARROW_LEFT:
PageLeft();
break;
case ARROW_RIGHT:
PageRight();
break;
default:
CCLOG("Got Item %d Pressed",pMenuItem->getTag());
break;
}
}
注意获取分布在多个页面上的项目的公式可能有点棘手。有一个“屏幕分数”的概念,即页面上的项目网格占用了多少。还有“菜单锚点”的概念,它在页面上你想要网格的位置。
一些屏幕截图
答案 1 :(得分:1)
或者你可以用更少的代码以现代的方式做到这一点!!
// you have to include this header to use the ui classes
#include "ui/CocosGUI.h"
using namespace ui;
#define COLS 4
#define ROWS 4
#define ITEMS_PER_PAGE (ROWS * COLS)
#define TOTAL_PAGES_NUM 10
#define MENU_PADDING (Vec2(0.8,0.8))
#define MENU_ANCHOR (Vec2(0.5,0.5))
static Vec2 calcPosition(int itemNum)
{
Size scrSize = Director::getInstance()->getWinSize();
float Xs = scrSize.width;
float Ys = scrSize.height;
float Xb = MENU_PADDING.x*Xs / COLS;
float Yb = MENU_PADDING.y*Ys / ROWS;
float Xa = MENU_ANCHOR.x * Xs;
float Ya = MENU_ANCHOR.y * Ys;
int page = itemNum / ITEMS_PER_PAGE;
int binCol = itemNum % COLS;
int binRow = (itemNum - page * ITEMS_PER_PAGE) / COLS;
float xPos = binCol * Xb + Xb / 2 + Xa - MENU_PADDING.x*Xs / 2 + page * Xs;
float yPos = Ya - binRow*Yb - Yb / 2 + MENU_PADDING.y * Ys / 2;
return Vec2(xPos, yPos);
}
//init method
// pageView is the container that will contain all pages
auto pageView = PageView::create();
pageView->setContentSize(winSize);
//if you want pages indicator just uncomment this
//pageView->setIndicatorEnabled(true);
//pageView->setIndicatorPosition(some position);
//pageView->setIndicatorSelectedIndexColor(some Color3B);
for (int i = 0; i < TOTAL_PAGES_NUM; i++) {
auto layout = Layout::create();
layout->setContentSize(winSize);
// give each page a different random color
int r = rand() % 200;
int g = rand() % 200;
int b = rand() % 200;
auto bg = LayerColor::create(Color4B(Color3B(r, g, b)), winSize.width, winSize.height);
layout->addChild(bg, 0);
// populate each single page with items (which are in this case labels)
for (int i = 0; i < ITEMS_PER_PAGE; i++) {
auto label = LabelTTF::create(StringUtils::format("item %i", (i + 1)), "Comic Sans MS", 15);
Vec2 pos = calcPosition(i);
label->setPosition(pos);
layout->addChild(label, 1);
}
pageView->addPage(layout);
}
this->addChild(pageView);
答案 2 :(得分:0)