cocos2dx --- Action综合应用二:椭圆运动Action
转载:http://blog.csdn.net/ufolr/article/details/7447773 ufolr
cocos2dx中提供了一些常用的action,但有时为了实现某种特效,需要定义自己的Action。这篇博文展现了通过继承CCActionInterval实现了椭圆运动Action。大家可以根据ufolr博主的思想,举一反三实现自己的Action。
思路:根据椭圆方程(在实现当中尽量用参数方程,避免复杂平方的计算), 在每一帧中更新Sprite的位置
实现:确定一个椭圆的条件,需要知道空间位置(中心点坐标)、长半轴(a)、和短半轴(b)(或者知道半焦距(c))。因此需要三个量来确定一个椭圆,所以在LRActionInterval.h中定义一个包含三个成员的结构来作为我们生成椭圆的参数:
1 // 定义一个结构来包含确定椭圆的参数 2 typedef struct _lrTuoyuanConfig { 3 //中心点坐标 4 CCPoint centerPosition; 5 //椭圆a长,三角斜边 6 float aLength; 7 //椭圆c长,三角底边 8 float cLength; 9 } lrTuoyuanConfig;
定义椭圆Action类
1 class LRTuoyuanBy : public CCActionInterval 2 { 3 public: 4 //用“动作持续时间”和“椭圆控制参数”初始化动作 5 bool initWithDuration(float t, const lrTuoyuanConfig& c); 6 virtual void update(float time);//利用update函数来不断的设定坐标 7 public: 8 //用“动作持续时间”和“椭圆控制参数”创建动作 9 static LRTuoyuanBy *actionWithDuration(float t, const lrTuoyuanConfig& c); 10 11 protected: 12 lrTuoyuanConfig m_sConfig; 13 CCPoint m_startPosition; 14 CCPoint s_startPosition; 15 };
其实设定路径就是不断的刷新,将路径上的点赋给执行action的对象。因此,既然需要做一个椭圆的轨迹,就需要得到椭圆上每个点的坐标值,然后将其赋给执行action的对象。 参数方程:x=acos(θ),y=bsin(θ);利用这个一次方程可以直观的计算出当前坐标点。由椭圆的参数方程可以分别写出返回X/Y坐标值的函数:
1 #define 3.1415926 PI 2 static inline float tuoyuanXat( float a, float bx, float c, float t )//返回X坐标 3 { 4 //参数方程 5 return -a*cos(2*PI*t)+a; 6 } 7 static inline float tuoyuanYat( float a, float by, float c, float t )//返回Y坐标 8 { 9 float b = sqrt(powf(a, 2) - powf(c, 2));//因为之前定义的参数是焦距c而不是短半轴b,所以需要计算出b 10 //参数方程 11 return b*sin(2*PI*t); 12 }
然后根据中心、a、c确定椭圆:
1 // 2 //TuoyuanBy 3 // 4 LRTuoyuanBy* LRTuoyuanBy::actionWithDuration(float t, const lrTuoyuanConfig& c)//利用之前定义的椭圆的三个参数初始化椭圆 5 { 6 LRTuoyuanBy *pTuoyuanBy = new LRTuoyuanBy(); 7 pTuoyuanBy->initWithDuration(t, c); 8 pTuoyuanBy->autorelease(); 9 10 return pTuoyuanBy; 11 } 12 13 bool LRTuoyuanBy::initWithDuration(float t, const lrTuoyuanConfig& c) 14 { 15 if (CCActionInterval::initWithDuration(t)) 16 { 17 m_sConfig = c; 18 return true; 19 } 20 21 return false; 22 } 23 void LRTuoyuanBy::update(float time) 24 { 25 if (m_pTarget) 26 { 27 CCPoint s_startPosition =m_sConfig.centerPosition;//中心点坐标 28 float a = m_sConfig.aLength; 29 float bx = m_sConfig.centerPosition.x; 30 float by = m_sConfig.centerPosition.y; 31 float c = m_sConfig.cLength; 32 float x = tuoyuanXat(a, bx, c, time);//调用之前的坐标计算函数来计算出坐标值 33 float y = tuoyuanYat(a, by, c, time); 34 m_pTarget->setPosition(ccpAdd(s_startPosition, ccp(x-a, y)));//由于我们画计算出的椭圆你做值是以原点为中心的,所以需要加上我们设定的中心点坐标 35 } 36 }