cocos2dx之旋转的button

cocos2dx之旋转的button,第1张

概述**************************************************************************** 时间:2015-04-06 作者:Sharing_Li 转载注明出处:http://www.voidcn.com/article/p-eymwalux-rx.html ***************************************

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

时间:2015-04-06

作者:Sharing_li

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

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

先分析一下功能需求:

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

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

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

4、按钮Z序的调整

5、滑动区域的限制

接下来看看代码怎么写:

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

[cpp] view plain copy #ifndef__BTN_TURN_H__ #define__BTN_TURN_H__ #include"cocos2d.h" USING_NS_CC; enumBtnPos { Pos_Bottom=1, Pos_left, 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)"> }; classBtnTurn:publiccocos2d::Layer { public: BtnTurn(); ~BtnTurn(); virtualboolinit(); CREATE_FUNC(BtnTurn) protected: boolontouchBegan(touch*touch,Event*pEvent); virtualvoIDontouchmoved(touch*ptouch,Event*pEvent); voIDontouchended(touch*ptouch,108); List-style:decimal-leading-zero outsIDe; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> //点击按钮之后的动画 voIDruntouchedamt(Sprite*btn); //滑动界面的动画 voIDrunSlIDedamt(boolisleft,floatratio,87); Font-weight:bold; background-color:inherit">floatjudgePosX); private: Sprite*m_btn1; Sprite*m_btn2; Sprite*m_btn3; Sprite*m_btn4; Vec2m_posBottom; Vec2m_posleft; Vec2m_postop; Vec2m_posRight; Pointm_firstPos; Sizem_winSize; boolm_valID;//先点击有效区域 boolm_invalID;//先点击无效区域 #endif


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

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

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

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

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

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

m_winSize=Director::getInstance()->getWinSize(); m_posBottom=Vec2(0,0); m_posleft=Vec2(-m_winSize.wIDth*0.24,m_winSize.height*0.15); m_postop=Vec2(0,m_winSize.height*0.24); m_posRight=Vec2(m_winSize.wIDth*0.24,248)"> A=m_posBottom.x-m_posleft.x; Bu=m_postop.y-m_posleft.y; Bd=m_posleft.y-m_posBottom.y; Cx=m_posBottom.x; Cy=m_posleft.y; Texture2D*pTt2d=Director::getInstance()->getTextureCache()->addImage("BtnTurn/btn.png"); m_btn1=Sprite::createWithTexture(pTt2d); m_btn1->setposition(m_posBottom); m_btn1->setTag(Pos_Bottom); this->addChild(m_btn1,4); m_btn2=Sprite::createWithTexture(pTt2d); m_btn2->setposition(m_posleft); m_btn2->setScale(0.75); m_btn2->setopacity(100); m_btn2->setTag(Pos_left); this->addChild(m_btn2,3); m_btn3=Sprite::createWithTexture(pTt2d); m_btn3->setposition(m_postop); m_btn3->setScale(0.5); m_btn3->setopacity(50); m_btn3->setTag(Pos_top); this->addChild(m_btn3,2); m_btn4=Sprite::createWithTexture(pTt2d); m_btn4->setposition(m_posRight); m_btn4->setScale(0.75); m_btn4->setopacity(100); m_btn4->setTag(Pos_Right); 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(); ListenerT->ontouchBegan=CC_CALLBACK_2(BtnTurn::ontouchBegan,this); ListenerT->ontouchmoved=CC_CALLBACK_2(BtnTurn::ontouchmoved,153); Font-weight:bold; background-color:inherit">this); 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); 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) m_firstPos=touch->getLocation(); true; }

很简单,就两行代码,获取点击开始的按钮。然后看看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(); autojudgePos=this->convertToNodeSpace(movePos); autoBox=Rect(-m_winSize.wIDth*0.5,-m_winSize.height*0.1,m_winSize.wIDth,m_winSize.height*0.4); //优化,不能全屏都可以滑,并判断是先点击有效还是无效区域 if(!Box.containsPoint(judgePos)) if(!m_valID) m_invalID= } return; if(!m_invalID) m_valID=else //根据滑动方向来运动 autoratio=fabsf(movePos.x-m_firstPos.x)*2/m_winSize.wIDth; if(ratio>=1) this->runSlIDedamt(movePos.x-m_firstPos.x<0,ratio,fabsf(m_firstPos.x-movePos.x)); 上面代码中Box是可以滑动的有效区域,m_valID和m_invalID是用来判断开始触摸屏幕,是点击了有效区域,还是无效区域。

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

