自定义Action
cocos2d-x 为我们提供许多常见Action,如 CCMove,CCFadeIn..., 这些action可以满足我们常见的一些需求,当然,我们也能自已定义Action来满足更多效果,以下提供两个例子
1.自定义一个EclipseAction,使目标做椭圆形运动
#include <iostream>
#include "cocos2d.h"
USING_NS_CC;
//所有以时间来控制运动的action都需要继承CCActionInterval
class EclipseAction : public CCActionInterval
{
public:
EclipseAction();
//初始化action
bool initWithDuration(float duration,CCPoint orgin,float a,float b);
virtual void startWithTarget(CCNode *pTarget);
virtual void update(float time);
public:
//类似引擎的对象创建构造,duration表示运动一周的时间,orgin表示圆心坐标,a/b分别表示椭圆长半轴和短半轴,a = b时,显然,轨迹是一个标准圆
static EclipseAction * create(float duration,CCPoint orgin,float a,float b);
//设置对象是否根据圆曲线进行旋转
void setIsRotated(bool value);
//设置初始旋转角度
void setStartRotation(float r);
private:
bool m_isRotate;
CCPoint m_orgin;
float m_a;
float m_b;
float m_startrotation;
};
EclipseAction.cpp
#include "EclipseAction.h"
EclipseAction::EclipseAction()
{
m_isRotate = false;
m_startrotation = 0;
}
EclipseAction * EclipseAction::create(float duration, cocos2d::CCPoint orgin, float a, float b)
{
EclipseAction * result = newEclipseAction();
result->initWithDuration(duration, orgin, a, b);
result->autorelease();
return result;
}
void EclipseAction::startWithTarget(cocos2d::CCNode *pTarget)
{
CCActionInterval::startWithTarget(pTarget);
}
bool EclipseAction::initWithDuration(float duration, cocos2d::CCPoint orgin, float a, float b)
{
if (CCActionInterval::initWithDuration(duration))
{
m_orgin = orgin;
m_a = a;
m_b = b;
return true;
}
returnfalse;
}
void EclipseAction::setIsRotated(bool value)
{
m_isRotate = value;
}
void EclipseAction::setStartRotation(float r)
{
m_startrotation = r;
}
void EclipseAction::update(float time)
{
if (m_pTarget)
{
//这里的time就相当于当前时间占总的需要运行时间的百分比
//这里根据椭圆标准方程来设定轨迹:(x - x0) * (x - x0) / a*a + (y - y0) * (y - y0) / b * b = 1。
CCPoint oldP = m_pTarget->getPosition();
float X = m_orgin.x + m_a * cos( 2 * 3.14 * (time + m_startrotation));
float Y = m_orgin.y + m_b * sin( 2 * 3.14 * (time + m_startrotation));
m_pTarget->setPosition(X, Y);
//change by ho
CCPoint newP = m_pTarget->getPosition();
if (m_isRotate)
{
float distX = newP.x - oldP.x;
float distY = newP.y - oldP.y;
float angleDes = 180 + (90 - 180 * atan2(distY, distX) / 3.14);
m_pTarget->setRotation(angleDes);
}
}
}
2. 自定义一个抛物线轨迹:从当前点,呈抛物线轨迹运动到目标点
class ParabolaAction :public CCActionInterval
{
public:
bool initWithDuration(float duration, const CCPoint& position);
virtual void startWithTarget(CCNode *pTarget);
virtual void update(float time);
public:
/** creates the action */
static ParabolaAction* createParabolaAction(float duration, const CCPoint& position);
protected:
CCPoint m_endPosition;
CCPoint m_startPosition;
CCPoint m_delta;
float a;
float b;
float c;
};
#include "ParabolaAction.h"
void ParabolaAction::startWithTarget(cocos2d::CCNode *pTarget)
{
CCActionInterval::startWithTarget(pTarget);
m_startPosition = pTarget->getPosition();//这里得到刚开始的位置
// m_delta = ccpSub(m_endPosition, m_startPosition); //从这里得到的m_delta然后在update里面
float x1 = m_startPosition.x;
float y1 = m_startPosition.y;
float x2 = m_endPosition.x;
float y2 = m_endPosition.y;
//设定初始值,这里的抛物线方程表达形式为 y = a * x^2 + b * x + c
a = - 0.16f;
b = 1.0f * ( y2 - y1 - a * ( x2 * x2 - x1 * x1))/(x2- x1);
c = y2 - a * x2 * x2 - b * x2;
}
ParabolaAction * ParabolaAction::createParabolaAction(float duration, const cocos2d::CCPoint &position)
{
ParabolaAction * result = newParabolaAction();
result->initWithDuration(duration, position);
result->autorelease();
return result;
}
//这个函数得到初始化数据
bool ParabolaAction::initWithDuration(float duration, const CCPoint& position){
if (CCActionInterval::initWithDuration(duration))
{
m_endPosition = position;
return true;
}
returnfalse;
}
void ParabolaAction::update(float time)
{
if (m_pTarget)
{
//这里的time就相当于当前时间占总的需要运行时间的百分比
float newX = m_startPosition.x + (m_endPosition.x - m_startPosition.x) * time;
float newY = a * newX * newX + b * newX + c ;
m_pTarget->setPosition(newX, newY);
}
}