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,来看头文件

#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@H_301_47@ 


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

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

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

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

const float RUNTIME = 0.3; //动画运行时间float A;//椭圆长半径float Bd;//下椭圆短半径float Bu;//上椭圆短半径float Cx;//椭圆中心X坐标float Cy;//椭圆中心Y坐标@H_301_47@ 

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

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;@H_301_47@ 


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

我们来看看ontouchBegan函数:

bool BtnTurn::ontouchBegan(touch* touch,Event* pEvent){	m_firstPos = touch->getLocation();	return true;}@H_301_47@ 

很简单,就两行代码,获取点击开始的按钮。然后看看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));}@H_301_47@ 

上面代码中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));	}@H_301_47@ 


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

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

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

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;}@H_301_47@ 


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

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;	}}@H_301_47@ 

代码好像有点多,其实也就是分别处理点击了除最前面按钮的动画效果。这里简单起见,没有用椭圆效果,用的moveto函数。

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

总结

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

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

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

原文地址:https://54852.com/web/1053447.html

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

发表评论

登录后才能评论

评论列表(0条)

    保存