Use an SKShapeNode for the mask of an SKCropNode (Swift) - ios

How can I use an SKShapeNode for the mask of an SKCropNode? My code currently creates an SKShapeNode circle and then sets the crop node mask to it
shapeNode = SKShapeNode(circleOfRadius: 50)
shapeNode.fillColor = UIColor.red
shapeNode.lineWidth = 1
shapeNode.position = CGPoint(x: 0, y: 0)
shapeNode.zPosition = 4
cropNode = SKCropNode()
cropNode.maskNode = shapeNode
cropNode.addChild(Node)
But when I add the Node as a child of the cropNode it doesnt draw anything but a red circle (exactly as i set it to do)
Is there any way to use an SKShapeNode as the mask of an SKCropNode?
-Update-
I figured out how to make an SKSpriteNode drawn from the SKShapeNode
shapeNode = SKShapeNode(circleOfRadius: 60)
shapeNode.fillColor = UIColor.red
let shapeTexture = view.texture(from: shapeNode)
textureNode = SKSpriteNode(texture: shapeTexture)
textureNode.position = CGPoint(x: 0, y: 0)
textureNode.zPosition = 3
cropNode.maskNode = textureNode
cropNode.addChild(tileMap2)
self.addChild(cropNode)
But now the SKCropNode isnt working when applied to the SKSpriteNode how do I fix this?

Related

SKSpriteNode shadow rendering incorrectly?

I'm using Xcode 11.4.1 and Swift 5.2.2, and I am trying cast a shadow using an SKLightNode onto a circular SKSpriteNode.
However, the shadow is cast over the rectangular frame of the SpriteNode rather than the circle image png that I am using.
This is the desired effect
This is what happens
In the first image, I am using a 611x611px circle png while in the second I am using a 612x612 png. I have found that this "corner shadow" happens only when using specific image dimensions to create the SpriteNode.
Specifically, through my testing, square images with size <688px and >601px display no corner shadow, except sizes exactly 612 and 608. I am testing this in a playground but the same problem occurs in a full xcodeproj.
What have I done wrong here? I doubt my code is the issue but here it is:
import PlaygroundSupport
import SpriteKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
let background = SKSpriteNode(color: UIColor.blue, size: frame.size)
background.zPosition = 0
background.position = CGPoint(x: frame.midX, y: frame.midY)
background.lightingBitMask = 1
addChild(background)
let light = SKLightNode()
light.zPosition = 100
light.categoryBitMask = 1
light.falloff = 0.5
light.lightColor = UIColor.white
light.position = CGPoint(x: frame.midX, y: frame.midY)
addChild(light)
let sprite = SKSpriteNode(imageNamed: "612.png")
sprite.color = UIColor.yellow
sprite.colorBlendFactor = 1
sprite.zPosition = 3
sprite.position = CGPoint(x: frame.midX, y: frame.midY + 100)
sprite.size = CGSize(width: 100, height: 100)
sprite.physicsBody = SKPhysicsBody(circleOfRadius: 50)
sprite.physicsBody?.categoryBitMask = 2
sprite.shadowCastBitMask = 1
sprite.lightingBitMask = 1
sprite.physicsBody?.isDynamic = false
addChild(sprite)
}
}
let sceneView = SKView(frame: CGRect(x:0 , y:0, width: 640, height: 480))
let scene = GameScene()
scene.scaleMode = .aspectFill
scene.size = sceneView.frame.size
sceneView.presentScene(scene)
PlaygroundSupport.PlaygroundPage.current.liveView = sceneView

SKCropNode fails when I add extra SKNode children in hierarchy

Update: It looks like iOS 10 has fixed this issue. I upgraded to Swift 3 and Xcode 8 and everything is working as expected.
I've run into this issue a couple times now and I can't tell if it's a bug in SKCropNode or if I'm just misusing it. Perhaps there's some bit of documentation I'm missing to explain why this is happening?
I have a crop node with a 100x100 rectangle shape as the mask. If I place a blue circle inside it, it gets cropped properly.
// Create a crope node with a small square.
let cropNode = SKCropNode()
let cropNodeMask = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 100, height: 100))
cropNodeMask.fillColor = UIColor.whiteColor()
cropNode.maskNode = cropNodeMask
self.addChild(cropNode)
// Create a blue circle and put it in the crop node.
let blueCircle = SKShapeNode(circleOfRadius: 110)
blueCircle.fillColor = UIColor.blueColor()
blueCircle.strokeColor = UIColor.clearColor()
cropNode.addChild(blueCircle)
Now, when I place that same circle inside of an otherwise empty SKNode and place that container inside the same crop node, cropping fails.
// Create a crope node with a small square.
let cropNode = SKCropNode()
let cropNodeMask = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 100, height: 100))
cropNodeMask.fillColor = UIColor.whiteColor()
cropNode.maskNode = cropNodeMask
self.addChild(cropNode)
// Create a container to hold the circle.
let container = SKNode()
cropNode.addChild(container)
// Create a blue circle and put it in the container.
let blueCircle = SKShapeNode(circleOfRadius: 110)
blueCircle.fillColor = UIColor.blueColor()
blueCircle.strokeColor = UIColor.clearColor()
container.addChild(blueCircle)
But a sprite in that same container seems to be cropped fine.
// Create a crope node with a small square.
let cropNode = SKCropNode()
let cropNodeMask = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 100, height: 100))
cropNodeMask.fillColor = UIColor.whiteColor()
cropNode.maskNode = cropNodeMask
self.addChild(cropNode)
// Create a container to hold the sprite.
let container = SKNode()
cropNode.addChild(container)
// Create a spaceship and add it to the container.
let spaceshipNode = SKSpriteNode(imageNamed: "Spaceship")
spaceshipNode.anchorPoint = CGPointZero
container.addChild(spaceshipNode)
SKShapeNode is bugged, best to avoid it at all costs. Use it to create your shapes, then convert it to a texture for use with SKSpriteNode

