cocos2dx之旋转的button
**************************************************************************** 时间:2015-04-06 作者:Sharing_Li 转载注明出处:http://www.52php.cn/article/p-eymwalux-rx.html **************************************************************************** 一般游戏的主界面按钮的摆放,都是中心垂直对齐,如果弄得稍微炫一点,就是下面的这种效果,也就是本篇要讲解的内容: 先分析一下功能需求: 1、一共四个按钮,只有点击了最前面的按钮,按钮的响应事件才能触发,点击了其他按钮,则旋转到最前面。 2、点击了除最前面的按钮外的动画效果,和左右滑动时的动画效果。(大小,透明度,运动轨迹) 3、左右滑动到途中时松手时的动画调整。 4、按钮Z序的调整 5、滑动区域的限制 接下来看看代码怎么写: 定义一个类BtnTurn,来看头文件 #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); //点击按钮之后的动画 void runTouchedAmt(Sprite * btn); //滑动界面的动画 void runSlidedAmt(bool isLeft,float ratio,float judgePosX); private: 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;//先点击有效区域 bool m_invalid;//先点击无效区域 }; #endif
http://www.52php.cn/article/p-fmhyjmnl-rx.html 本篇将不采用链接中说的方法来实现。 首先,我们定义一些全局数据: const float RUNTIME = 0.3; //动画运行时间 float A;//椭圆长半径 float Bd;//下椭圆短半径 float Bu;//上椭圆短半径 float Cx;//椭圆中心X坐标 float Cy;//椭圆中心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,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(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,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); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listenerT,this); return true;
我们来看看onTouchBegan函数: bool BtnTurn::onTouchBegan(Touch* touch,Event* pEvent) { m_firstPos = touch->getLocation(); return true; } 很简单,就两行代码,获取点击开始的按钮。然后看看onTouchMoved void BtnTurn::onTouchMoved(Touch *pTouch,Event *pEvent) { auto movePos = pTouch->getLocation(); auto judgePos = this->convertToNodeSpace(movePos); auto box = 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 = true; } return ; } if (!m_invalid) { m_valid = true; } else { return ; } //根据滑动方向来运动 auto ratio = fabsf(movePos.x - m_firstPos.x) * 2 / m_winSize.width; if (ratio >= 1) { return ; } this->runSlidedAmt(movePos.x - m_firstPos.x < 0,ratio,fabsf(m_firstPos.x - movePos.x)); } 上面代码中box是可以滑动的有效区域,m_valid和m_invalid是用来判断开始触摸屏幕,是点击了有效区域,还是无效区域。 然后根据滑动的方向,来调用动画实现函数runSlidedAmt: void BtnTurn::runSlidedAmt(bool isLeft,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; //判断是否需要调换Z顺序 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;//判断左边的button沿哪个椭圆运动 auto B2 = isLeft ? Bd : Bu;//判断右边的button沿哪个椭圆运动 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)) * 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,temp)); btnRight->setScale(0.75 + 0.25 * (isLeft ? ratio : -ratio)); btnRight->setOpacity(100 + (isLeft ? 155 * ratio : -50 * ratio)); }
x = A * cosβ + Cx;y = B * sinβ + Cy; 然后根据数学函数库的反三角函数等,就可以求出相应的值了。这里需要注意的是三角函数和反三角函数的值域。 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 (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//滑动操作 { auto adjustPos = pTouch->getLocation(); //判断滑动方向 if (adjustPos.x - m_firstPos.x < 0)//向左滑动 { 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; }
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),MoveTo::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),m_posTop),50),NULL)); rightBtn->setZOrder(2); auto bottomBtn = (Sprite *)this->getChildByTag(Pos_Bottom); bottomBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,m_posRight),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,Sequence::createWithTwoActions(MoveTo::create(RUNTIME/2,MoveTo::create(RUNTIME/2,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,ScaleTo::create(RUNTIME/2,0.75)),m_posLeft)),Sequence::createWithTwoActions(FadeTo::create(RUNTIME/2,FadeTo::create(RUNTIME/2,100)),NULL)); rightBtn->setZOrder(3); auto bottomBtn = (Sprite *)this->getChildByTag(Pos_Bottom); bottomBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,m_posTop)),NULL)); bottomBtn->setZOrder(2); auto leftBtn = (Sprite *)this->getChildByTag(Pos_Left); leftBtn->runAction(Spawn::create(Sequence::createWithTwoActions(ScaleTo::create(RUNTIME/2,m_posRight)),Sequence::createWithTwoActions(FadeIn::create(RUNTIME/2),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,NULL)); btn->setZOrder(4); auto topBtn = (Sprite *)this->getChildByTag(Pos_Top); topBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,NULL)); topBtn->setZOrder(3); auto leftBtn = (Sprite *)this->getChildByTag(Pos_Left); leftBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,NULL)); leftBtn->setZOrder(2); auto bottomBtn = (Sprite *)this->getChildByTag(Pos_Bottom); bottomBtn->runAction(Spawn::create(ScaleTo::create(RUNTIME,NULL)); bottomBtn->setZOrder(3); btn->setTag(Pos_Bottom); topBtn->setTag(Pos_Right); leftBtn->setTag(Pos_Top); bottomBtn->setTag(Pos_Left); } break; } } 代码好像有点多,其实也就是分别处理点击了除最前面按钮的动画效果。这里简单起见,没有用椭圆效果,用的moveto函数。 到这里讲解完毕,免费下载资源 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Oracle密码过期ORA-28001: the password has expired解决办
- objective-c – 如何将来自method1的可变数量的参数传递给m
- xmlhttprequest – Safari将200个对AJAX请求的响应静默转换
- Dojo 事件<10>
- iphone – 在构建/签署应用程序时,Xcode如何使用应用程序ID
- TextView在xml中的onClick方法
- ruby-on-rails-4 – Rails 4:activeadmin错误消息 – Bund
- c# – WPF支持触摸或多点触控屏幕?
- cocos2d-x学习笔记(11)回调CallFunc,lambda
- oracle – 如何在没有更新的情况下导致“ORA-01555:快照太