如何在精灵套件中进行慢速色彩转换?

时间:2015-10-26 18:11:07

标签: swift sprite-kit

Hello开发人员,

我试图在SpriteKit中慢慢改变圆圈的颜色,在它们之间有一段时间从原始颜色转换到新颜色,从一种颜色转换到另一种颜色。我遇到的问题是我的代码没有慢慢改变,它只是像我直接分配新颜色一样改变。这是我的实际代码:

func changeColor(c: UIColor) {
        var r:CGFloat = 0
        var g:CGFloat = 0
        var b:CGFloat = 0
        var a:CGFloat = 0
        c.getRed(&r, green: &g, blue: &b, alpha: &a)

        var r1:CGFloat = 0
        var g1:CGFloat = 0
        var b1:CGFloat = 0
        var a1:CGFloat = 0
        circle.fillColor.getRed(&r1, green: &g1, blue: &b1, alpha: &a1);
        let wait = SKAction.waitForDuration(0.4)
        r = (r - r1)/10
        g = (g - g1)/10
        b = (b - b1)/10

        for(var i = 0; i < 10; i++) {
            let cN = UIColor(red: (r1 + r*CGFloat(i)), green: (g1 + g*CGFloat(i)), blue: (b1 + b*CGFloat(i)), alpha: 1.0)
            circle.fillColor = cN
            circle.strokeColor = cN
            runAction(wait)
        }
    }

我真的相信问题出在&#34; runAction(等待)&#34;,但我不确定。我想知道是否有默认功能能够满足我的需求,但我对此非常怀疑。

1 个答案:

答案 0 :(得分:4)

问题是你正在尝试做所有这些事情&#34;生活&#34;在for循环中。函数中的所有代码都在动画帧之间运行,这样就无法工作。

为了使这一点更加清晰,请暂时忽略wait部分。当您运行如下所示的函数时:

func changeColor() { // unrolled loop and pseudocode colors for clarity
    circle.fillColor = blue
    circle.fillColor = red
    circle.fillColor = green
}

...... SpriteKit 会立即三次更改圆圈的颜色 - 但它不会绘制结果。无论您将其设置为最近的颜色,只有在所有代码完成运行且SpriteKit绘制屏幕后才会显示。

当您使用SKAction时,您正在做的是排列SpriteKit的指令以跟随随着时间的推移,其中包含有关多个动画帧的任务的说明。但是代码中的非SKAction调用仍然与之前相同 - 它们会立即进行更改,最终结果会在下一帧绘制时显示。

所以,当你的代码看起来像这样:

func changeColor() { // unrolled loop and pseudocode colors for clarity
    circle.fillColor = blue
    circle.runAction(SKAction.waitForDuration(0.4))
    circle.fillColor = red
}

......事件的顺序是这样的:

  1. 将颜色设置为蓝色
  2. 将等待操作添加到计划操作列表
  3. 将颜色设置为红色
  4. 绘制下一帧(颜色为红色)
  5. 执行计划行动清单(在按顺序执行下一步行动前等待0.4秒)
  6. 因此,首先要做的是让颜色更改停止进行帧间更改,并将它们添加到超时任务列表中 - 即通过SKAction更改颜色。有一个colorizeWithColor动作,但我不确定它是否适用于形状节点(具有单独的填充/描边颜色)。试试吧,如果失败,您可以尝试直接设置fillColor / strokeColor的{​​{3}}操作。

    回到伪代码谈论排序问题,但是......

    func changeColor() { // unrolled loop and pseudocode color actions
        circle.runAction(mySetBlueColorAction)
        circle.runAction(SKAction.waitForDuration(0.4))
        circle.runAction(mySetRedColorAction)
    }
    

    如果你这样做,你会注意到这里仍然存在问题。只需调用runAction即可添加单独的操作(大致)并行。所以你的圈子仍然会改变颜色两次,但这两种变化都在同一时间发生。 (哪一个获胜?我不确定那里是一个确定的答案。)在你的圈子对它的颜色感到困惑的同时,它也开始等待0.4秒......到底是什么?

    waitForDuration操作仅在runBlock 操作的上下文中才有意义 - 为了使其有意义,需要按顺序执行某些操作才能等待

    所以,如果你想要发生的事情听起来像这个序列:

    1. 设置颜色
    2. 等一下
    3. 将颜色设置为其他
    4. ...然后您需要的是序列操作,描述您希望按顺序发生的事情:

      let sequence = SKAction.sequence([
          mySetBlueColorAction,
          SKAction.waitForDuration(0.4),
          mySetRedColorAction,
          SKAction.waitForDuration(0.4),
          mySetGreenColorAction,
          // etc.
      ])