2012-06-08 13:55:28 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2010-2012 cocos2d-x.org
|
|
|
|
* cocos2d for iPhone: http://www.cocos2d-iphone.org
|
|
|
|
*
|
|
|
|
* Copyright (c) 2008 Radu Gruian
|
|
|
|
*
|
|
|
|
* Copyright (c) 2011 Vit Valentin
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*
|
2012-09-16 06:12:28 +08:00
|
|
|
* Original code by Radu Gruian: http://www.codeproject.com/Articles/30838/Overhauser-Catmull-Rom-Splines-for-Camera-Animatio.So
|
2012-06-08 13:55:28 +08:00
|
|
|
*
|
|
|
|
* Adapted to cocos2d-x by Vit Valentin
|
|
|
|
*
|
|
|
|
* Adapted from cocos2d-x to cocos2d-iphone by Ricardo Quesada
|
|
|
|
*/
|
|
|
|
#include "ccMacros.h"
|
|
|
|
#include "support/CCPointExtension.h"
|
|
|
|
#include "CCActionCatmullRom.h"
|
2012-06-19 16:20:46 +08:00
|
|
|
#include "cocoa/CCZone.h"
|
2012-06-08 13:55:28 +08:00
|
|
|
|
2012-06-11 18:25:57 +08:00
|
|
|
using namespace std;
|
|
|
|
|
2012-06-08 13:55:28 +08:00
|
|
|
NS_CC_BEGIN;
|
|
|
|
|
|
|
|
/*
|
2013-06-20 14:13:12 +08:00
|
|
|
* Implementation of PointArray
|
2012-06-08 13:55:28 +08:00
|
|
|
*/
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray* PointArray::create(unsigned int capacity)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray* ret = new PointArray();
|
2012-06-08 13:55:28 +08:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
if (ret->initWithCapacity(capacity))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete ret;
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
}
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2012-06-08 13:55:28 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
bool PointArray::initWithCapacity(unsigned int capacity)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
_controlPoints = new vector<Point*>();
|
2012-06-08 13:55:28 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
Object* PointArray::copyWithZone(cocos2d::Zone *zone)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
vector<Point*> *newArray = new vector<Point*>();
|
|
|
|
vector<Point*>::iterator iter;
|
2013-06-15 14:03:30 +08:00
|
|
|
for (iter = _controlPoints->begin(); iter != _controlPoints->end(); ++iter)
|
2013-01-14 14:45:16 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
newArray->push_back(new Point((*iter)->x, (*iter)->y));
|
2013-01-14 14:45:16 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray *points = new PointArray();
|
2013-01-23 14:38:46 +08:00
|
|
|
points->initWithCapacity(10);
|
2012-06-08 13:55:28 +08:00
|
|
|
points->setControlPoints(newArray);
|
|
|
|
|
|
|
|
return points;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray::~PointArray()
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
vector<Point*>::iterator iter;
|
2013-06-15 14:03:30 +08:00
|
|
|
for (iter = _controlPoints->begin(); iter != _controlPoints->end(); ++iter)
|
2013-01-14 14:45:16 +08:00
|
|
|
{
|
|
|
|
delete *iter;
|
|
|
|
}
|
2013-06-15 14:03:30 +08:00
|
|
|
delete _controlPoints;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray::PointArray() :_controlPoints(NULL){}
|
2012-06-08 13:55:28 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
const std::vector<Point*>* PointArray::getControlPoints()
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
return _controlPoints;
|
2013-01-14 14:45:16 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void PointArray::setControlPoints(vector<Point*> *controlPoints)
|
2013-01-14 14:45:16 +08:00
|
|
|
{
|
2013-01-23 14:38:46 +08:00
|
|
|
CCAssert(controlPoints != NULL, "control points should not be NULL");
|
2013-01-14 14:45:16 +08:00
|
|
|
|
2013-01-23 14:38:46 +08:00
|
|
|
// delete old points
|
2013-06-20 14:13:12 +08:00
|
|
|
vector<Point*>::iterator iter;
|
2013-06-15 14:03:30 +08:00
|
|
|
for (iter = _controlPoints->begin(); iter != _controlPoints->end(); ++iter)
|
2013-01-14 14:45:16 +08:00
|
|
|
{
|
|
|
|
delete *iter;
|
|
|
|
}
|
2013-06-15 14:03:30 +08:00
|
|
|
delete _controlPoints;
|
2013-01-14 14:45:16 +08:00
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
_controlPoints = controlPoints;
|
2013-01-14 14:45:16 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void PointArray::addControlPoint(Point controlPoint)
|
2013-01-14 14:45:16 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
_controlPoints->push_back(new Point(controlPoint.x, controlPoint.y));
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void PointArray::insertControlPoint(Point &controlPoint, unsigned int index)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
Point *temp = new Point(controlPoint.x, controlPoint.y);
|
2013-06-15 14:03:30 +08:00
|
|
|
_controlPoints->insert(_controlPoints->begin() + index, temp);
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
Point PointArray::getControlPointAtIndex(unsigned int index)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
index = MIN(_controlPoints->size()-1, MAX(index, 0));
|
|
|
|
return *(_controlPoints->at(index));
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void PointArray::replaceControlPoint(cocos2d::Point &controlPoint, unsigned int index)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-01-14 14:45:16 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
Point *temp = _controlPoints->at(index);
|
2013-01-14 14:45:16 +08:00
|
|
|
temp->x = controlPoint.x;
|
|
|
|
temp->y = controlPoint.y;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void PointArray::removeControlPointAtIndex(unsigned int index)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
vector<Point*>::iterator iter = _controlPoints->begin() + index;
|
|
|
|
Point* pRemovedPoint = *iter;
|
2013-06-15 14:03:30 +08:00
|
|
|
_controlPoints->erase(iter);
|
2013-01-23 14:38:46 +08:00
|
|
|
delete pRemovedPoint;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
unsigned int PointArray::count()
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
return _controlPoints->size();
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray* PointArray::reverse()
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
vector<Point*> *newArray = new vector<Point*>();
|
|
|
|
vector<Point*>::reverse_iterator iter;
|
|
|
|
Point *point = NULL;
|
2013-06-15 14:03:30 +08:00
|
|
|
for (iter = _controlPoints->rbegin(); iter != _controlPoints->rend(); ++iter)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-01-14 14:45:16 +08:00
|
|
|
point = *iter;
|
2013-06-20 14:13:12 +08:00
|
|
|
newArray->push_back(new Point(point->x, point->y));
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray *config = PointArray::create(0);
|
2012-06-08 13:55:28 +08:00
|
|
|
config->setControlPoints(newArray);
|
|
|
|
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void PointArray::reverseInline()
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
unsigned int l = _controlPoints->size();
|
2013-06-20 14:13:12 +08:00
|
|
|
Point *p1 = NULL;
|
|
|
|
Point *p2 = NULL;
|
2013-01-14 14:45:16 +08:00
|
|
|
int x, y;
|
2012-06-08 13:55:28 +08:00
|
|
|
for (unsigned int i = 0; i < l/2; ++i)
|
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
p1 = _controlPoints->at(i);
|
|
|
|
p2 = _controlPoints->at(l-i-1);
|
2013-01-14 14:45:16 +08:00
|
|
|
|
|
|
|
x = p1->x;
|
|
|
|
y = p1->y;
|
|
|
|
|
|
|
|
p1->x = p2->x;
|
|
|
|
p1->y = p2->y;
|
|
|
|
|
|
|
|
p2->x = x;
|
|
|
|
p2->y = y;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CatmullRom Spline formula:
|
2013-06-20 14:13:12 +08:00
|
|
|
Point ccCardinalSplineAt(Point &p0, Point &p1, Point &p2, Point &p3, float tension, float t)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
|
|
|
float t2 = t * t;
|
|
|
|
float t3 = t2 * t;
|
|
|
|
|
|
|
|
/*
|
2012-06-20 11:48:31 +08:00
|
|
|
* Formula: s(-ttt + 2tt - t)P1 + s(-ttt + tt)P2 + (2ttt - 3tt + 1)P2 + s(ttt - 2tt + t)P3 + (-2ttt + 3tt)P3 + s(ttt - tt)P4
|
2012-06-08 13:55:28 +08:00
|
|
|
*/
|
|
|
|
float s = (1 - tension) / 2;
|
|
|
|
|
2012-06-20 11:48:31 +08:00
|
|
|
float b1 = s * ((-t3 + (2 * t2)) - t); // s(-t3 + 2 t2 - t)P1
|
|
|
|
float b2 = s * (-t3 + t2) + (2 * t3 - 3 * t2 + 1); // s(-t3 + t2)P2 + (2 t3 - 3 t2 + 1)P2
|
|
|
|
float b3 = s * (t3 - 2 * t2 + t) + (-2 * t3 + 3 * t2); // s(t3 - 2 t2 + t)P3 + (-2 t3 + 3 t2)P3
|
|
|
|
float b4 = s * (t3 - t2); // s(t3 - t2)P4
|
2012-06-08 13:55:28 +08:00
|
|
|
|
|
|
|
float x = (p0.x*b1 + p1.x*b2 + p2.x*b3 + p3.x*b4);
|
|
|
|
float y = (p0.y*b1 + p1.y*b2 + p2.y*b3 + p3.y*b4);
|
|
|
|
|
|
|
|
return ccp(x,y);
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
/* Implementation of CardinalSplineTo
|
2012-06-08 13:55:28 +08:00
|
|
|
*/
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineTo* CardinalSplineTo::create(float duration, cocos2d::PointArray *points, float tension)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineTo *ret = new CardinalSplineTo();
|
2012-06-08 13:55:28 +08:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
if (ret->initWithDuration(duration, points, tension))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CC_SAFE_RELEASE_NULL(ret);
|
|
|
|
}
|
|
|
|
}
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2012-06-08 13:55:28 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
bool CardinalSplineTo::initWithDuration(float duration, cocos2d::PointArray *points, float tension)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
|
|
|
CCAssert(points->count() > 0, "Invalid configuration. It must at least have one control point");
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
if (ActionInterval::initWithDuration(duration))
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
|
|
|
this->setPoints(points);
|
2013-06-15 14:03:30 +08:00
|
|
|
this->_tension = tension;
|
2012-06-08 13:55:28 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineTo::~CardinalSplineTo()
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_points);
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineTo::CardinalSplineTo()
|
2013-06-15 14:03:30 +08:00
|
|
|
: _points(NULL)
|
|
|
|
, _deltaT(0.f)
|
|
|
|
, _tension(0.f)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void CardinalSplineTo::startWithTarget(cocos2d::Node *pTarget)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
ActionInterval::startWithTarget(pTarget);
|
2012-06-08 13:55:28 +08:00
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
// _deltaT = (float) 1 / _points->count();
|
2012-11-14 18:05:15 +08:00
|
|
|
|
|
|
|
// Issue #1441
|
2013-06-15 14:03:30 +08:00
|
|
|
_deltaT = (float) 1 / (_points->count() - 1);
|
2012-12-26 18:59:31 +08:00
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
_previousPosition = pTarget->getPosition();
|
2013-06-20 14:13:12 +08:00
|
|
|
_accumulatedDiff = PointZero;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineTo* CardinalSplineTo::clone() const
|
2013-06-14 08:25:14 +08:00
|
|
|
{
|
2013-06-19 06:06:53 +08:00
|
|
|
// no copy constructor
|
2013-06-20 14:13:12 +08:00
|
|
|
auto a = new CardinalSplineTo();
|
2013-06-15 14:03:30 +08:00
|
|
|
a->initWithDuration(this->_duration, this->_points, this->_tension);
|
2013-06-14 08:25:14 +08:00
|
|
|
a->autorelease();
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineTo* CardinalSplineTo::copyWithZone(cocos2d::Zone *pZone)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
Zone* pNewZone = NULL;
|
|
|
|
CardinalSplineTo* pRet = NULL;
|
2013-06-15 14:03:30 +08:00
|
|
|
if(pZone && pZone->_copyObject) //in case of being called at sub class
|
2012-06-14 15:13:16 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
pRet = (CardinalSplineTo*)(pZone->_copyObject);
|
2012-06-14 15:13:16 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
pRet = new CardinalSplineTo();
|
|
|
|
pZone = pNewZone = new Zone(pRet);
|
2012-06-14 15:13:16 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
ActionInterval::copyWithZone(pZone);
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
pRet->initWithDuration(this->getDuration(), this->_points, this->_tension);
|
2012-06-14 15:13:16 +08:00
|
|
|
|
|
|
|
CC_SAFE_DELETE(pNewZone);
|
|
|
|
return pRet;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void CardinalSplineTo::update(float time)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
|
|
|
unsigned int p;
|
|
|
|
float lt;
|
|
|
|
|
2012-11-14 18:05:15 +08:00
|
|
|
// eg.
|
|
|
|
// p..p..p..p..p..p..p
|
|
|
|
// 1..2..3..4..5..6..7
|
|
|
|
// want p to be 1, 2, 3, 4, 5, 6
|
2012-06-08 13:55:28 +08:00
|
|
|
if (time == 1)
|
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
p = _points->count() - 1;
|
2012-06-08 13:55:28 +08:00
|
|
|
lt = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
p = time / _deltaT;
|
|
|
|
lt = (time - _deltaT * (float)p) / _deltaT;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Interpolate
|
2013-06-20 14:13:12 +08:00
|
|
|
Point pp0 = _points->getControlPointAtIndex(p-1);
|
|
|
|
Point pp1 = _points->getControlPointAtIndex(p+0);
|
|
|
|
Point pp2 = _points->getControlPointAtIndex(p+1);
|
|
|
|
Point pp3 = _points->getControlPointAtIndex(p+2);
|
2012-06-08 13:55:28 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
Point newPos = ccCardinalSplineAt(pp0, pp1, pp2, pp3, _tension, lt);
|
2012-06-08 13:55:28 +08:00
|
|
|
|
2013-02-27 09:38:30 +08:00
|
|
|
#if CC_ENABLE_STACKABLE_ACTIONS
|
2013-01-14 14:45:16 +08:00
|
|
|
// Support for stacked actions
|
2013-06-20 14:13:12 +08:00
|
|
|
Node *node = _target;
|
|
|
|
Point diff = ccpSub( node->getPosition(), _previousPosition);
|
2013-01-14 14:45:16 +08:00
|
|
|
if( diff.x !=0 || diff.y != 0 ) {
|
2013-06-15 14:03:30 +08:00
|
|
|
_accumulatedDiff = ccpAdd( _accumulatedDiff, diff);
|
|
|
|
newPos = ccpAdd( newPos, _accumulatedDiff);
|
2012-12-26 18:59:31 +08:00
|
|
|
}
|
2013-02-27 09:38:30 +08:00
|
|
|
#endif
|
|
|
|
|
2012-06-08 13:55:28 +08:00
|
|
|
this->updatePosition(newPos);
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void CardinalSplineTo::updatePosition(cocos2d::Point &newPos)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
_target->setPosition(newPos);
|
|
|
|
_previousPosition = newPos;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineTo* CardinalSplineTo::reverse() const
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray *pReverse = _points->reverse();
|
2012-06-08 13:55:28 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
return CardinalSplineTo::create(_duration, pReverse, _tension);
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
/* CardinalSplineBy
|
2012-06-08 13:55:28 +08:00
|
|
|
*/
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineBy* CardinalSplineBy::create(float duration, cocos2d::PointArray *points, float tension)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineBy *ret = new CardinalSplineBy();
|
2012-06-08 13:55:28 +08:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
if (ret->initWithDuration(duration, points, tension))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CC_SAFE_RELEASE_NULL(ret);
|
|
|
|
}
|
|
|
|
}
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2012-06-08 13:55:28 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineBy::CardinalSplineBy() : _startPosition(0,0)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void CardinalSplineBy::updatePosition(cocos2d::Point &newPos)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
Point p = ccpAdd(newPos, _startPosition);
|
2013-06-15 14:03:30 +08:00
|
|
|
_target->setPosition(p);
|
|
|
|
_previousPosition = p;
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineBy* CardinalSplineBy::reverse() const
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray *copyConfig = (PointArray*)_points->copy();
|
2012-06-08 13:55:28 +08:00
|
|
|
|
|
|
|
//
|
|
|
|
// convert "absolutes" to "diffs"
|
|
|
|
//
|
2013-06-20 14:13:12 +08:00
|
|
|
Point p = copyConfig->getControlPointAtIndex(0);
|
2012-06-08 13:55:28 +08:00
|
|
|
for (unsigned int i = 1; i < copyConfig->count(); ++i)
|
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
Point current = copyConfig->getControlPointAtIndex(i);
|
|
|
|
Point diff = ccpSub(current, p);
|
2012-06-08 13:55:28 +08:00
|
|
|
copyConfig->replaceControlPoint(diff, i);
|
|
|
|
|
|
|
|
p = current;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// convert to "diffs" to "reverse absolute"
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray *pReverse = copyConfig->reverse();
|
2012-06-08 13:55:28 +08:00
|
|
|
copyConfig->release();
|
|
|
|
|
|
|
|
// 1st element (which should be 0,0) should be here too
|
|
|
|
|
2012-06-14 15:13:16 +08:00
|
|
|
p = pReverse->getControlPointAtIndex(pReverse->count()-1);
|
|
|
|
pReverse->removeControlPointAtIndex(pReverse->count()-1);
|
2012-06-08 13:55:28 +08:00
|
|
|
|
|
|
|
p = ccpNeg(p);
|
2012-06-14 15:13:16 +08:00
|
|
|
pReverse->insertControlPoint(p, 0);
|
2012-06-08 13:55:28 +08:00
|
|
|
|
2012-06-14 15:13:16 +08:00
|
|
|
for (unsigned int i = 1; i < pReverse->count(); ++i)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
Point current = pReverse->getControlPointAtIndex(i);
|
2012-06-08 13:55:28 +08:00
|
|
|
current = ccpNeg(current);
|
2013-06-20 14:13:12 +08:00
|
|
|
Point abs = ccpAdd(current, p);
|
2012-06-14 15:13:16 +08:00
|
|
|
pReverse->replaceControlPoint(abs, i);
|
2012-06-08 13:55:28 +08:00
|
|
|
|
|
|
|
p = abs;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
return CardinalSplineBy::create(_duration, pReverse, _tension);
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void CardinalSplineBy::startWithTarget(cocos2d::Node *pTarget)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineTo::startWithTarget(pTarget);
|
2013-06-15 14:03:30 +08:00
|
|
|
_startPosition = pTarget->getPosition();
|
2012-06-08 13:55:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CardinalSplineBy* CardinalSplineBy::clone() const
|
2013-06-14 08:25:14 +08:00
|
|
|
{
|
2013-06-19 06:06:53 +08:00
|
|
|
// no copy constructor
|
2013-06-20 14:13:12 +08:00
|
|
|
auto a = new CardinalSplineBy();
|
|
|
|
a->initWithDuration(this->_duration, (PointArray*)this->_points->copy()->autorelease(), this->_tension);
|
2013-06-14 08:25:14 +08:00
|
|
|
a->autorelease();
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
/* CatmullRomTo
|
2012-06-08 13:55:28 +08:00
|
|
|
*/
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CatmullRomTo* CatmullRomTo::create(float dt, cocos2d::PointArray *points)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
CatmullRomTo *ret = new CatmullRomTo();
|
2012-06-08 13:55:28 +08:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
if (ret->initWithDuration(dt, points))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CC_SAFE_RELEASE_NULL(ret);
|
|
|
|
}
|
|
|
|
}
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2012-06-08 13:55:28 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
bool CatmullRomTo::initWithDuration(float dt, cocos2d::PointArray *points)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
if (CardinalSplineTo::initWithDuration(dt, points, 0.5f))
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CatmullRomTo* CatmullRomTo::clone() const
|
2013-06-14 08:25:14 +08:00
|
|
|
{
|
2013-06-19 06:06:53 +08:00
|
|
|
// no copy constructor
|
2013-06-20 14:13:12 +08:00
|
|
|
auto a = new CatmullRomTo();
|
|
|
|
a->initWithDuration(this->_duration, (PointArray*)this->_points->copy()->autorelease());
|
2013-06-14 08:25:14 +08:00
|
|
|
a->autorelease();
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CatmullRomTo* CatmullRomTo::reverse() const
|
2013-06-19 06:06:53 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray *pReverse = _points->reverse();
|
|
|
|
return CatmullRomTo::create(_duration, pReverse);
|
2013-06-19 06:06:53 +08:00
|
|
|
}
|
|
|
|
|
2013-06-14 08:25:14 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
/* CatmullRomBy
|
2012-06-08 13:55:28 +08:00
|
|
|
*/
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CatmullRomBy* CatmullRomBy::create(float dt, cocos2d::PointArray *points)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
CatmullRomBy *ret = new CatmullRomBy();
|
2012-06-08 13:55:28 +08:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
if (ret->initWithDuration(dt, points))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CC_SAFE_RELEASE_NULL(ret);
|
|
|
|
}
|
|
|
|
}
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2012-06-08 13:55:28 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
bool CatmullRomBy::initWithDuration(float dt, cocos2d::PointArray *points)
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
if (CardinalSplineTo::initWithDuration(dt, points, 0.5f))
|
2012-06-08 13:55:28 +08:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CatmullRomBy* CatmullRomBy::clone() const
|
2013-06-14 08:25:14 +08:00
|
|
|
{
|
2013-06-19 06:06:53 +08:00
|
|
|
// no copy constructor
|
2013-06-20 14:13:12 +08:00
|
|
|
auto a = new CatmullRomBy();
|
|
|
|
a->initWithDuration(this->_duration, (PointArray*)this->_points->copy()->autorelease());
|
2013-06-14 08:25:14 +08:00
|
|
|
a->autorelease();
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CatmullRomBy* CatmullRomBy::reverse() const
|
2013-06-19 06:06:53 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray *copyConfig = (PointArray*)_points->copy();
|
2013-06-19 06:06:53 +08:00
|
|
|
|
|
|
|
//
|
|
|
|
// convert "absolutes" to "diffs"
|
|
|
|
//
|
2013-06-20 14:13:12 +08:00
|
|
|
Point p = copyConfig->getControlPointAtIndex(0);
|
2013-06-19 06:06:53 +08:00
|
|
|
for (unsigned int i = 1; i < copyConfig->count(); ++i)
|
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
Point current = copyConfig->getControlPointAtIndex(i);
|
|
|
|
Point diff = ccpSub(current, p);
|
2013-06-19 06:06:53 +08:00
|
|
|
copyConfig->replaceControlPoint(diff, i);
|
|
|
|
|
|
|
|
p = current;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// convert to "diffs" to "reverse absolute"
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
PointArray *pReverse = copyConfig->reverse();
|
2013-06-19 06:06:53 +08:00
|
|
|
copyConfig->release();
|
|
|
|
|
|
|
|
// 1st element (which should be 0,0) should be here too
|
|
|
|
|
|
|
|
p = pReverse->getControlPointAtIndex(pReverse->count()-1);
|
|
|
|
pReverse->removeControlPointAtIndex(pReverse->count()-1);
|
|
|
|
|
|
|
|
p = ccpNeg(p);
|
|
|
|
pReverse->insertControlPoint(p, 0);
|
|
|
|
|
|
|
|
for (unsigned int i = 1; i < pReverse->count(); ++i)
|
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
Point current = pReverse->getControlPointAtIndex(i);
|
2013-06-19 06:06:53 +08:00
|
|
|
current = ccpNeg(current);
|
2013-06-20 14:13:12 +08:00
|
|
|
Point abs = ccpAdd(current, p);
|
2013-06-19 06:06:53 +08:00
|
|
|
pReverse->replaceControlPoint(abs, i);
|
|
|
|
|
|
|
|
p = abs;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
return CatmullRomBy::create(_duration, pReverse);
|
2013-06-19 06:06:53 +08:00
|
|
|
}
|
|
|
|
|
2012-06-08 13:55:28 +08:00
|
|
|
NS_CC_END;
|
|
|
|
|