【COCOS2DX-游戏开发之三十】抖动效果 CCShake

http://www.jb51.cc/article/p-gfmfuutz-xy.html
cocos2dx全屏抖动,个别对象抖动

1)CCShake.h

/** desc:让指定控件抖动 一个CCNode同时执行多个CCShake动作,或者一个CCShake没有完又执行一个CCShake的话就会出现问题,会出现偏移的现象! 解决方案: 1).不要同时执行多个CCShake动作. 2.自己外部记录这个CCNode的位置,执行完成后手动setPosition(); */
#ifndef __SHAKE_H__
#define __SHAKE_H__

#include "cocos2d.h"

/** * 按指定频度范围内抖动[-strength_x,strength_x][-strength_y,strength_y] */ 
class CCShake : public cocos2d::CCActionInterval
{
    // Code by Francois Guibert
    // Contact: www.frozax.com - http://twitter.com/frozax - www.facebook.com/frozax
public:
    CCShake();

    // Create the action with a time and a strength (same in x and y)
    static CCShake* create(float d,float strength );
    // Create the action with a time and strengths (different in x and y)
    static CCShake* createWithStrength(float d,float strength_x,float strength_y );
    bool initWithDuration(float d,float strength_y );

protected:

    virtual void startWithTarget(cocos2d::CCNode *pTarget);
    virtual void update(float time);
    virtual void stop(void);


    // Initial position of the shaked node
    float m_initial_x,m_initial_y;
    // Strength of the action
    float m_strength_x,m_strength_y;
};

/** * 线性抖动(剩余时间越短,抖动范围越小) */  
class CCFallOffShake : public CCShake  
{  
public:  
    CCFallOffShake();  

    // Create the action with a time and a strength (same in x and y) 
    static CCFallOffShake* create(float d,float strength );  
    // Create the action with a time and strengths (different in x and y) 
    static CCFallOffShake* createWithStrength(float d,float strength_y );  

protected:  
    virtual void update(float time);  
};  

#endif //__SHAKE_H__

2)CCShake.cpp

// Code by Francois Guibert
// Contact: www.frozax.com - http://twitter.com/frozax - www.facebook.com/frozax


#include "CCShake.h"
#include "cocos2d.h"
USING_NS_CC;

// not really useful,but I like clean default constructors
CCShake::CCShake() : m_strength_x(0),m_strength_y(0),m_initial_x(0),m_initial_y(0)
{
}

CCShake* CCShake::create( float d,float strength )
{
    // call other construction method with twice the same strength
    return createWithStrength( d,strength,strength );
}

CCShake* CCShake::createWithStrength(float duration,float strength_x,float strength_y)
{
    CCShake *pRet = new CCShake();

    if (pRet && pRet->initWithDuration(duration,strength_x,strength_y))
    {
        pRet->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(pRet);
    }


    return pRet;
}

bool CCShake::initWithDuration(float duration,float strength_y)
{
    if (CCActionInterval::initWithDuration(duration))
    {
        m_strength_x = strength_x;
        m_strength_y = strength_y;
        return true;
    }

    return false;
}

// Helper function. I included it here so that you can compile the whole file
// it returns a random value between min and max included
static float fgRangeRand( float min,float max )
{
    float rnd = ((float)rand()/(float)RAND_MAX);
    return rnd*(max-min)+min;
}

void CCShake::update(float dt)
{
    float randx = fgRangeRand( -m_strength_x,m_strength_x )*dt;
    float randy = fgRangeRand( -m_strength_y,m_strength_y )*dt;

    // move the target to a shaked position
    m_pTarget->setPosition( ccpAdd(ccp(m_initial_x,m_initial_y),ccp( randx,randy)));
}

void CCShake::startWithTarget(CCNode *pTarget)
{
    CCActionInterval::startWithTarget( pTarget );

    // save the initial position
    m_initial_x = pTarget->getPosition().x;
    m_initial_y = pTarget->getPosition().y;
}

void CCShake::stop(void)
{
    // Action is done,reset clip position
    this->getTarget()->setPosition( ccp( m_initial_x,m_initial_y ) );

    CCActionInterval::stop();
}

CCFallOffShake::CCFallOffShake()  
{  

}  

// Create the action with a time and a strength (same in x and y) 
CCFallOffShake* CCFallOffShake::create(float d,float strength )  
{  
    return createWithStrength( d,strength );  
}  

// Create the action with a time and strengths (different in x and y) 
CCFallOffShake* CCFallOffShake::createWithStrength(float duration,float strength_y)  
{  
    CCFallOffShake *pRet = new CCFallOffShake();  

    if (pRet && pRet->initWithDuration(duration,strength_y))  
    {  
        pRet->autorelease();  
    }  
    else  
    {  
        CC_SAFE_DELETE(pRet);  
    }  

    return pRet;  
}  

void CCFallOffShake::update(float dt)  
{  
    float rate = (getDuration() - getElapsed())/getDuration();  
    if (rate < 0.f) {  
        rate = 0.f;  
    }  

    float randx = fgRangeRand( -m_strength_x,m_strength_x )*rate;  
    float randy = fgRangeRand( -m_strength_y,m_strength_y )*rate;  

    // move the target to a shaked position 
    m_pTarget->setPosition( ccpAdd(ccp(m_initial_x,randy)));  
}

3)HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "CCShake.h"

class HelloWorld : public cocos2d::CCLayer
{
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp,so we recommend returning the class instance pointer
    static cocos2d::CCScene* scene();

    // a selector callback
    void menuCloseCallback(CCObject* pSender);

    void ShakeScreenCallback(CCObject* pSender);

    void ShakeScreenFinishedCallback(CCObject* pSender);
    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

4)HelloWorld.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();

    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }

    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image,which is clicked to quit the program
    // you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png","CloseSelected.png",this,menu_selector(HelloWorld::menuCloseCallback));

    pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2,origin.y + pCloseItem->getContentSize().height/2));

    // create menu,it's an autorelease object
    CCMenu* pMenu = CCMenu::create(pCloseItem,NULL);
    pMenu->setPosition(CCPointZero);
    this->addChild(pMenu,1);

    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label

    CCLabelTTF* pLabel = CCLabelTTF::create("Shake it up,Baby!","Arial",24);

    // position the label on the center of the screen
    pLabel->setPosition(ccp(origin.x + visibleSize.width/2,origin.y + visibleSize.height - pLabel->getContentSize().height));

    // add the label as a child to this layer
    this->addChild(pLabel,1);

    CCMenuItemImage *pShakeButton = CCMenuItemImage::create(
                                        "CloseNormal.png",menu_selector(HelloWorld::ShakeScreenCallback));

    pShakeButton->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));

    // create menu,it's an autorelease object
    CCMenu* pShakeMenu = CCMenu::create(pShakeButton,NULL);
    pShakeMenu->setPosition(CCPointZero);
    this->addChild(pShakeMenu,1);

    return true;
}


void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
    CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
    CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
#endif
}

void HelloWorld::ShakeScreenCallback(CCObject* pSender)
{
    //CCShake *p_shake = CCShake::createWithStrength(0.6,13,13);
    //CCShake *p_shake = CCShake::createWithStrength(1.0,5,5); 
    CCFallOffShake *p_shake = CCFallOffShake::create(3.6,13);
    //CCCallFunc* callback=CCCallFunc::create(this,callfunc_selector(StageScene::zhengpingCallBack));
    //CCAction * act=CCSequence::create(p_shake,callback,NULL);
    CCAction* act = CCSequence::create(p_shake,NULL);
    this->runAction(act);
}

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...