使用基数样条曲线进行循环

时间:2015-10-30 07:24:26

标签: c++ cocos2d-x

我正在尝试为精灵制作一个动画,它会继续路径并且会永远循环。但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);

看起来像是:

enter image description here

当然,动画看起来并不太好。我想做一个完美的循环(以恒定的速度),在那里无法看到结束或开始的地方。

如果我将继续添加相同的点,它将循环好直到它到达故障的末端,你可以在右上角看到。

我怎样才能做到这一点?

我想到的唯一的事情就是点数过多,并且正好有一半的动画要求它去乞讨或创造一个新点。

3 个答案:

答案 0 :(得分:2)

最后我做到了。我不得不稍微更改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个不同的插值点。在第一个也是最后一个点被切断之前。

答案 1 :(得分:0)

要在CAD程序(如AutoCAD)中绘制样条曲线,您不仅要指定点,还要指定极值点的方向(虚拟延伸)。方向会影响样条曲线从极值点到下一个点的行为 这里没有指定方向,因此样条曲线的极值点有一个&#34;急剧过渡&#34; 尝试添加两个点来指示方向,例如:

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));

我指出了极端点的大致位置。您应该移动它们并确定准确叠加样条曲线的确切位置 附:或者您可以尝试连接样条曲线不是在拐角处和样条曲线的平面图上,例如在点(250,360)处。

答案 2 :(得分:0)

我以前的回答只涉及样条曲线创建。但现在我通过螺旋旋转制作了粒子旋转,并且知道可以帮助你的最简单的方法 因此,您需要一个容器用于您的对象,您应该做两件事:旋转容器并在容器上移动对象。我将展示一个以粒子为对象的例子:

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:以获得更好的效果。