自定义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.xm_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);

    }

}

 

posted @ 2013-04-09 13:58  haroel  阅读(647)  评论(0编辑  收藏  举报