Strange black border when using SKCropNode

I'm working on a game with SpriteKit and I have a square SKSpriteNode whose corners I want to make round. I can't use an SKShapeNode because I want to eventually add a gradient to it. So I decided to use as SKCropNode to crop it, but when I do so, a weird black border like this appears:
If I don't try to crop it, it looks like this:
This is my code I am using to create and crop it:
spriteNode = SKSpriteNode(color: color.skColor, size: CGSize(width: TileSize, height: TileSize))
let borderRadius: CGFloat = 2
let roundPath = CGPathCreateWithRoundedRect(CGRect(x: -TileSize / 2, y: -TileSize / 2, width: TileSize, height: TileSize), borderRadius, borderRadius, nil)
let mask = SKShapeNode()
mask.path = roundPath
mask.fillColor = SKColor.whiteColor()
mask.strokeColor = SKColor.whiteColor()
let cropNode = SKCropNode()
cropNode.maskNode = mask
let shadow = SKSpriteNode(color: SKColor.blackColor(), size: CGSize(width: TileSize, height: TileSize))
shadow.colorBlendFactor = 1
shadow.alpha = 0.25
let radius: CGFloat = 3.5
shadow.position = CGPoint(x: radius / 2, y: radius / 2)
let effectNode = SKEffectNode()
effectNode.filter = CIFilter(name: "CIGaussianBlur", withInputParameters: [kCIInputRadiusKey: radius])
effectNode.zPosition = spriteNode!.zPosition - 1
effectNode.addChild(shadow)
let bluredTile = SKShapeNode(path: roundPath)
bluredTile.addChild(effectNode)
cropNode.addChild(spriteNode!)
addChild(bluredTile)
addChild(cropNode)
Why is this happening, and how can I stop it?

Programmatically create constrained region of physics, SpriteKit

I would like two regions, as shown in the image below, where the yellow region is to contain sprites. For example I'd like to have balls in the yellow region bouncing and reflecting off the boundaries of the yellow region. How can I programmatically do this without using an sks file?
You create an edge based physics body using the +bodyWithEdgeLoopFromRect:
override func didMoveToView(view: SKView) {
//Setup scene's physics body (setup the walls)
physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)
let yellowSprite = SKSpriteNode(color: .yellowColor(), size: CGSize(width: 300, height: 300))
yellowSprite.position = CGPoint(x: frame.midX, y: frame.midY)
//Create the rectangle which will represent physics body.
let rect = CGRect(origin: CGPoint(x: -yellowSprite.size.width/2, y: -yellowSprite.size.height/2), size: yellowSprite.size)
yellowSprite.physicsBody = SKPhysicsBody(edgeLoopFromRect: rect)
addChild(yellowSprite)
//Add Red ball "inside" the yellow sprite
let red = SKShapeNode(circleOfRadius: 20)
red.fillColor = .redColor()
red.strokeColor = .clearColor()
red.position = yellowSprite.position
red.physicsBody = SKPhysicsBody(circleOfRadius: 20)
red.physicsBody?.restitution = 1
red.physicsBody?.friction = 0
red.physicsBody?.affectedByGravity = false
addChild(red)
red.physicsBody?.applyImpulse(CGVector(dx: 20, dy: 15))
}
About rect parameter:
The rectangle that defines the edges. The rectangle is specified
relative to the owning node’s origin.
Hope this helps!

How to make border for a scene in SpriteKit

I am trying to make border for the two sides in a scene but there is some kind of error the here is the code i used
let leftEdge : SKNode = SKNode()
leftEdge.physicsBody = SKPhysicsBody(edgeFromPoint: CGPointZero, toPoint: CGPointMake(0.0, self.size.height + 100))
leftEdge.position = CGPointZero;
self.addChild(leftEdge)
let rightEdge : SKNode = SKNode()
rightEdge.physicsBody = SKPhysicsBody(edgeFromPoint: CGPointZero, toPoint: CGPointMake(0.0, self.size.height + 100))
rightEdge.position = CGPointMake(self.size.width, 0.0);
self.addChild(rightEdge)
but the top border and bottom border get the borders and the two sides its seems like they have border outside the the scene cause i shoot object toward them it goes out of the scene and get back so the question how i make borders only for the two sides the left and the right
try this
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 1
self.physicsBody = border
obviously you can add your own physics to your border.

Resources