voIDBtnTurn::runSlIDedamt(floatjudgePosX) autobtntop=this->getChildByTag(Pos_top); autobtnleft=this->getChildByTag(Pos_left); autobtnRight=this->getChildByTag(Pos_Right); autobtnBottom=this->getChildByTag(Pos_Bottom); autodeltPosDown=m_posRight-m_posBottom; autodeltPosUp=m_postop-m_posleft; //判断是否需要调换Z顺序 if(judgePosX>m_winSize.wIDth/4) btntop->setZOrder(3); btnleft->setZOrder(isleft?2:4); btnRight->setZOrder(isleft?4:2); btnBottom->setZOrder(3); autoB1=isleft?Bu:Bd;//判断左边的button沿哪个椭圆运动 autoB2=isleft?Bd:Bu;//判断右边的button沿哪个椭圆运动 inttemp=isleft?(m_posBottom.x-deltPosDown.x*ratio):(m_posBottom.x+deltPosDown.x*ratio); btnBottom->setposition(Vec2(temp,sin(-acos((temp-Cx)/A))*Bd+Cy)); btnBottom->setScale(1-0.25*ratio); btnBottom->setopacity(255-155*ratio); temp=isleft?(m_posleft.y+deltPosUp.y*ratio):(m_posleft.y-deltPosDown.y*ratio); btnleft->setposition(Vec2(-cos(asin((temp-Cy)/B1))*A+Cx,temp)); btnleft->setScale(0.75-(isleft?0.25*ratio:-0.25*ratio)); btnleft->setopacity(100-(isleft?50*ratio:-155*ratio)); temp=m_postop.x+(isleft?(deltPosUp.x*ratio):(-1*deltPosUp.x*ratio)); btntop->setposition(Vec2(temp,sin(acos((temp-Cx)/A))*Bu+Cy)); btntop->setScale(0.5+0.25*ratio); btntop->setopacity(50+50*ratio); temp=m_posRight.y+(isleft?(-1*deltPosDown.y*ratio):(deltPosUp.y*ratio)); btnRight->setposition(Vec2(cos(asin((temp-Cy)/B2))*A+Cx,248)"> btnRight->setScale(0.75+0.25*(isleft?ratio:-ratio)); btnRight->setopacity(100+(isleft?155*ratio:-50*ratio)); }


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

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

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

voID
BtnTurn::ontouchended(touch*ptouch,153); Font-weight:bold; background-color:inherit">if(m_invalID) false; return; } autoendPos=ptouch->getLocation(); autodelX=endPos.x-m_firstPos.x; autodelY=endPos.y-m_firstPos.y; //如果是点击 *** 作 if(fabsf(delX)<0.0001&&fabsf(delY)<0.0001) endPos=this->convertToNodeSpace(endPos); autoBox1=m_btn1->getBoundingBox(); autoBox2=m_btn2->getBoundingBox(); autoBox3=m_btn3->getBoundingBox(); autoBox4=m_btn4->getBoundingBox(); if(Box1.containsPoint(endPos)) if(m_btn1->getZOrder()==4) log("******************Btn1CallBack***************"); this->runtouchedamt(m_btn1); elseif(Box2.containsPoint(endPos)) if(m_btn2->getZOrder()==4) log("******************Btn2CallBack***************"); this->runtouchedamt(m_btn2); if(Box3.containsPoint(endPos)) if(m_btn3->getZOrder()==4) log("******************Btn3CallBack***************"); else this->runtouchedamt(m_btn3); if(Box4.containsPoint(endPos)) if(m_btn4->getZOrder()==4) log("******************Btn4CallBack***************"); this->runtouchedamt(m_btn4); else//滑动 *** 作 autoadjustPos=ptouch->getLocation(); //判断滑动方向 if(adjustPos.x-m_firstPos.x<0)//向左滑动 autotmpBtn=(Sprite*)this->runtouchedamt(tmpBtn); if(adjustPos.x-m_firstPos.x>0) autotmpBtn=(Sprite*)this->runtouchedamt(tmpBtn); m_valID=false;
首先判断是否是点击 *** 作,如果是,再来判断点击了哪个button,如果是最前面的button,就响应函数,如果不是则调用动画效果;如果不是点击 *** 作,那就是滑动 *** 作,然后根据滑动方向调用调整动画。我们来看看runtouchedamt函数:

voIDBtnTurn::runtouchedamt(Sprite*btn) autotag=btn->getTag(); switch(tag) casePos_left: 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)); btn->setZOrder(4); autotopBtn=(Sprite*)(this->getChildByTag(Pos_top)); 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); autorightBtn=(Sprite*)this->getChildByTag(Pos_Right); rightBtn->runAction(Spawn::create(Scaleto::create(RUNTIME,0.5),m_postop),50),248)"> rightBtn->setZOrder(2); autobottomBtn=(Sprite*) bottomBtn->runAction(Spawn::create(Scaleto::create(RUNTIME,m_posRight),248)"> bottomBtn->setZOrder(3); btn->setTag(Pos_Bottom); topBtn->setTag(Pos_left); rightBtn->setTag(Pos_top); bottomBtn->setTag(Pos_Right); break; casePos_top: FadeIn::create(0.2),NulL)); btn->setZOrder(4); 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); autobottomBtn=(Sprite*)this->getChildByTag(Pos_Bottom); 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); autoleftBtn=(Sprite*)this->getChildByTag(Pos_left); 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); btn->setTag(Pos_Bottom); leftBtn->setTag(Pos_Right); rightBtn->setTag(Pos_left); bottomBtn->setTag(Pos_top); casePos_Right: 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); 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); bottomBtn->setZOrder(3); topBtn->setTag(Pos_Right); leftBtn->setTag(Pos_top); bottomBtn->setTag(Pos_left); 代码好像有点多,其实也就是分别处理点击了除最前面按钮的动画效果。这里简单起见,没有用椭圆效果,用的moveto函数。

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

总结

以上是内存溢出为你收集整理的cocos2dx之旋转的button全部内容,希望文章能够帮你解决cocos2dx之旋转的button所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1076597.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存