首页 > 代码库 > Cocos2d-x 3.2 学习笔记(十四)保卫萝卜之界面UI

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);  }}
四、最新进度
 
     目前,数据库、场景都已构架完毕,可以看下效果了。(地图太多了……时间不充裕目前只做了一个场景)
技术分享

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