如何在cocos2dx中使用cOS为IOS游戏制作滑动菜单

时间:2014-01-11 14:21:45

标签: cocos2d-x

我想制作一个滑动菜单,就像水平菜单一样,在一个屏幕上会有40个精灵分别标记为1级2级,最多40个。 在右下角会有另一个带箭头的精灵,当我点击它时应该滑到其他屏幕并显示41到80级别。请给我一个基本概念如何使用它。我将感谢你。 注意:我正在使用C ++

在cocos2d-x中使用Xcode和ony want解决方案

3 个答案:

答案 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;
   }
}

注意获取分布在多个页面上的项目的公式可能有点棘手。有一个“屏幕分数”的概念,即页面上的项目网格占用了多少。还有“菜单锚点”的概念,它在页面上你想要网格的位置。

一些屏幕截图

enter image description here

enter image description here

答案 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)

我修改了现有的并在github上传。这是链接:

GitHub Link to SlidingMenu

您可能会发现它很有帮助。您可以直接将其添加到游戏中。