SpriteKit - Animate SKShapeNode Shape Path
Asked Answered
F

1

8

Currently I am using Core Graphics for a shape and to transform the shape in to a different one with CAShapeLayer and CABasicAnimation path animation.

However due to the complexity of the game, If were to step in to SpritKit, using SKShapeNode, (discarding CAShapeLayer and using SKShapeNode) would I be able to smoothly animate it in to a different shape?

I did not see a SKAction method that would let you change the path of a SKShapeNode.

Thanks in advance.

Fearless answered 21/12, 2018 at 17:54 Comment(3)
How your shape looks like? What do you want to create? What did you try with CAShapeLayer or SKShapeNode?Klan
@Klan CAShapeLayer has a complex shape. About 200+ points. I am able to recreate the shape with SKShapeNode using CGPath. The wall I hit was when I have to animate the shape changes.Fearless
I believe you can do it with a sequence of actions, some fade in and out and finally add the shape you want to be transformed to. you don't need to use CAShapeLayer or any CoreAnimation.Macknair
A
6

Well. Happy holidays.

The simplest way is to use the CALayerAnimation to teach the SKNode how to action like this :

class ViewController: UIViewController {


@IBOutlet weak var skview: SKView!
var  path1: CGPath!
var  path2: CGPath!

override func viewDidLoad() {
    super.viewDidLoad()

  path1  = CGPath.init(rect: CGRect.init(x: 0, y: 0, width: 100, height: 100), transform: nil)

    path2 = CGPath.init(rect: CGRect.init(x: 0, y: 0, width: 250, height: 400), transform: nil)

}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let shapeLayer = CAShapeLayer()
    self.view.layer.addSublayer(shapeLayer)
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.path = path1

    let anim = CABasicAnimation.init(keyPath: "path")
    anim.duration = 1.0
    anim.fromValue  = path1
    anim.toValue = path2
    anim.isRemovedOnCompletion  = false


    let shapeNode = SKShapeNode.init(path: path1)
    shapeNode.fillColor = UIColor.green

    skview.scene?.addChild(shapeNode)


    shapeLayer.add(anim, forKey:
    "prepanimation")
    shapeNode.run(SKAction.customAction(withDuration: anim.duration, actionBlock: { (node, timeDuration) in
        (node as! SKShapeNode).path =
        shapeLayer.presentation()?.path
    }))

}
}

If you path is too big and an optimum way is to consider converting CABasicAnimation to CAKeyFrameAnimation approach.

From the above process you can extract a pair (time, presentation_Path) at design time. Then assign back during the runtime in SKCustomAction. Please refer to SKKeyframeSequence to get the idea (not exactly but similar animation).

Aurilia answered 24/12, 2018 at 20:48 Comment(4)
I meant moving away from 'CAShapeLayer' and using SKShapeNode in place of that. Is there a way to do that? Above looks right, yet, seems not efficient because twice the work is done for CAShapeLayer and SKShapeNode.Fearless
You have to write custom animation for that.Aurilia
I gave the full bounty since your solution looks clever. However, I am still searching for this animation to be done strictly on SpriteKit.Fearless
Thank you very muchAurilia

© 2022 - 2024 — McMap. All rights reserved.