cocos2dx之旋转的button

前端之家收集整理的这篇文章主要介绍了cocos2dx之旋转的button前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

****************************************************************************

时间:2015-04-06

作者:Sharing_Li

转载注明出处:http://www.jb51.cc/article/p-eymwalux-rx.html

一般游戏的主界面按钮的摆放,都是中心垂直对齐,如果弄得稍微炫一点,就是下面的这种效果,也就是本篇要讲解的内容

先分析一下功能需求:

1、一共四个按钮,只有点击了最前面的按钮,按钮的响应事件才能触发,点击了其他按钮,则旋转到最前面。

2、点击了除最前面的按钮外的动画效果,和左右滑动时的动画效果。(大小,透明度,运动轨迹)

3、左右滑动到途中时松手时的动画调整。

4、按钮Z序的调整

5、滑动区域的限制

接下来看看代码怎么写:

定义一个类BtnTurn,来看头文件

  1. #ifndef__BTN_TURN_H__
  2. #define__BTN_TURN_H__
  3. #include"cocos2d.h"
  4. USING_NS_CC;
  5. enumBtnPos
  6. {
  7. Pos_Bottom=1,
  8. Pos_Left,
  9. Pos_Top,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Pos_Right,248)"> };
  10. classBtnTurn:publiccocos2d::Layer
  11. {
  12. public:
  13. BtnTurn();
  14. ~BtnTurn();
  15. virtualboolinit();
  16. CREATE_FUNC(BtnTurn)
  17. protected:
  18. boolonTouchBegan(Touch*touch,Event*pEvent);
  19. virtualvoidonTouchMoved(Touch*pTouch,Event*pEvent);
  20. voidonTouchEnded(Touch*pTouch,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> //点击按钮之后的动画
  21. voidrunTouchedAmt(Sprite*btn);
  22. //滑动界面的动画
  23. voidrunSlidedAmt(boolisLeft,floatratio,87); font-weight:bold; background-color:inherit">floatjudgePosX);
  24. private:
  25. Sprite*m_btn1;
  26. Sprite*m_btn2;
  27. Sprite*m_btn3;
  28. Sprite*m_btn4;
  29. Vec2m_posBottom;
  30. Vec2m_posLeft;
  31. Vec2m_posTop;
  32. Vec2m_posRight;
  33. Pointm_firstPos;
  34. Sizem_winSize;
  35. boolm_valid;//先点击有效区域
  36. boolm_invalid;//先点击无效区域
  37. #endif


这里最主要的核心代码就是沿椭圆轨迹旋转效果,之前有篇文章讲解了沿椭圆运动的动画,可以像用系统的MoveTo等使用runAction,参考地址:

http://www.jb51.cc/article/p-fmhyjmnl-rx.html

本篇将不采用链接中说的方法来实现。

首先,我们定义一些全局数据:

    constfloatRUNTIME=0.3;//动画运行时间
  1. floatA;//椭圆长半径
  2. floatBd;//下椭圆短半径
  3. floatBu;//上椭圆短半径
  4. floatCx;//椭圆中心X坐标
  5. floatCy;//椭圆中心Y坐标

再来看看我们的初始化函数

    m_winSize=Director::getInstance()->getWinSize();
  1. m_posBottom=Vec2(0,0);
  2. m_posLeft=Vec2(-m_winSize.width*0.24,m_winSize.height*0.15);
  3. m_posTop=Vec2(0,m_winSize.height*0.24);
  4. m_posRight=Vec2(m_winSize.width*0.24,248)"> A=m_posBottom.x-m_posLeft.x;
  5. Bu=m_posTop.y-m_posLeft.y;
  6. Bd=m_posLeft.y-m_posBottom.y;
  7. Cx=m_posBottom.x;
  8. Cy=m_posLeft.y;
  9. Texture2D*pTt2d=Director::getInstance()->getTextureCache()->addImage("BtnTurn/btn.png");
  10. m_btn1=Sprite::createWithTexture(pTt2d);
  11. m_btn1->setPosition(m_posBottom);
  12. m_btn1->setTag(Pos_Bottom);
  13. this->addChild(m_btn1,4);
  14. m_btn2=Sprite::createWithTexture(pTt2d);
  15. m_btn2->setPosition(m_posLeft);
  16. m_btn2->setScale(0.75);
  17. m_btn2->setOpacity(100);
  18. m_btn2->setTag(Pos_Left);
  19. this->addChild(m_btn2,3);
  20. m_btn3=Sprite::createWithTexture(pTt2d);
  21. m_btn3->setPosition(m_posTop);
  22. m_btn3->setScale(0.5);
  23. m_btn3->setOpacity(50);
  24. m_btn3->setTag(Pos_Top);
  25. this->addChild(m_btn3,2);
  26. m_btn4=Sprite::createWithTexture(pTt2d);
  27. m_btn4->setPosition(m_posRight);
  28. m_btn4->setScale(0.75);
  29. m_btn4->setOpacity(100);
  30. m_btn4->setTag(Pos_Right);
  31. this->addChild(m_btn4,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> autolistenerT=EventListenerTouchOneByOne::create();
  32. listenerT->onTouchBegan=CC_CALLBACK_2(BtnTurn::onTouchBegan,this);
  33. listenerT->onTouchMoved=CC_CALLBACK_2(BtnTurn::onTouchMoved,153); font-weight:bold; background-color:inherit">this);
  34. listenerT->onTouchEnded=CC_CALLBACK_2(BtnTurn::onTouchEnded,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> listenerT->setSwallowTouches(false);
  35. Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraPHPriority(listenerT,153); font-weight:bold; background-color:inherit">returntrue;


这里,初始化全局变量,和四个按钮的初始位置。可以发现这里的按钮并不是按钮,而是sprite,因为只有显示在最前面的按钮才能响应函数,所以定义成sprite方便处理。我们通过判断点击开始和点击结束,这两个点是否是同一个点来确定是否点击了按钮,然后根据按钮的Zorder来判断是否响应函数。我们还给每个按钮设置了tag值,这个tag值并不是不变的,因为按钮的位置会改变,所以tag的值也会改变,以确保我们通过getChildByTag函数,能够正确获取到相应tag值的按钮,比如getChildByTag(Pos_Top),函数返回的一定是处于最上面位置的那个按钮。

我们来看看onTouchBegan函数

    boolBtnTurn::onTouchBegan(Touch*touch,Event*pEvent)
  1. m_firstPos=touch->getLocation();
  2. true;
  3. }

很简单,就两行代码获取点击开始的按钮。然后看看onTouchMoved

    voidBtnTurn::onTouchMoved(Touch*pTouch,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> automovePos=pTouch->getLocation();
  1. autojudgePos=this->convertToNodeSpace(movePos);
  2. autoBox=Rect(-m_winSize.width*0.5,-m_winSize.height*0.1,m_winSize.width,m_winSize.height*0.4);
  3. //优化,不能全屏都可以滑,并判断是先点击有效还是无效区域
  4. if(!Box.containsPoint(judgePos))
  5. if(!m_valid)
  6. m_invalid= }
  7. return;
  8. if(!m_invalid)
  9. m_valid=else
  10. //根据滑动方向来运动
  11. autoratio=fabsf(movePos.x-m_firstPos.x)*2/m_winSize.width;
  12. if(ratio>=1)
  13. this->runSlidedAmt(movePos.x-m_firstPos.x<0,ratio,fabsf(m_firstPos.x-movePos.x));
  14. 上面代码Box是可以滑动的有效区域,m_valid和m_invalid是用来判断开始触摸屏幕,是点击了有效区域,还是无效区域。

    然后根据滑动的方向,来调用动画实现函数runSlidedAmt:

      voidBtnTurn::runSlidedAmt(floatjudgePosX)
    1. autobtnTop=this->getChildByTag(Pos_Top);
    2. autobtnLeft=this->getChildByTag(Pos_Left);
    3. autobtnRight=this->getChildByTag(Pos_Right);
    4. autobtnBottom=this->getChildByTag(Pos_Bottom);
    5. autodeltPosDown=m_posRight-m_posBottom;
    6. autodeltPosUp=m_posTop-m_posLeft;
    7. //判断是否需要调换Z顺序
    8. if(judgePosX>m_winSize.width/4)
    9. btnTop->setZOrder(3);
    10. btnLeft->setZOrder(isLeft?2:4);
    11. btnRight->setZOrder(isLeft?4:2);
    12. btnBottom->setZOrder(3);
    13. autoB1=isLeft?Bu:Bd;//判断左边的button沿哪个椭圆运动
    14. autoB2=isLeft?Bd:Bu;//判断右边的button沿哪个椭圆运动
    15. inttemp=isLeft?(m_posBottom.x-deltPosDown.x*ratio):(m_posBottom.x+deltPosDown.x*ratio);
    16. btnBottom->setPosition(Vec2(temp,sin(-acos((temp-Cx)/A))*Bd+Cy));
    17. btnBottom->setScale(1-0.25*ratio);
    18. btnBottom->setOpacity(255-155*ratio);
    19. temp=isLeft?(m_posLeft.y+deltPosUp.y*ratio):(m_posLeft.y-deltPosDown.y*ratio);
    20. btnLeft->setPosition(Vec2(-cos(asin((temp-Cy)/B1))*A+Cx,temp));
    21. btnLeft->setScale(0.75-(isLeft?0.25*ratio:-0.25*ratio));
    22. btnLeft->setOpacity(100-(isLeft?50*ratio:-155*ratio));
    23. temp=m_posTop.x+(isLeft?(deltPosUp.x*ratio):(-1*deltPosUp.x*ratio));
    24. btnTop->setPosition(Vec2(temp,sin(acos((temp-Cx)/A))*Bu+Cy));
    25. btnTop->setScale(0.5+0.25*ratio);
    26. btnTop->setOpacity(50+50*ratio);
    27. temp=m_posRight.y+(isLeft?(-1*deltPosDown.y*ratio):(deltPosUp.y*ratio));
    28. btnRight->setPosition(Vec2(cos(asin((temp-Cy)/B2))*A+Cx,248)"> btnRight->setScale(0.75+0.25*(isLeft?ratio:-ratio));
    29. btnRight->setOpacity(100+(isLeft?155*ratio:-50*ratio));
    30. }


    这里,我们通过椭圆的非标准方程,根据已知的x坐标或者y坐标,求出对应的y坐标或x坐标。假如椭圆的圆心坐标为(Cx,Cy),那么根据方程:

    x = A * cosβ + Cx;y = B * sinβ + Cy;

    然后根据数学函数库的反三角函数等,就可以求出相应的值了。这里需要注意的是三角函数和反三角函数的值域。
    接着,我们来看看onTouchEnded函数

      voidBtnTurn::onTouchEnded(Touch*pTouch,153); font-weight:bold; background-color:inherit">if(m_invalid)
    1. false;
    2. return;
    3. }
    4. autoendPos=pTouch->getLocation();
    5. autodelX=endPos.x-m_firstPos.x;
    6. autodelY=endPos.y-m_firstPos.y;
    7. //如果是点击操作
    8. if(fabsf(delX)<0.0001&&fabsf(delY)<0.0001)
    9. endPos=this->convertToNodeSpace(endPos);
    10. autoBox1=m_btn1->getBoundingBox();
    11. autoBox2=m_btn2->getBoundingBox();
    12. autoBox3=m_btn3->getBoundingBox();
    13. autoBox4=m_btn4->getBoundingBox();
    14. if(Box1.containsPoint(endPos))
    15. if(m_btn1->getZOrder()==4)
    16. log("******************Btn1CallBack***************");
    17. this->runTouchedAmt(m_btn1);
    18. elseif(Box2.containsPoint(endPos))
    19. if(m_btn2->getZOrder()==4)
    20. log("******************Btn2CallBack***************");
    21. this->runTouchedAmt(m_btn2);
    22. if(Box3.containsPoint(endPos))
    23. if(m_btn3->getZOrder()==4)
    24. log("******************Btn3CallBack***************");
    25. else
    26. this->runTouchedAmt(m_btn3);
    27. if(Box4.containsPoint(endPos))
    28. if(m_btn4->getZOrder()==4)
    29. log("******************Btn4CallBack***************");
    30. this->runTouchedAmt(m_btn4);
    31. else//滑动操作
    32. autoadjustPos=pTouch->getLocation();
    33. //判断滑动方向
    34. if(adjustPos.x-m_firstPos.x<0)//向左滑动
    35. autotmpBtn=(Sprite*)this->runTouchedAmt(tmpBtn);
    36. if(adjustPos.x-m_firstPos.x>0)
    37. autotmpBtn=(Sprite*)this->runTouchedAmt(tmpBtn);
    38. m_valid=false;

    39. 首先判断是否是点击操作,如果是,再来判断点击了哪个button,如果是最前面的button,就响应函数,如果不是则调用动画效果;如果不是点击操作,那就是滑动操作,然后根据滑动方向调用调整动画。我们来看看runTouchedAmt函数

        voidBtnTurn::runTouchedAmt(Sprite*btn)
      1. autotag=btn->getTag();
      2. switch(tag)
      3. casePos_Left:
      4. btn->runAction(Spawn::create(ScaleTo::create(RUNTIME,1),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Sequence::createWithTwoActions(MoveTo::create(RUNTIME/2,m_posBottom),248)"> MoveTo::create(RUNTIME/2,m_posBottom)),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> FadeIn::create(RUNTIME),NULL));
      5. btn->setZOrder(4);
      6. autotopBtn=(Sprite*)(this->getChildByTag(Pos_Top));
      7. topBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,0.75),248)"> MoveTo::create(RUNTIME,m_posLeft),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> FadeTo::create(RUNTIME,100),248)"> topBtn->setZOrder(3);
      8. autorightBtn=(Sprite*)this->getChildByTag(Pos_Right);
      9. rightBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,0.5),m_posTop),50),248)"> rightBtn->setZOrder(2);
      10. autobottomBtn=(Sprite*) bottomBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,m_posRight),248)"> bottomBtn->setZOrder(3);
      11. btn->setTag(Pos_Bottom);
      12. topBtn->setTag(Pos_Left);
      13. rightBtn->setTag(Pos_Top);
      14. bottomBtn->setTag(Pos_Right);
      15. break;
      16. casePos_Top:
      17. FadeIn::create(0.2),NULL));
      18. btn->setZOrder(4);
      19. autorightBtn=(Sprite*) rightBtn->runAction(Spawn::create(Sequence::createWithTwoActions(ScaleTo::create(RUNTIME/2,ScaleTo::create(RUNTIME/2,0.75)),m_posLeft)),248)"> Sequence::createWithTwoActions(FadeTo::create(RUNTIME/2,FadeTo::create(RUNTIME/2,100)),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> rightBtn->setZOrder(3);
      20. autobottomBtn=(Sprite*)this->getChildByTag(Pos_Bottom);
      21. bottomBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,m_posTop)),248)"> FadeTo::create(RUNTIME,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> bottomBtn->setZOrder(2);
      22. autoleftBtn=(Sprite*)this->getChildByTag(Pos_Left);
      23. leftBtn->runAction(Spawn::create(Sequence::createWithTwoActions(ScaleTo::create(RUNTIME/2,m_posRight)),248)"> Sequence::createWithTwoActions(FadeIn::create(RUNTIME/2),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> leftBtn->setZOrder(3);
      24. btn->setTag(Pos_Bottom);
      25. leftBtn->setTag(Pos_Right);
      26. rightBtn->setTag(Pos_Left);
      27. bottomBtn->setTag(Pos_Top);
      28. casePos_Right:
      29. MoveTo::create(RUNTIME,248)"> FadeIn::create(RUNTIME),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> autotopBtn=(Sprite*) topBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> topBtn->setZOrder(3);
      30. leftBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> leftBtn->setZOrder(2);
      31. bottomBtn->setZOrder(3);
      32. topBtn->setTag(Pos_Right);
      33. leftBtn->setTag(Pos_Top);
      34. bottomBtn->setTag(Pos_Left);
      35. 代码好像有点多,其实也就是分别处理点击了除最前面按钮的动画效果。这里简单起见,没有用椭圆效果,用的moveto函数

        到这里讲解完毕,免费下载资源

        原文链接:https://www.f2er.com/cocos2dx/340410.html

        猜你在找的Cocos2d-x相关文章