• Cocos2d-x 3.2 学习笔记(十四)保卫萝卜之界面UI


         保卫萝卜~上一篇说了使用CocoStudio制作主界面,这里来完善主界面动画及后续界面(主题界面ThemeUI、场景选择界面SelectMapUI),主要涉及的控件PageView。
      学习要写笔记,记录自己的步骤(练手作)。
    一、主界面动画
     
         上一篇的主界面是静态的,这样很不好看。如果有玩过保卫萝卜就知道它的主界面是动的,云啊、叶子啊都在动,OK加几行代码来实现。
    先看效果图:
      加入如下代码:
    bool MenuScene :: init()
    {
          if ( !Layer :: init() )
          {
               return false ;
          }
        
        
          cocos2d ::ui :: Widget* layout = cocostudio ::GUIReader :: getInstance()-> widgetFromJsonFile ("MainUi.json" );
          this ->addChild ( layout);
          Button * btnAdventure = ( Button*) layout ->getChildByName ( "btnAdventure");
          Button * btnBossHome = ( Button*) layout ->getChildByName ( "btnBossHome");
          Button * btnBoss = ( Button*) layout ->getChildByName ( "btnBoss");
          btnAdventure ->addTouchEventListener ( this, toucheventselector (MenuScene :: btnClick));
          btnBossHome ->addTouchEventListener ( this, toucheventselector (MenuScene :: btnClick));
          btnBoss ->addTouchEventListener ( this, toucheventselector (MenuScene :: btnClick));
        
          ImageView * cloud1 = ( ImageView*) layout ->getChildByName ( "cloud1");
          ImageView * cloud2 = ( ImageView*) layout ->getChildByName ( "cloud2");
          Vec2 size = Director ::getInstance ()-> getVisibleSize();
          cloud1 ->runAction ( RepeatForever:: create (Sequence :: create( MoveBy ::create ( 10,
               Vec2 (size . x+ cloud1 ->getCustomSize (). width, 0 )),Place :: create( Vec2 (0 , cloud1-> getPositionY ())),nullptr )));
          cloud2 ->runAction ( RepeatForever:: create (Sequence :: create( MoveBy ::create ( 20,
               Vec2 (size . x+ cloud2 ->getCustomSize (). width, 0 )),Place :: create( Vec2 (0 , cloud2-> getPositionY ())),nullptr )));
          ImageView * bird = ( ImageView*) layout ->getChildByName ( "bird");
          bird ->runAction ( RepeatForever:: create (
               Sequence ::create (
               MoveBy ::create ( 1, Vec2 (0 , 50)),
               MoveBy ::create ( 1, Vec2 (0 ,- 50)), nullptr )));
    
          ImageView * leaf2 = ( ImageView*) layout ->getChildByName ( "leaf2");
          ImageView * leaf3 = ( ImageView*) layout ->getChildByName ( "leaf3");
          RotateTo * rotateTo = RotateTo:: create (0.1f , 20);
          RotateTo * rotateTo2 = RotateTo:: create (0.1f , 0);
          leaf2 ->runAction ( RepeatForever:: create (
               Sequence ::create (
               Repeat ::create ( Sequence:: create (rotateTo , rotateTo2, nullptr ),2 ),
               DelayTime ::create ( 5), nullptr )));
          leaf3 ->runAction ( RepeatForever:: create (
               Sequence ::create (
               DelayTime ::create ( 8),
               Repeat ::create ( Sequence:: create (rotateTo , rotateTo2, nullptr ),2 ),
               DelayTime ::create ( 4), nullptr )));
    
          return true ;
    }
      OK,加入动作表现之后界面利马生动起来。
     
    二、主题选择
     
      1、场景UI制作
         菜单部分使用PageView控件,这个控件是翻页效果,先看效果:
     
         在CocoStudio中创建ThemeUI并使用PageView控件如:
     
     
      2、加入舞台
      这里有五个页面,分别是
      天际主题、森林主题、沙漠主题、海底主题、未开放的极地,
      每个页面下面的sign标签是通关数和总关卡数,这里是需要变动的。
      PageView控件可以使用手指滑动,也要有按钮的互动,因此有两个左右按钮,点击左上角的home会返回主界面。
      首先,把导出的json文件加至舞台,添加事件以及默认页:
    cocos2d::ui::Widget* layout = cocostudio::GUIReader::getInstance()->widgetFromJsonFile("ThemeUI/ThemeUI.json");
      this->addChild(layout);
    
      Button* btnMenu = (Button*)layout->getChildByName("btnMenu");
      _btnLeft = (Button*)layout->getChildByName("btnLeft");
      _btnRight = (Button*)layout->getChildByName("btnRight");
      btnMenu->addTouchEventListener(this,toucheventselector(ThemeScene::btnClickMenu));
      _btnLeft->addTouchEventListener(this,toucheventselector(ThemeScene::btnClickLeft));
      _btnRight->addTouchEventListener(this,toucheventselector(ThemeScene::btnClickRight));
    
      _pageView = (PageView*)layout->getChildByName("pageView");
      _pageView->addEventListenerPageView(this,pagevieweventselector(ThemeScene::pageEvent));
      int index = _pageView->getPages().size();
      while (index-->0)
      {
        Layout* pageIndex = (Layout*)_pageView->getPage(index);
        pageIndex->setUserData((int*)index);
        pageIndex->addTouchEventListener(this,toucheventselector(ThemeScene::layputEvent));
      }
      changePage( 0 );
      这里有两个事件  1、PageView的翻动事件。2、点击PageView子页的事件
      这里有两个注意点
      1、翻动PageView要与按钮对应,首页左向按钮消失,尾页右向按钮消失
      2、点击按钮翻动PageView
    void ThemeScene::btnClickLeft(Button* btn, TouchEventType eventType)
    {
      if( eventType == TOUCH_EVENT_ENDED )
      {
        auto nextPage = _pageView->getCurPageIndex() - 1;
        changePage( nextPage );
      }
    }
    
    void ThemeScene::btnClickRight(Button* btn, TouchEventType eventType)
    {
      if( eventType == TOUCH_EVENT_ENDED )
      {
        auto nextPage = _pageView->getCurPageIndex() + 1;
        changePage( nextPage );
      }
    }
    
    void ThemeScene::changePage( int index )
    {
      auto totalPage = _pageView->getPages().size();
      _btnLeft->setVisible( index != 0 );
      _btnRight->setVisible( index != ( totalPage-1 ) );
    
      if( index == _pageView->getCurPageIndex() ) return;
    
      if( index >= 0 && index <= totalPage-1 )
      {
        _pageView->scrollToPage( index );
      }
    }
    
    void ThemeScene::pageEvent(Ref* page,PageViewEventType type)
    {
      log("EventType");
      changePage( _pageView->getCurPageIndex() );
    }
      这样不管是按钮还是触摸都可以正确的显示按钮状态。
     
      3、场景选择处理
      在初始化PageView子页的时候加入了标记数据UserData,这个数据表示选择的场景类型
    enum MapType
    {
      Sky_Type,
      Forest_Type,
      Desert_Type,
      Seabed_Type,
      Max_Type
    };
      这里的场景类型在后面的逻辑中是非常重要的数据,因此要找个地方去存储。
      选择主题事件触发
    void ThemeScene::layputEvent(Layout* layout, TouchEventType eventType)
    {
      if( eventType == TOUCH_EVENT_ENDED )
      {
        int sign = (int)layout->getUserData();
        log("layputEvent  %d",(int)layout->getUserData());
        if( sign >= 0 && sign < MapType::Max_Type )
        {
          auto type = MapType((int)layout->getUserData());
          SelectMapModel::getInstance()->setmapType(type);
          Director::getInstance()->replaceScene(SelectMapUI::createScene());
        }
        else
        {
          log("not open");
        }
      }
    }
      Ok这样就没有任何问题了。目前关于数据记录的方法还没有完全想好,所以子页的sign显示就是默认的。
    三、地图选择
     
         1、场景UI制作
      场景类型MapType对应【1、2、3、6】
     
      这里也有一个PageView,这里面只做了一个pageItem,所有的地图子页都是一样的,可以用代码clone一下。当然每个场景的资源名字都是一样的,根据地图类型进行了区分。
      OK,看下效果吧:
     
     
       2、初始化地图
         首先,Json文件加入舞台,然后加入事件,初始化PageView。先拿到一个PageView子页,然后去初始化子页再clone添加至PageView
    _pageView = (PageView*)layout->getChildByName("panelSky")->getChildByName("pageView");
      Layout* item = (Layout*)_pageView->getChildByName("pageItem");
      item->removeFromParent();
      _pageView->removeAllPages();
      int count = SelectMapModel::getInstance()->getMapCount(SelectMapModel::getInstance()->getmapType());
      for (int idx = 1; idx <= count; idx++)
      {
        createOnlyPage(_pageView,item,idx);
      }
    
    void SelectMapUI::createOnlyPage(PageView* page,Layout* item, int idx)
    {
      std::string url = SelectMapModel::getInstance()->getMapResPath(SelectMapModel::getInstance()->getmapType());
      ImageView* mapImg = (ImageView*)item->getChildByName("mapImg");
      ImageView* towers = (ImageView*)item->getChildByName("towers");
      
      mapImg->loadTexture(url+StringUtil::combination("ss_map%02d.png",idx));
      towers->loadTexture(url+StringUtil::combination("ss_towers_%02d.png",idx));
    
      page->addPage((Layout*)item->clone());
    }
      其中自写StringUtil::combination是字符组合类,图片的路径都是通过MapType类决定的,根据选择不同的主题来决定地图数及图片路径。
      ”开始“按钮,根据选择的地图来决定战斗场景的初始化。
    void SelectMapUI::btnClick(Button* btn, TouchEventType eventType)
    {
      if( eventType == TOUCH_EVENT_ENDED )
      {
        log("click btn is %s",btn->getName().c_str());
        int sceneID = _pageView->getCurPageIndex() + 1;
        SceneMgr::getInstance()->replaceScene(sceneID);
      }
    }
    四、最新进度
     
         目前,数据库、场景都已构架完毕,可以看下效果了。(地图太多了……时间不充裕目前只做了一个场景)
  • 相关阅读:
    [转]距离的计算方法
    [转]C#算法题
    varchar和nvarchar区别
    Request.QueryString 的用法
    CommandBehavior.CloseConnection有何作用
    fileupload简单使用
    (二十九)商品管理-添加商品
    (二十八)分类信息的curd-分类信息删除
    (二十七)分类信息的curd-分类信息修改
    (二十六)分类信息的curd-分类信息添加
  • 原文地址:https://www.cnblogs.com/Richard-Core/p/4228124.html
Copyright © 2020-2023  润新知