转自:http://blog.sina.com.cn/s/blog_7cbd10170102uxi1.html
最近使用cocos2dx需要用到一个需求,就是关于图片精灵抖动的动作效果。稍微查了一下,找到一个CCShake用来实现这样效果的。不过网上几乎都是在2.x平台上的。所以我根据需求把它改成能用在3.x平台上的。下面放一下代码先:
//
// CCShake.h
//
// Code by Francois Guibert
// Contact: www.frozax.com - http://twitter.com/frozax - www.facebook.com/frozax
//
// 何遵祖修改于2014.7.10 支持cocos2dx 3.0 修正了动作执行精灵位置错误问题 测试环境:cocos2d-x-3.0rc1
#ifndef __war__CCShake__
#define __war__CCShake__
#include
#include "cocos2d.h"
using namespace cocos2d;
class Shake : public ActionInterval
{
public:
Shake();
// Create the action with a time and a strength (same in x and y)
// 产生震动效果的初始化函数参数,两个方向相同
// @param d 震动持续的时间
// @param strength 震动的幅度
static Shake* create(float d, float strength);
// Create the action with a time and strengths (different in x and y)
// 产生震动效果的初始化函数,两个方向值不一样
static Shake* create(float d, float strength_x, float strength_y);
bool initWithDuration(float d, float strength_x, float strength_y);
//以下都是重写父类抽象类的函数(必须重写)
virtual Shake* clone() const override;
virtual Shake* reverse(void) const override;
virtual void startWithTarget(Node *target) override;
virtual void update(float time) override;
virtual void stop(void);
protected:
// Initial position of the shaked node
// 精灵的位置
float _initial_x, _initial_y;
// Strength of the action
// 抖动的幅度
float _strength_x, _strength_y;
};
//
// Shake.cpp
// war
//
#include "CCShake.h"
// not really useful, but I like clean default constructors
Shake::Shake() : _strength_x(0), _strength_y(0), _initial_x(0), _initial_y(0)
{
}
Shake* Shake::create(float d, float strength )
{
// call other construction method with twice the same strength
return create( d, strength, strength );
}
Shake* Shake::create(float duration, float strength_x, float strength_y)
{
Shake *p_action = new Shake();
p_action->initWithDuration(duration, strength_x, strength_y);
p_action->autorelease();
return p_action;
}
bool Shake::initWithDuration(float duration, float strength_x, float strength_y)
{
if (CCActionInterval::initWithDuration(duration))
{
_strength_x = strength_x;
_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
float fgRangeRand( float min, float max )
{
float rnd = ((float)rand()/(float)RAND_MAX);
return rnd*(max-min)+min;
}
void Shake::update(float time)
{
float randx = fgRangeRand( -_strength_x, _strength_x );
float randy = fgRangeRand( -_strength_y, _strength_y );
// move the target to a shaked position
_target->setPosition(Vec2(_initial_x + randx,
_initial_y + randy));
}
Shake* Shake::clone(void) const
{
auto a = new Shake();
a->initWithDuration(_duration, _strength_x, _strength_y);
a->autorelease();
return a;
}
Shake* Shake::reverse() const
{
return Shake::create(_duration, -_strength_x, -_strength_y);
}
void Shake::startWithTarget(Node *target)
{
CCActionInterval::startWithTarget(target);
// save the initial position
_initial_x = target->getPosition().x;
_initial_y = target->getPosition().y;
}
void Shake::stop(void)
{
// Action is done, reset clip position
_target->setPosition(Vec2( _initial_x, _initial_y ) );
CCActionInterval::stop();
}
Cocos2dx3.0中对ActionInterval类中的抽象类方法增加多了两个,一个是clone(),一个是reverse()。前者作用是起到一个复制的作用,后者是反向,让动作以当初设定的相反方向执行。
这个Shake主要的核心是在update和fgRangeRand方法中,主要思路是在fgRangeRand中在类的_strength(-_strength ~ _strength)值的范围里面产生随机数,然后根据精灵位置加上这里产生的值,从而不断的快速改变位置来参数抖动的效果。
在使用过程中,由于某处设置错误,导致shake动作被调用两次,完成动作后精灵偏离了原来的位置。所以,切记,不能被同时执行两个shake动作。