[英]Make a loop with cardinal spline
I'm trying to make an animation for a sprite, which will go on path and it will loop forever. 我正在尝试为sprite制作动画,该动画将继续前进并永远循环。 But CardinalSpline doesn't close up as I thought.
但是CardinalSpline并没有像我想的那样关闭。
Here are example points (it's a square): 这是示例点(它是一个正方形):
pointsRed->addControlPoint(Vec2(350, 350));
pointsRed->addControlPoint(Vec2(350, 150));
pointsRed->addControlPoint(Vec2(150, 150));
pointsRed->addControlPoint(Vec2(150, 350));
pointsRed->addControlPoint(Vec2(350, 350));
Animation creation: 动画制作:
auto redSpline = CardinalSplineTo::create(20, pointsRed, 0);
It looks like that: 看起来像这样:
So of course animation doesn't look too good. 因此,动画当然看起来不太好。 I want to make a perfect loop (with constant speed), where cannot be seen where's an end or start.
我想做一个完美的循环(以恒定的速度),在哪里看不到终点或起点。
If I will continue adding the same points it will loop nice until it reaches the end where's an breakdown, which you can see on top right corner. 如果我继续添加相同的点,它将很好地循环播放,直到到达故障点为止,您可以在右上角看到该点。
How can I achieve this? 我该如何实现?
Only thing, which comes to my mind is too double amount of points and at exactly half of animation seek it to the begging or create a new one. 我想到的唯一一件事是要点的数量过多,动画的一半恰好找它乞讨或创建一个新的对象。
Finally I did it. 最后我做到了。 I had to change cocos2d-x code a bit.
我不得不稍微更改cocos2d-x代码。
All needed changes: 所有需要的更改:
in startWithTarget: 在startWithTarget中:
_deltaT = (float) 1 / (_points->count() - 1);
to: 至:
_deltaT = (float) 1 / (_points->count());
Reimplemented getControlPointAtIndex: 重新实现了getControlPointAtIndex:
from: 从:
Vec2 PointArray::getControlPointAtIndex(ssize_t index)
{
index = MIN(static_cast<ssize_t>(_controlPoints->size())-1, MAX(index, 0));
return *(_controlPoints->at(index));
}
to: 至:
Vec2 PointArray::getControlPointAtIndex(ssize_t index)
{
ssize_t tIndex = index;
ssize_t pSize = static_cast<ssize_t>(_controlPoints->size());
if(tIndex < 0) tIndex += pSize;
if(tIndex >= pSize) tIndex -= pSize;
return *(_controlPoints->at(tIndex));
}
Then spline is interpolating well, because it always has 4 different points to interpolate. 然后,样条曲线可以很好地进行插值,因为它总是有4个不同的点可以插值。 Before that first and last point were cut off.
在此之前,第一个和最后一个点被切断。
To draw a spline in CAD programs such as AutoCAD, you must specify not only points, but also the direction (imaginary extension) for the extreme points. 要在CAD程序(例如AutoCAD)中绘制样条曲线,不仅必须指定点,还必须指定极限点的方向(虚构延伸)。 Direction affects the behavior of the spline from the extreme point to the next.
方向会影响样条曲线从端点到下一端点的行为。
Here the direction is not specified, so the extreme point of the spline has a "sharp transition". 此处未指定方向,因此样条曲线的极点具有“尖锐过渡”。
Try to add two points to indicate the direction, for example: 尝试添加两个点以指示方向,例如:
pointsRed->addControlPoint(Vec2(300, 360));
pointsRed->addControlPoint(Vec2(350, 350));
pointsRed->addControlPoint(Vec2(350, 150));
pointsRed->addControlPoint(Vec2(150, 150));
pointsRed->addControlPoint(Vec2(150, 350));
pointsRed->addControlPoint(Vec2(350, 350));
pointsRed->addControlPoint(Vec2(360, 300));
I pointed out the approximate position of the extreme points. 我指出了极端点的大概位置。 You should to move them and determine the exact position to achieve precise overlay of a spline.
您应该移动它们并确定精确位置以实现样条线的精确覆盖。
PS Or you can try to connect the spline is not at the corner and on a flat plot of the spline, for example at the point (250, 360). PS或者您可以尝试连接样条线不在角部和样条线的平面图上,例如在点(250,360)处。
My previous answer concerned only spline creation. 我以前的答案只涉及样条线的创建。 But now I made my particle rotation by spiral, and know the simplest way which can help you.
但是现在我使粒子旋转成螺旋状,并且知道可以帮助您的最简单方法。
So, you need a container for your's object, and you should make two things: rotate container and move object on container. 因此,您需要一个用于对象的容器,并且应该做两件事:旋转容器和在容器上移动对象。 I will show an example with particle as object:
我将展示一个以粒子为对象的示例:
Sprite* container = Sprite::create("background.png");
container->setAnchorPoint(Vec2::ANCHOR_MIDDLE); // the container is rotated about its center
container->setPosition(winSize.width * 0.5f, winSize.height * 0.5f);
container->setOpacity(255); // it’s only for test. After that you can setOpacity(0)
this->addChild(container);
ParticleSystemQuad* particle = ParticleSystemQuad::create("particle_meteor.plist");
// place object 100 pixels above the center of the container
particle->setPosition(container->getBoundingBox().size.width * 0.5f, container->getBoundingBox().size.height * 0.5f + 100);
container->addChild(particle);
container->runAction(RotateBy::create(4.0f, 360));
EaseInOut* easeUp = EaseInOut::create(MoveBy::create(0.4f, Vec2(0, 35)), 2.0f);
EaseInOut* easeDown = EaseInOut::create(MoveBy::create(0.4f, Vec2(0, -35)), 2.0f);
particle->runAction(Sequence::create(DelayTime::create(0.1f),
easeUp,
easeDown,
DelayTime::create(0.2f),
easeUp,
easeDown,
DelayTime::create(0.2f),
easeUp,
easeDown,
DelayTime::create(0.2f),
easeUp,
easeDown,
DelayTime::create(0.1f),
NULL)); // particle «jumps» in corners
Here I show only one turnover, but you can get it to rotate continuously. 在这里,我仅显示一个营业额,但您可以使其连续旋转。 There is result of program:
有程序的结果:
It is not same as your splain, but the principle of the creation should be clear. 它与您的原作不同,但创建原理应明确。 I think, you can decrease the distance in
MoveBy:
and experiment with Ease:
for a better results. 我认为,您可以在
MoveBy:
减小距离,并尝试Ease:
以获得更好的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.