libcocos2dのソースの中に組み込んでやれば他のActionと同様に呼び出せるようになる。
ソースの中にdefineしてしまっているが自然長や初速度、摩擦係数などを変更すれば動きをもっと激しくすることも可能。
SpringMoveBy.h
#ifndef SPRINGMOVE_H_
#define SPRINGMOVE_H_
#include "cocos2d.h"
class CC_DLL SpringMoveBy : public cocos2d::ActionInterval
{
public:
static SpringMoveBy* create(float duration, const cocos2d::Vec2& position, float mass, float k);
//
// Overrides
//
virtual SpringMoveBy* clone() const override;
virtual SpringMoveBy* reverse(void) const override;
virtual void startWithTarget(cocos2d::Node *target) override;
/**
* @param time In seconds.
*/
virtual void update(float time) override;
CC_CONSTRUCTOR_ACCESS:
SpringMoveBy() {}
virtual ~SpringMoveBy() {}
/**
* initializes the action
* @param duration in seconds
*/
bool initWithDuration(float duration, const cocos2d::Vec2& position, float mass, float k);
protected:
cocos2d::Vec2 _startPosition;
cocos2d::Vec2 _delta;
float _k;
float _mass;
cocos2d::Vec2 _previousPos;
float _velocity;
float _accel;
float _position;
private:
CC_DISALLOW_COPY_AND_ASSIGN(SpringMoveBy);
};
#endif /* SPRINGMOVE_H_ */
SpringMoveBy.cpp
#include "SpringMove.h"
USING_NS_CC;
//
// SpringMoveBy
//
#define GRAVITY 9.80665 // 重力加速度
#define NATURAL_LENGTH 0 // 自然長
#define FIRST_ACCEL GRAVITY // 初期加速度
#define FIRST_VEROCITY 60 // 初期速度
#define FIRST_POSITION 0 // 初期位置
#define FRICTION 0.996 // 摩擦係数
USING_NS_CC;
SpringMoveBy* SpringMoveBy::create(float duration, const Vec2& position, float mass, float k)
{
SpringMoveBy *springMoveBy = new (std::nothrow) SpringMoveBy();
springMoveBy->initWithDuration(duration, position, mass, k);
springMoveBy->autorelease();
return springMoveBy;
}
bool SpringMoveBy::initWithDuration(float duration, const Vec2& position, float mass, float k)
{
CCASSERT(mass >=0, "Number of mass must be >= 0");
if (ActionInterval::initWithDuration(duration) && mass>=0)
{
_delta = position;
_mass = mass;
_k = k;
_velocity = FIRST_VEROCITY;
_accel = FIRST_ACCEL;
_position = FIRST_POSITION;
return true;
}
return false;
}
SpringMoveBy* SpringMoveBy::clone() const
{
// no copy constructor
auto a = new (std::nothrow) SpringMoveBy();
a->initWithDuration(_duration, _delta, _mass, _k);
a->autorelease();
return a;
}
void SpringMoveBy::startWithTarget(Node *target)
{
ActionInterval::startWithTarget(target);
_previousPos = _startPosition = target->getPosition();
}
void SpringMoveBy::update(float t) // _delta = 現在座標
{
if (_target)
{
auto force = -_k * ( _position - NATURAL_LENGTH ) + _mass * GRAVITY;
_accel = force / _mass;
_velocity += _accel * t;
_velocity = _velocity * FRICTION;
_position += _velocity * t;
#ifdef CC_ENABLE_STACKABLE_ACTIONS
Vec2 currentPos = _target->getPosition();
Vec2 diff = currentPos - _previousPos;
_startPosition = diff + _startPosition;
Vec2 newPos = _startPosition;
newPos = _startPosition + Vec2(0,_position);
_target->setPosition(newPos);
_previousPos = newPos;
#else
_target->setPosition(_startPosition + Vec2(0, _position));
#endif // !CC_ENABLE_STACKABLE_ACTIONS
}
}
SpringMoveBy* SpringMoveBy::reverse() const
{
return SpringMoveBy::create(_duration, Vec2(-_delta.x, -_delta.y),
_mass, _k);
}
![]() |
| 動作例 |


