Been looking around for a while and couldn’t really find a suitable action for moving a node around a center of rotation, so I rolled my own version.
Note that this action won’t change the target’s rotation. The intention is to only make it move in a circular path around a center of rotation.
Maybe this will help someone else in the future. (MIT license for ppl who care)
If you want to clone it from github here is the link: https://github.com/sts2055/STSRotateAround
Header:
/*
* STSRotateAround.h
*
* Copyright (c) 2014 Stefan Schmitt.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef __STSRotateAround__
#define __STSRotateAround__
#include "CCActionInterval.h"
struct PolarCoord {
float r; // radius
float a; // angle
};
/** Converts a polar coordinate to a cartesian coordinate */
inline cocos2d::Point convertPolarToCartesian(const PolarCoord& p)
{
const float rad = CC_DEGREES_TO_RADIANS(p.a);
const float x = p.r * cosf(rad);
const float y = p.r * sinf(rad);
return cocos2d::Point(x,y);
}
/** Converts a cartesian coordinate to a polar coordinate */
inline PolarCoord convertCartesianToPolar(const cocos2d::Point& p)
{
const float r = hypotf(p.x, p.y);
const float rad = atan2f(p.y, p.x);
const float a = CC_RADIANS_TO_DEGREES(rad);
return {r,a};
}
#pragma mark - RotateAround
/**
@brief Makes the target move around a center of rotation
*/
class RotateAround : public cocos2d::ActionInterval
{
public:
typedef cocos2d::ActionInterval super;
/**
* Create the action
* @param duration: the duration of the flickering
* @param centerOfRotation: the point around which to rotate
*/
static RotateAround* create(const float duration,
const cocos2d::Point centerOfRotation,
const bool reverse = false);
//
// Override
//
virtual void startWithTarget(cocos2d::Node* target) override;
virtual void update(float time) override;
virtual RotateAround* clone() const override;
virtual RotateAround* reverse() const override;
CC_CONSTRUCTOR_ACCESS:
RotateAround();
explicit RotateAround(const cocos2d::Point& centerOfRotation, const bool& reverse);
virtual ~RotateAround() {};
/** init the action */
bool initWithDuration(const float& duration);
protected:
const cocos2d::Point _centerOfRotation;
PolarCoord _startPolarCoord; // relative to center of rotation
const bool _reversed;
private:
CC_DISALLOW_COPY_AND_ASSIGN(RotateAround);
};
#endif /* defined(__STSRotateAround__) */
Implementation:
/*
* STSRotateAround.h
*
* Copyright (c) 2014 Stefan Schmitt.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "STSRotateAround.h"
USING_NS_CC;
RotateAround::RotateAround()
: _centerOfRotation(Point::ZERO)
, _startPolarCoord({0.f,0.f})
, _reversed(false)
{
}
RotateAround::RotateAround(const cocos2d::Point& centerOfRotation, const bool& reverse)
: _centerOfRotation(centerOfRotation)
, _startPolarCoord({0.f,0.f})
, _reversed(reverse)
{
}
RotateAround* RotateAround::create(const float duration,
const cocos2d::Point centerOfRotation,
const bool reverse /*=false*/)
{
RotateAround* pRet = new RotateAround(centerOfRotation, reverse);
if (pRet && pRet->initWithDuration(duration))
{
pRet->autorelease();
return pRet;
}
else
{
delete pRet;
pRet = NULL;
return NULL;
}
}
bool RotateAround::initWithDuration(const float& duration)
{
if (super::initWithDuration(duration)) {
return true;
}
return false;
}
void RotateAround::startWithTarget(cocos2d::Node* target)
{
super::startWithTarget(target);
if (_target) {
const Point pos = _target->getPosition();
const Vec2 vec = Vec2(pos.x - _centerOfRotation.x, pos.y - _centerOfRotation.y);
_startPolarCoord = convertCartesianToPolar(vec);
}
}
void RotateAround::update(float time)
{
CC_UNUSED_PARAM(time);
if(_target) {
const float elapsed = getElapsed();
const float percent = elapsed / _duration;
const float angle = _reversed ? 360.f * -percent : 360.f * percent;
const PolarCoord polarCoord {_startPolarCoord.r, _startPolarCoord.a + angle};
Point pos = convertPolarToCartesian(polarCoord);
pos = Point(_centerOfRotation.x + pos.x, _centerOfRotation.y + pos.y);
_target->setPosition(pos);
}
}
RotateAround* RotateAround::reverse() const
{
const bool reverse = true;
return RotateAround::create(_duration, _centerOfRotation, reverse);
}
RotateAround* RotateAround::clone() const
{
const bool reverse = true;
RotateAround* pRet = new RotateAround(_centerOfRotation, reverse);
if (pRet && pRet->initWithDuration(_duration))
{
pRet->autorelease();
return pRet;
}
else
{
delete pRet;
pRet = NULL;
return NULL;
}
}