SpriteKit Swift make an entire scene darker, then change it back - swift

Is there any way to make an entire scene, including all of its children nodes (not just the background color) darker in color? I am looking for an effect similar to that of this code:
node.color = SKColor.blackColor()
node.colorBlendFactor = 0.25
The above code shades the node a darker color, while keeping the original colors (except that those colors are just darker) and detail.
However, as far as I can tell, this code doesn't work on scenes, it only works on SKSpriteNode. Is there any way to darken a whole scene? The answer could be some sort of filter, a special way of colorizing a scene, or maybe there is just no way. Anything helps!
Thanks

When I need to do something similar to what you are asking, I simply add a SKSpriteNode on top of everything else as follows:
let dimPanel = SKSpriteNode(color: UIColor.blackColor(), size: self.size)
dimPanel.alpha = 0.75
dimPanel.zPosition = 100
dimPanel.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
self.addChild(dimPanel)
Just make sure the panel's zPosition is greater than everything you want to make dimmer.
This way, you can also use the SKAction.colorizeWithColor to change the panel to whatever color you want.
To add the panel and then remove it, you could start the alpha at 0, then do:
dimPanel.runAction(SKAction.sequence([
SKAction.fadeAlphaTo(0.75, duration: 3),
SKAction.fadeOutWithDuration(3)
]))

The answer could be some sort of filter...
Indeed. While #TrentSartain's answer is quite practical, it's not the only way. SKScene inherits from SKEffectNode, so you can apply a Core Image filter (or filter chain) to the entire scene as a way to darken it or add other visual effects.
Once you get into Core Image filters, you have all kinds of options for darkening — you can get a different effect from ramping the parameters to CIExposureAdjust than with CIToneCurve, for example. Or you could combine several filters, so your scene (for example) fades to grayscale and blurs as it darkens.
Note: there are no SKActions for animating Core Image filters, but you can change the parameters of a CIFilter object over time in your update function or a customActionWithDuration:actionBlock: block.

Related

Swift 3 (SpriteKit): Changing the alpha value of the parent which affects all children

Say for instance I create SKShapeNode and create children for it (an example is a cross and its two intersecting lines). The cross is the parent, and the intersecting lines are the children. How could you change the alpha value of all the parent's children?
Currently just using:
parent.alpha = 0.5
doesn't change the alpha value of its children.
If anyone is able to maybe create a shader that could solve this issue or use any other way, please reply.
This post is in response to my previous post: (Swift: Make translucent overlapping lines of the same color not change color when intersecting)
I am trying to make the darker spots where translucent lines intersect disappear if someone is able to solve this issue.
Here is some code as an example:
let nodeParent = SKShapeNode()
let nodeOne = SKShapeNode(circleOfRadius: 5)
let nodeTwo = SKShapeNode(circleOfRadius: 5)
//Set the color of the circles, I'm not sure if this is the right way
nodeOne.fillColor = UIColor.init(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0)
nodeTwo.fillColor = UIColor.init(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
nodeParent.addChild(nodeOne)
nodeParent.addChild(nodeTwo)
addChild(nodeParent)
nodeParent.alpha = 0.5
I have taken a screenshot of the problem while using lines instead of circles:
Thanks.
This is the correct and intended behaviour, for SpriteKit blendModes, largely because they don't have a like-for-like blending mode that ignores anything the same as itself.
When you reduce the opacity of several nodes, that are still drawn sequentially, as these are, you get a cumulative result under any blending positions. That's why the bright part at the middle.
In my answer to your previous question, I was avoiding cumulative rendering by "flattening" both axis of the cross into a texture, then loading that texture as a SpriteNode, a one time rendering object that has no intersections because it's all one thing.
Anything you want to have avoid this kind of cumulative, sequential rendering effect of less than full opacity will require you to first "flatten" it with all objects/lines/shapes at 100% opacity, first, then apply Opacity changes to get alpha effects.
This is why I said, in that first "answer", that it's not really a solution for your bigger problem, just a way to get the desired result.
Without a like-to-like ignores rendering mode, SpriteKit isn't able to do overlays without a cumulative impact on anything that's got less than full opacity.

Swift Sprite-kit SKPhyshicsBody

I have a few images that can detect when they get touched right now I am using
plane.physicsBody = SKPhysicsBody(circleOfRadius: plane.frame.height / 2)
but I need it so it is the boarder of the image not a circle or rectangle.
We have a plane and you want a physical body.
Your first approach is circleOfRadius (the physical representation is a circle with a given radius). You can use another shape, such a rectangle:
plane.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(100, height: 100))
As explained in the comments you can also use the shape of a sprite (texture) to create the shape of the physics body:
plane.physicsBody = SKPhysicsBody(texure: plane.texture!, size: plane.size)
But a good way to choose it's this: if you want your game to run smootly on many different devices, don't make sure the physics calculations become too complicated. In other words if you have many object around your plane with physical behavior moving around and colliding with each other, you may choose to use simplified shapes to deal with the physics more efficiently, especially if a shape already looks a lot like a rectangle or a circle.

