In my app I want to show an animation of slowly rotating fan blades (four of them) in front of the fan body and background.
I can get close to the desired result by simply rotating the image of the blades in a UIImageView using Core Animation. But the blades look too "flat". I can get a bit closer still by calculating a slight shadow for the blades, and then rotating the shaded image just 90° over and over. That still doesn't look great.
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOpacity = 0.8
self.layer.shadowOffset = CGSize(width: 1, height: 1.5)
self.layer.shadowRadius = 2.5
let animate = CABasicAnimation(keyPath: "transform.rotation")
So I've taken the time to play with SpriteKit enough to get close to a possible solution. I need a bit more help to complete the approach. I want the shadow of the blades to be seen on the background behind it. So far I can only get the blades to look like they're lit, but they are not casting a shadow.
Here's my excerpted code for the view controller where I want this to happen:
import SpriteKit
func addShuriken() { // example comes from raywunderlich, modified
let shuriken = SKSpriteNode(imageNamed: "Fan Blades") // This is my png image of 4 fan blades
let actualY = 300
let left = arc4random() % 2
let actualX = 150
shuriken.position = CGPoint(x: 0.5, y: 0.5)
shuriken.name = "shuriken"
shuriken.zPosition = 1
shuriken.lightingBitMask = 1
shuriken.shadowCastBitMask = 1
shuriken.size = CGSize(width: 60.0, height: 60.0)
animationView.scene?.addChild(shuriken)
let angle = left == 0 ? -CGFloat.pi/2 : CGFloat.pi/2
let rotate = SKAction.repeatForever(SKAction.rotate(byAngle: angle, duration: 0.5))
shuriken.run(SKAction.repeatForever(rotate))
}
func makeScene() -> SKScene {
let minimumDimension = min(80, 80)
let size = CGSize(width: minimumDimension, height: minimumDimension)
let scene = SKScene(size: size)
scene.backgroundColor = .blue // I'd prefer this to be clear. I think I'll probably have to put an image here on which to cast a shadow
scene.alpha = 1.0
scene.scaleMode = .resizeFill
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
animationView.allowsTransparency = true
let light = SKLightNode()
light.lightColor = .white
light.shadowColor = .black
light.falloff = 0.5
light.isEnabled = true
light.categoryBitMask = 1
light.position = CGPoint(x: 0.2, y: 0.0)
scene.addChild(light)
return scene
}
private lazy var animationView = SKView()
override func loadView() {
super.loadView()
view.addSubview(animationView)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard animationView.scene == nil else {
return
}
let scene = makeScene()
animationView.frame.size = scene.size
animationView.presentScene(scene)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
animationView.center.x = view.bounds.midX
animationView.center.y = view.bounds.midY
}
This code produces a rotating image with uniform lighting on the fan blades but no shadow cast onto the background. The lighting doesn't seem to be from one direction - it looks like it's centered. I'll attach a screen shot if you can tell me how to do that here.