用基数样条做一个循环
Make a loop with cardinal spline
我正在尝试为 sprite 制作动画,它会在路径上运行并且会永远循环。但是CardinalSpline并没有像我想的那样关闭。
以下是示例点(这是一个正方形):
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));
动画创作:
auto redSpline = CardinalSplineTo::create(20, pointsRed, 0);
看起来是这样的:
所以当然动画看起来不太好。我想做一个完美的循环(以恒定速度),在哪里看不到结束或开始。
如果我继续添加相同的点,它会很好地循环,直到它到达故障的尽头,您可以在右上角看到它。
我怎样才能做到这一点?
我唯一想到的是点数太多了,动画刚好一半就开始寻找它或创建一个新的。
要在 AutoCAD 等 CAD 程序中绘制样条曲线,您不仅必须指定点,还必须指定极值点的方向(假想延伸)。方向影响样条曲线从极值点到下一个点的行为。
这里没有指定方向,所以样条的极值点有一个"sharp transition".
尝试添加两个点来表示方向,例如:
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));
我指出了极值点的大概位置。您应该移动它们并确定确切的位置以实现样条曲线的精确叠加。
P.S。或者您可以尝试连接样条曲线不在拐角处和样条曲线的平坦图上,例如在点 (250, 360) 处。
我之前的回答只涉及样条创建。但是现在我用螺旋线让我的粒子旋转,并且知道了最简单的方法可以帮助你。
所以,你的对象需要一个容器,你应该做两件事:旋转容器和在容器上移动对象。我将展示一个以粒子为对象的例子:
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
这里我只展示了一个翻转,但是你可以让它连续旋转。有程序结果:
和你的splain不一样,但是创作原理应该很清楚了。我认为,您可以减小 MoveBy:
中的距离并尝试 Ease:
以获得更好的结果。
我终于做到了。我不得不稍微更改 cocos2d-x 代码。
所有需要的更改:
在 startWithTarget 中:
_deltaT = (float) 1 / (_points->count() - 1);
至:
_deltaT = (float) 1 / (_points->count());
重新实现了 getControlPointAtIndex:
来自:
Vec2 PointArray::getControlPointAtIndex(ssize_t index)
{
index = MIN(static_cast<ssize_t>(_controlPoints->size())-1, MAX(index, 0));
return *(_controlPoints->at(index));
}
至:
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));
}
然后样条插值很好,因为它总是有 4 个不同的点可以插值。在第一个和最后一个点被切断之前。
我正在尝试为 sprite 制作动画,它会在路径上运行并且会永远循环。但是CardinalSpline并没有像我想的那样关闭。
以下是示例点(这是一个正方形):
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));
动画创作:
auto redSpline = CardinalSplineTo::create(20, pointsRed, 0);
看起来是这样的:
所以当然动画看起来不太好。我想做一个完美的循环(以恒定速度),在哪里看不到结束或开始。
如果我继续添加相同的点,它会很好地循环,直到它到达故障的尽头,您可以在右上角看到它。
我怎样才能做到这一点?
我唯一想到的是点数太多了,动画刚好一半就开始寻找它或创建一个新的。
要在 AutoCAD 等 CAD 程序中绘制样条曲线,您不仅必须指定点,还必须指定极值点的方向(假想延伸)。方向影响样条曲线从极值点到下一个点的行为。
这里没有指定方向,所以样条的极值点有一个"sharp transition".
尝试添加两个点来表示方向,例如:
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));
我指出了极值点的大概位置。您应该移动它们并确定确切的位置以实现样条曲线的精确叠加。
P.S。或者您可以尝试连接样条曲线不在拐角处和样条曲线的平坦图上,例如在点 (250, 360) 处。
我之前的回答只涉及样条创建。但是现在我用螺旋线让我的粒子旋转,并且知道了最简单的方法可以帮助你。
所以,你的对象需要一个容器,你应该做两件事:旋转容器和在容器上移动对象。我将展示一个以粒子为对象的例子:
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
这里我只展示了一个翻转,但是你可以让它连续旋转。有程序结果:
和你的splain不一样,但是创作原理应该很清楚了。我认为,您可以减小 MoveBy:
中的距离并尝试 Ease:
以获得更好的结果。
我终于做到了。我不得不稍微更改 cocos2d-x 代码。
所有需要的更改:
在 startWithTarget 中:
_deltaT = (float) 1 / (_points->count() - 1);
至:
_deltaT = (float) 1 / (_points->count());
重新实现了 getControlPointAtIndex:
来自:
Vec2 PointArray::getControlPointAtIndex(ssize_t index)
{
index = MIN(static_cast<ssize_t>(_controlPoints->size())-1, MAX(index, 0));
return *(_controlPoints->at(index));
}
至:
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));
}
然后样条插值很好,因为它总是有 4 个不同的点可以插值。在第一个和最后一个点被切断之前。