how to paint/erase SKSpriteNode

A little bit stuck on how to paint/draw an effect like an alpha Chanel onto an SKSpriteNode node i've started off with setting up the two images I need (ps if there is another way to do this is sprite-kit id love to know how to paint the masks
1)The hidden picture - SKSpriteNode *hiddenimageNode
2)The overlay that gets scratched away SKSpriteNode *myOverlay
3)And finally a mask node comprising of
UIImage *image;
SKTexture *maskTexture= [SKTexture textureWithImage:image];
maskNode = [SKSpriteNode spriteNodeWithTexture:maskTexture];
all of these are placed inside of a node "cropNode" [SKCropNode node];
this works more like a static image (that of a circle moving at touch location and not quite what I'm after, I'm hoping to be able to scratch away the entire image)
this works fine but its Not quite the look I'm after
Pictures: Dragging finger from pos1 to pos02, while "erasing purple layer to reveal a smileyface"
is there a way to make it look like I'm erasing the sprite?
nubie coder
//Updating project...
So since then I have tried using this code
https://github.com/oyiptong/CGScratch
and have added it to my SkScene by creating a subview then placing the UIView (Scratchview into it)the erasing is working however the erasing is not happening where the touches are occurring, any ideas why this might be happening?
If you are doing this in iOS 8, then your best bet is to just use SKSpriteNodes as your masking nodes, there is a weird bug with other kinds of nodes that causes distortion.
If you are doing this with iOS9 +, then SKShapeNodes are fixed.
I am going to explain the concept for iOS 9. To get this to work in iOS 8 is a real pain, since subtraction does not subtract alpha in iOS 8.
Now for your mask nodes, you only have 2 options for drawing, On and Off based on the alpha level of the pixels in your mask image. So what you want to do is incorporate subtraction alpha blending to create your desired effect.
let bigcircle = SKShapeNode(circleOfRadius: 80)
bigcircle = .whiteColor()
let littlecircle = SKShapeNode(circleOfRadius: 40)
littlecircle.position = CGPoint(x: 10, y: 10)
littlecircle.fillColor = .whiteColor()
littlecircle.blendMode = .Subtract
bigcircle.addChild(littlecircle)
maskNode = bigcircle
What this code is doing is making a big white circle with a radius of 80 points, and drawing a white circle inside of it at 40 points. Since we are using subtraction blending, it is going to take the new color and subtract it from the old (in our case white(1,1,1,1) - white(1,1,1,10 = transparent(0,0,0,0)) and get us a nice hole in our mask that will end up being cropped out of the layer over your smiley face.

SKPhysicsBody uses only part of SKTexture

I'm using an SKTexture with an image and set the SKPhysicsBody. Like that:
var moleTexture = SKTexture(imageNamed: "moleTop1")
leftPlayer = SKSpriteNode(texture: moleTexture)
leftPlayer.physicsBody = SKPhysicsBody(texture: moleTexture, size: leftPlayer.texture!.size())
Now after I start my game, I noticed that the physicsBody is set wrong. I've activated the showPhysics property and my image looks like that:
As you see, the only thing which is used by SKPhysicsBody is the little part on the middle left(blue border).
How can I change that so that the whole image will be used?
That looks interesting. I believe it will only create an outline (or one shape) and it appears to be starting from the left and because there are no other pixels near enough it calls it done.
I wonder if you get a different result if those pixels are touching. I would try and validate that first. If that is the case you may have to change the texture or use a different variation of the texture for the physical body.
I hope that helps =)

Is there a simple way to let a layer throw an smooth shadow?

I was drawing a path into a layer. Lets say I can't access that drawing code in any way, because it comes from a compiled lib. Now I want to let that layer throw a shadow which matches the shape of its irregular content shape.
Is there an easy way to do it? Or must I draw like 20 of those layers and scale them up on every iteration, adjusting their alpha and letting the GPU do the extraordinarily heavy compositing?
every CALayer has the following properties:
shadowOpacity
shadowRadius
shadowOffset
shadowColor
shadowPath
If you set shadowOpacity to something other than 0 (the default) you'll see a shadow.
(CALayer docs)