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);
}