Shadow attenuation along with SKSpriteNode, which casts it

Here is my setup using the Sprite Kit. First, I create a simple node sprite inside SKScene, for example:

let block = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(90, 160)) block.zPosition = 2 block.shadowCastBitMask = 1 addChild(block) 

Then add the light node to the scene:

 let light = SKLightNode() light.categoryBitMask = 1 light.falloff = 1 addChild(light) 

Of course, the block now highlights a nice little shadow:

SKSpriteNode with alpha = 1.0 casting a shadow

Now I am fading the block by manipulating its alpha value, for example, by running an action:

 let fadeOut = SKAction.fadeAlphaTo(0.0, duration: 5.0) block.runAction(fadeOut) 

Here's an awkward situation: while the block is becoming more transparent, the shadow remains exactly the same . Here's what it looks like just a minute before the end of the action:

enter image description here

And as soon as the alpha drops to 0.0 entirely, the shadow suddenly disappears, from one frame to another.

It would be much nicer if the shadow slowly became weaker and weaker, since the object casting it becomes more and more transparent .

Question:

Is this possible with the Sprite Kit? If so, how would you do it?

+5
source share
2 answers

This is a bit tricky because a shadow other than SKLightNode is independent of the node alpha property. What you need to do is the alpha channel disappears from the shadowColor property of the shadowColor object at the same time that you lose your block .

The main steps:

  • Save the shadowColor light and this color alpha channel for reference.
  • Create SKAction.customActionWithDuration , which:
    • Recalculates the value for the alpha channel based on the original and how much time has passed so far in action.
    • Sets the shadowColor light to its original color, but with a new alpha channel.
  • Perform the block attenuation action and the shadow attenuation action in parallel.

Example:

 let fadeDuration = 5.0 // We're going to use this a lot // Grab the light original shadowColor so we can use it later let shadowColor = light.shadowColor // Also grab its alpha channel so we don't have to do it each time let shadowAlpha = CGColorGetAlpha(shadowColor.CGColor) let fadeShadow = SKAction.customActionWithDuration(fadeDuration) { // The first parameter here is the node this is running on. // Ideally you'd use that to get the light, but I'm taking // a shortcut and accessing it directly. (_, time) -> Void in // This is the original alpha channel of the shadow, adjusted // for how much time has past while running the action so far // It will go from shadowAlpha to 0.0 over fadeDuration let alpha = shadowAlpha - (shadowAlpha * time / CGFloat(fadeDuration)) // Set the light shadowColor to the original color, but replace // its alpha channel our newly calculated one light.shadowColor = shadowColor.colorWithAlphaComponent(alpha) } // Make the action to fade the block too; easy! let fadeBlock = SKAction.fadeAlphaTo(0.0, duration: fadeDuration) // Run the fadeBlock action and fadeShadow action in parallel block.runAction(SKAction.group([fadeBlock, fadeShadow])) 
+2
source

The following is one way to ensure that the shadow and block will fade in / out. To use this approach, you need to declare the light and block it as class properties.

 override func didEvaluateActions() { light.shadowColor = light.shadowColor.colorWithAlphaComponent(block.alpha/2.0) } 

EDIT: Here's how to implement the above.

 class GameScene: SKScene { let light = SKLightNode() let block = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(90, 160)) override func didMoveToView(view: SKView) { /* Setup your scene here */ block.zPosition = 2 block.shadowCastBitMask = 1 block.position = CGPointMake(100, 100) addChild(block) light.categoryBitMask = 1 light.falloff = 1 addChild(light) let fadeOut = SKAction.fadeAlphaTo(0.0, duration: 5.0); let fadeIn = SKAction.fadeAlphaTo(1.0, duration: 5.0); block.runAction(SKAction.sequence([fadeOut,fadeIn,fadeOut])) } override func didEvaluateActions() { light.shadowColor = light.shadowColor.colorWithAlphaComponent(block.alpha/2.0) } } 
+1
source

Source: https://habr.com/ru/post/1203431/


All Articles