5

The Apple docs on SKKeyframeSequence have brief sample code designed to create a gradient:

let colorSequence = SKKeyframeSequence(keyframeValues: [SKColor.green,
                                                        SKColor.yellow,
                                                        SKColor.red,
                                                        SKColor.blue],
                                       times: [0, 0.25, 0.5, 1])
colorSequence.interpolationMode = .linear
stride(from: 0, to: 1, by: 0.001).forEach {
    let color = colorSequence.sample(atTime: CGFloat($0)) as! SKColor
}

When combined with a drawing system of some sort, this is said to output this: enter image description here How can this be drawn from the sampling of the sequence of colours in the demo code?

ps I don't have any clue how to draw this with SpriteKit objects, hence the absence of attempted code. I'm not asking for code, just an answer on how to use this 'array' of colours to create a gradient that can be used as a texture in SpriteKit.

Confused
  • 6,048
  • 6
  • 34
  • 75
  • you don't know how to put this into a CALayer? There is a simple way to get a CALayer into a SKTexture... I think if I check my notes... – Fluidity Jan 24 '17 at 21:27
  • No. I don't know how to do that. Go ahead. Check your notes. @Fluidity you must be very smart. – Confused Jan 24 '17 at 21:56
  • But, in between that, take your time to reconsider the QUESTION. It's asking about how to do this in.... SPRITEKIT. Not Core Animation. – Confused Jan 24 '17 at 21:57
  • just noticing the SK prefix of it – Fluidity Jan 24 '17 at 22:01
  • "The primary use for an SKKeyframeSequence object is to animate properties on particles emitted by an SKEmitterNode object. When a keyframe object is assigned to an appropriate property on the emitter node, particles determine their values by sampling the keyframe sequence. The sequence replaces the normal simulation performed by the emitter node. " – Fluidity Jan 24 '17 at 22:05
  • I'll wait while you read the rest of the linked page. – Confused Jan 24 '17 at 22:06
  • no. you just need to play around with an emitter node until you get that fancy gradient ;P – Fluidity Jan 24 '17 at 22:09
  • https://developer.apple.com/reference/spritekit/skemitternode/1397992-particlecolorsequence – Fluidity Jan 24 '17 at 22:13
  • https://developer.apple.com/reference/spritekit/skkeyframesequence/1390914-interpolationmode – Fluidity Jan 24 '17 at 22:13
  • Take your time. Reread the question, and the page it links to. @Fluidity – Confused Jan 24 '17 at 22:15
  • 1
    "SKKeyframeSequence isn’t limited to working only with SKEmitterNode, you can use the sample(atTime:) method to generate values interpolated between keyframes for other applications. " @Fluidity -- I'm asking how to use it to create a gradient SKTexture, with SpriteKit. – Confused Jan 24 '17 at 22:18
  • I think either they changed the code after generating the image, or it's just supposed to be a generic example of a gradient. It's just the documentation being misleading. – James P Feb 02 '17 at 16:59

1 Answers1

5

The colors are different for some reason, but here is what I came up with using their source code:

PG setup:

import SpriteKit
import PlaygroundSupport

let sceneView = SKView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 1000, height: 450)))
let scene     = SKScene(size: CGSize(width: 1000, height: 450))

LOADSCENE: do {
  scene.backgroundColor = .white
  scene.anchorPoint = CGPoint(x: 0, y: 0.5)
  scene.physicsWorld.gravity = CGVector.zero
  sceneView.presentScene(scene)

  PlaygroundPage.current.liveView = sceneView
}

Solution:

// Utility func:
func drawLine(from point1: CGPoint, to point2: CGPoint, color: SKColor) {
  let linePath = CGMutablePath()
  linePath.move(to: point1)
  linePath.addLine(to: point2)

  let newLine = SKShapeNode(path: linePath)
  newLine.strokeColor = color
  newLine.lineWidth = 1
  newLine.zPosition = 10
  scene.addChild(newLine)
  newLine.position.x = point1.x

}

// Holds our soon-to-be-generated colors:
var colors = [SKColor]()

LOADCOLORS: do {
  let colorSequence = SKKeyframeSequence(keyframeValues: [SKColor.green,
                                                          SKColor.yellow,
                                                          SKColor.red,
                                                          SKColor.blue],
                                         times: [0, 0.25, 0.5, 1])

  colorSequence.interpolationMode = .linear
  stride(from: 0, to: 1, by: 0.001).forEach {
    colors.append(colorSequence.sample(atTime: CGFloat($0)) as! SKColor)
  }
}

DRAWGRAD: do {
  for i in 1...999 {
    let p1 = CGPoint(x: CGFloat(i), y: scene.frame.minY)
    let p2 = CGPoint(x: CGFloat(i), y: scene.frame.maxY)
    drawLine(from: p1, to: p2, color: colors[i])
  }

  print("Give me my 25 cookie points, please and TY")
}

enter image description here

You should then be able to get this as a texture as such:

let texture = sceneView.texture(from: scene)

Rendering this took about a million years to render on my gen2 i5 at 2.6ghz for some reason. Will have to look into that, unless it was just a PG bug...

Fluidity
  • 3,985
  • 1
  • 13
  • 34