4

I have a simple scene with some elements added to it.

Now i want focus on a specific element with a mask a cut a whole at the same position as the element I want to focus on. Very similar to what we can see on some games when they are started first time showing some kind of tutorial.

Basically I am adding a fullscreen layer with alpha=0.7 (so user still see all the content) but then add a circle at a specific position as this layers child and set blendMode=. Subtract so it "cuts" out a circle from this fullscreen layer so within this circle you have a clear view.

I have the following code after I have added all the elements onto the screen.

// before this code i added some basic elements like circles and backgrounds
let mask = SKSpriteNode(color: .blackColor(), size: self._screenSize)
mask.anchorPoint = CGPoint.zero
mask.position = CGPoint.zero
mask.zPosition = 100
mask.alpha = 0.7

let circle = SKShapeNode(circleOfRadius: Constants.Config.playersize*2)
circle.fillColor = .blackColor()
circle.lineWidth = 0
let circle_mask = SKSpriteNode(texture: SKView().textureFromNode(circle, crop: circle.frame))
circle_mask.blendMode = .Subtract
circle_mask.zPosition = 101

// now show the layer with alpha=0.7 and the circle mask being at the same position as my player element i want to focus on
mask.addChild(circle_mask)
circle_mask.position = player.position
self.addChild(mask)

But this simply adds the fullscreen layer, no circle holes. Looks like it is ignoring the circle_mask node. What am I doing wrong?

My plan is also to keep moving the circle mask to focus on other elements on this scene. As I understand. Subtract it should subtract only from its parent node, which is the fullscreen layer with alpa=0.7, right?

I just tried with SKCropNode. Added the fullscreen layer as a child into the crop node, then assigned the circle as mask. But now its cutting out nearly everything but just showing a circle of my fullscreen layer, i actually need the inverted result of this crop node.

The problem with blendMode is that is runs it on the final framebuffer, but what i need is to run it on the parent node only, so it does not cut everything behind the node when using .Subtract

NovumCoder
  • 4,349
  • 9
  • 43
  • 58
  • You never add circle to circle mask, you just make it as a texture, it does not blend to anything. Make circle mask the full black box. And add circle as a child. Alpha blending will kick in and create the hole. Also masking does not work at an alpha level, it is simply on and off, so you need to add a transparent texture as your normal texture, then you have your circle mask to punch the hole – Knight0fDragon Nov 20 '16 at 13:55
  • @Knight0fDragon: I don't get it. Isn't my code doing exactly what you described? My fullscreen layer has alpha=0.7 already. Now i add the circle sprite as child. But how do i make that "alpha blending" you are writing about. Obviously blendMode=.Subtract is wrong. At the end i add my mask with the circle child onto the scene. Can you provide some corrected code? – NovumCoder Nov 20 '16 at 18:43
  • no it is not, now that I am on a PC i will try and write an answer for you – Knight0fDragon Nov 20 '16 at 21:55

1 Answers1

3

Here is an example on how to create a translucent layer with a hole punched into it:

-(NOTE: .subtract blend mode does not take alpha of the sprite into consideration, so you need to use a crop node)

self.backgroundColor = .red


//Our transparent overlay
let fullScreen = SKSpriteNode(color: .black, size: self.size)
fullScreen.position = CGPoint.zero
fullScreen.zPosition = 100
fullScreen.alpha = 0.7

//let's make a mask to punch circles in our shape
let mask = SKSpriteNode(color: .white, size: self.size)
mask.position = CGPoint.zero
mask.zPosition = 100
mask.alpha = 1

let circle = SKShapeNode(circleOfRadius: 20*2)
circle.fillColor = .white
circle.lineWidth = 0
circle.alpha = 1

//let circle_mask = SKSpriteNode()
circle.blendMode = .subtract
mask.addChild(circle)

//let's create the node to place on screen
let crop = SKCropNode()
crop.maskNode = mask
crop.addChild(fullScreen)

self.addChild(crop)
Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44