****************************************************************************
Time:2015-04-06
Sharing_li
Reprint Annotated Source: http://blog.csdn.net/sharing_li/article/details/44903971
****************************************************************************
General game of the main interface button placement, are the center of vertical alignment, if you make a little bit more dazzling, is the following effect, that is, the content to be explained in this article:
First analyze the functional requirements:
1, altogether four buttons, only then clicked the Front button, the button response event can trigger, clicked the other button, then rotates to the front.
2. Click the animation effect in addition to the front button, and the animation effect when sliding left and right. (Size, transparency, motion trajectory)
3, sliding to the way when the animation adjustment.
4, the adjustment of the button Z-order
5, the limit of the sliding area
Now let's see how the code is written:
Define a class Btnturn, look at the header file
#ifndef __btn_turn_h__#define __btn_turn_h__#include "Cocos2d.h" using_ns_cc;enum btnpos{pos_bottom = 1,Pos_Left,Pos_ Top,pos_right,};class btnturn:public Cocos2d::layer{public:btnturn (); ~btnturn (); virtual bool init (); Create_func (Btnturn) protected:virtual bool Ontouchbegan (touch* touch, event* pevent); virtual void ontouchmoved (Touch * Ptouch, Event *pevent), virtual void ontouchended (Touch *ptouch, event *pevent);//Click the button after the animation void Runtouchedamt (Sprite * BTN)///sliding interface animation void Runslidedamt (bool isleft,float ratio,float judgeposx);p rivate:sprite * M_BTN1; Sprite * M_BTN2; Sprite * M_BTN3; Sprite * M_BTN4; VEC2 M_posbottom; VEC2 M_posleft; VEC2 M_postop; VEC2 M_posright; Point M_firstpos; Size m_winsize;bool m_valid;//First click on the active area bool m_invalid;//first click on the invalid area}; #endif
Here the main core code is the rotation along the elliptical trajectory effect, there is an article on the animation along the elliptical motion, you can use the system moveto, such as using runaction, reference address:
http://blog.csdn.net/sharing_li/article/details/43268877
This article will not be implemented using the method described in the link.
First, we define some global data:
const FLOAT RUNTIME = 0.3; Animation run time float a;//Oval long radius float bd;//Lower ellipse short radius float bu;//Upper ellipse short radius float cx;//Ellipse Center x coordinate float cy;//Ellipse Center y coordinate
Take a look at our initialization function:
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,m_ Winsize.height * 0.15); 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 (+); 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 (a); 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 ( M_btn4->settag (pos_right); This->addchild (m_btn4,3); auto Listenert = Eventlistenertouchonebyone::create (); Listenert->ontouchbegan = Cc_callback_2 (btnturn::ontouchbegan,this); listenert->ontouchmoved = CC_CALLBACK _2 (btnturn::ontouchmoved,this); listenert->ontouchended = Cc_callback_2 (btnturn::ontouchended,this); listenerT- >setswallowtouches (False);D irector::getinstance ()->geteventdispatcher () Addeventlistenerwithscenegraphpriority (listenert,this); return true;
Here, initialize the global variable, and the initial position of the four buttons. You can see that the button here is not a button, but a sprite, because only the front button can respond to the function, so it is defined as a sprite for easy handling. We determine whether the button is clicked by clicking Start and click End, whether the two points are the same point, and then judging the response function based on the zorder of the button. We also set the tag value for each button, the tag value is not constant, because the position of the button will change, so the value of the tag will also change, to ensure that we through the Getchildbytag function, we can correctly obtain the corresponding tag value of the button, such as Getchildbytag ( Pos_top), the function must return the button that is in the topmost position.
Let's take a look at the Ontouchbegan function:
BOOL Btnturn::ontouchbegan (touch* Touch, event* pevent) {m_firstpos = Touch->getlocation (); return true;}
Very simple, just two lines of code, get the Click Start button. And look at ontouchmoved.
void Btnturn::ontouchmoved (Touch *ptouch, Event *pevent) {Auto Movepos = ptouch->getlocation (); Auto Judgepos = this-& Gt;converttonodespace (movepos); auto box = Rect (-m_winsize.width * 0.5,-m_winsize.height * 0.1,m_winsize.width,m_ Winsize.height * 0.4);//optimization, can not slide full screen, and determine whether the first click on the valid or invalid area if (!box.containspoint (Judgepos)) {if (!m_valid) {m_invalid = true;} return;} if (!m_invalid) {m_valid = true;} Else{return;} Motion Auto ratio = FABSF (movepos.x-m_firstpos.x) * 2/M_WINSIZE.WIDTH;IF (ratio >= 1) {return;} According to the sliding direction This->runslidedamt (Movepos.x-m_firstpos.x < 0,RATIO,FABSF (m_firstpos.x-movepos.x));}
The box in the code above is a valid area to swipe, and m_valid and m_invalid are used to determine whether to start touching the screen, whether to click on a valid area or an invalid area.
Then, according to the direction of the slide, call the animation implementation function Runslidedamt:
void Btnturn::runslidedamt (bool isleft,float ratio,float judgeposx) {Auto Btntop = This->getchildbytag (POS_TOP); Auto Btnleft = This->getchildbytag (pos_left); auto Btnright = This->getchildbytag (pos_right); Auto BtnBottom = This->getchildbytag (pos_bottom); auto Deltposdown = M_posright-m_posbottom;auto Deltposup = m_postop-m_posleft;// Determine if you need to swap the Z-order if (Judgeposx > M_winsize.width/4) {btntop->setzorder (3); Btnleft->setzorder (Isleft 2:4); Btnright->setzorder (Isleft 4:2); Btnbottom->setzorder (3);} Auto B1 = Isleft? bu:bd;//judge the left button along which elliptical motion auto B2 = isleft? bd:bu;//judge the right button along which elliptical motion int temp = 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)), Cx,temp (Btnleft->setscale-(0.75. Isleft * 0.25: -0.25 * ratio)); ratio T->setopacity (Isleft * ratio: -155 * ratio)); temp = m_postop.x + (isleft? (deltposup.x * ratio): ( -1 * deltposup.x * ratio)); Btntop->setposition (VEC2 (Temp,sin ((ACOs)/a) * Bu + Cy)); Btntop->setscale (0.5 + 0.25 * ratio); Btntop->setopacity (+ ratio); temp = M_posright.y + (isleft?) ( -1 * DELTPOSDOWN.Y * ratio): (DELTPOSUP.Y * ratio)) btnright->setposition (Vec2 (COS (ASIN (TEMP-CY)/b2) * A + Cx,tem p)); Btnright->setscale (0.75 + 0.25 * (Isleft ratio:-ratio)); Btnright->setopacity (Isleft 155 * Ratio:- (* ratio));}
Here, we use the nonstandard equation of the ellipse to find the corresponding y-coordinate or x-coordinate according to the known x-coordinate or y-coordinate. If the center coordinate of the ellipse is (cx,cy), then according to the equation:
x = A * cosβ+ cx;y = B * sinβ+ Cy;
Then, according to the inverse trigonometric function of the mathematical function library, we can find the corresponding value. It is important to note that the trigonometric and inverse trigonometric function ranges.
Next, let's take a look at the ontouchended function:
void btnturn::ontouchended (Touch *ptouch, Event *pevent) {if (m_invalid) {m_invalid = False;return;} Auto Endpos = ptouch->getlocation (); auto Delx = Endpos.x-m_firstpos.x;auto dely = endpos.y-m_firstpos.y;//If the click action is (FABSF (DELX) < 0.0001 && FABSF (dely) < 0.0001) {Endpos = This->converttonodespace (endpos); auto Box1 = M_btn1->getboundingbox (); Auto Box2 = m_btn2-> Getboundingbox (); Auto Box3 = M_btn3->getboundingbox (); Auto box4 = M_btn4->getboundingbox (); if ( Box1.containspoint (Endpos)) {if (m_btn1->getzorder () = = 4) {log ("******************btn1 callback***************") ;} Else{this->runtouchedamt (M_BTN1);}} else if (Box2.containspoint (Endpos)) {if (m_btn2->getzorder () = = 4) {log ("******************btn2 callback********** *****");} Else{this->runtouchedamt (M_BTN2);}} else if (Box3.containspoint (Endpos)) {if (m_btn3->getzorder () = = 4) {log ("******************btn3 callback********** *****");} Else{this->runtouchedamt (M_BTN3);}} else if (Box4.containspoint (ENdpos) {if (m_btn4->getzorder () = = 4) {log ("******************btn4 callback***************");} Else{this->runtouchedamt (M_BTN4);}}} else//slide operation {Auto Adjustpos = ptouch->getlocation ();//Determine the sliding direction if (Adjustpos.x-m_firstpos.x < 0)//swipe left {auto tmpbtn = ( Sprite *) This->getchildbytag (pos_right); This->runtouchedamt (TMPBTN);} else if (adjustpos.x-m_firstpos.x > 0) {Auto TMPBTN = (Sprite *) This->getchildbytag (pos_left);this-> Runtouchedamt (TMPBTN);}} M_valid = false;}
The
first determines whether the click action, if so, then determines which button was clicked, if it is the first button, the response function, if not the animation effect, if not the click Action, that is the slide operation, and then adjust the animation according to the direction of the slide. Let's take a look at the Runtouchedamt function:
void Btnturn::runtouchedamt (Sprite * btn) {Auto tag = Btn->gettag (); switch (tag) {case Pos_left: {btn->runaction ( Spawn::create (Scaleto::create (runtime,1), Sequence::createwithtwoactions (Moveto::create (Runtime/2,m_posbottom), Moveto::create (Runtime/2,m_posbottom)), Fadein::create (RUNTIME), NULL)); Btn->setzorder (4); auto TOPBTN = (Sprite * ) (This->getchildbytag (Pos_top)); Topbtn->runaction (Spawn::create (scaleto::create), RUNTIME,0.75:: Create (Runtime,m_posleft), Fadeto::create (runtime,100), NULL)); Topbtn->setzorder (3); auto RIGHTBTN = (Sprite *) This->getchildbytag (pos_right); Rightbtn->runaction (Spawn::create (Scaleto::create (RUNTIME,0.5), MoveTo:: Create (Runtime,m_postop), Fadeto::create (runtime,50), NULL)); Rightbtn->setzorder (2); auto BOTTOMBTN = (Sprite *) This->getchildbytag (Pos_bottom); Bottombtn->runaction (Spawn::create (Scaleto::create (RUNTIME,0.75), MoveTo: : Create (Runtime,m_posright), Fadeto::create (runtime,100), NULL)); Bottombtn->setzorder (3); Btn->settag (POs_bottom); Topbtn->settag (Pos_left); Rightbtn->settag (pos_top); Bottombtn->settag (Pos_Right);} Break;case pos_top: {btn->runaction (Spawn::create (scaleto::create), runtime,1 ( Moveto::create (Runtime/2,m_posleft), Moveto::create (Runtime/2,m_posbottom)), Fadein::create (0.2), NULL));btn-> Setzorder (4); auto RIGHTBTN = (Sprite *) This->getchildbytag (pos_right); Rightbtn->runaction (Spawn::create ( Sequence::createwithtwoactions (Scaleto::create (runtime/2,0.5), Scaleto::create (runtime/2,0.75)), Sequence:: Createwithtwoactions (Moveto::create (Runtime/2,m_postop), Moveto::create (Runtime/2,m_posleft)), Sequence:: Createwithtwoactions (Fadeto::create (runtime/2,50), Fadeto::create (runtime/2,100)), NULL); Rightbtn->setzorder (3); auto BOTTOMBTN = (Sprite *) This->getchildbytag (pos_bottom); Bottombtn->runaction (Spawn::create (ScaleTo:: Create (runtime,0.5), Sequence::createwithtwoactions (Moveto::create (runtime/2,m_posright), MoveTo::create (RUNTIME /2,m_postop)), fadeto::creatE (runtime,50), NULL), Bottombtn->setzorder (2), Auto leftbtn = (Sprite *) This->getchildbytag (pos_left); leftbtn- >runaction (Spawn::create (Sequence::createwithtwoactions (Scaleto::create (runtime/2,1), ScaleTo::create ( runtime/2,0.75)), Sequence::createwithtwoactions (Moveto::create (Runtime/2,m_posbottom), MoveTo::create (RUNTIME/2 , M_posright)), Sequence::createwithtwoactions (Fadein::create (RUNTIME/2), Fadeto::create (RUNTIME/2,100)), NULL)); Leftbtn->setzorder (3); Btn->settag (Pos_bottom); Leftbtn->settag (pos_right); Rightbtn->settag (Pos_Left ); Bottombtn->settag (pos_top);} Break;case pos_right: {btn->runaction (Spawn::create (scaleto::create), runtime,1 (moveto::create Posbottom), Fadein::create (RUNTIME), NULL), Btn->setzorder (4), Auto TOPBTN = (Sprite *) This->getchildbytag (pos_ TOP); Topbtn->runaction (Spawn::create (Scaleto::create (runtime,0.75), Moveto::create (Runtime,m_posright), Fadeto::create (runtime,100), NULL); Topbtn->setzorder (3); auto LEFTBTN = (Sprite *) this->gEtchildbytag (Pos_left); Leftbtn->runaction (Spawn::create (Scaleto::create (runtime,0.5), MoveTo::create (RUNTIME , M_postop), Fadeto::create (runtime,50), NULL); Leftbtn->setzorder (2); auto BOTTOMBTN = (Sprite *) this-> Getchildbytag (Pos_bottom); Bottombtn->runaction (Spawn::create (Scaleto::create (runtime,0.75), MoveTo::create ( Runtime,m_posleft), Fadeto::create (runtime,100), NULL); Bottombtn->setzorder (3); Btn->settag (Pos_Bottom); Topbtn->settag (pos_right); Leftbtn->settag (pos_top); Bottombtn->settag (pos_left);} Break;}}
Code seems to be a bit more, in fact, is to handle the click on the other than the front button animation effect. For the sake of simplicity here, there is no ellipse effect, with the MoveTo function.
Here to explain, free download resources
The button of Cocos2dx's rotation