How to create a rectangle in Sprite kit using Swift - swift

I'm trying to create a rectangle using swift on Sprite kit, since the rectangle needs to be used as an object in the scene, i assumed that i needed to create a SkSpriteNode, and them give it a size, but it did not worked, this is how i did it:
var barra = SKSpriteNode()
barra.name = "bar"
barra.size = CGSizeMake(300, 100)
barra.color = SKColor.whiteColor()
barra.position = CGPoint(x: 100, y: 100)
self.addChild(barra)
Adding barra to the screen does not change the node counting.
Any help will be appreciated!

You may want to use a SKShapeNode, like this:
var barra = SKShapeNode(rectOfSize: CGSize(width: 300, height: 100))
barra.name = "bar"
barra.fillColor = SKColor.whiteColor()
barra.position = location
self.addChild(barra)
Here's Apple's documentation on SKShapeNode.

The way I was creating the rectangle was not the best, but the problem was the position I was inserting it on the game. This is how I've fixed it:
var barra = SKSpriteNode(color: SKColor.blackColor(), size: CGSizeMake(200, 200))
barra.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
barra.zPosition = 9 // zPosition to change in which layer the barra appears.
self.addChild(barra)

Related

SpriteKit: unwanted stretching of sprite when resizing/scaling

I've seen similar questions before but seems that no clear solution is provided. Currently I have a SKScene with child, contained by a SKView. Note: I'm not using a Game project; instead, I'm using the SKView in a normal UIView, and just add SKView as the subview of the UIView. The sprite itself is a small image, and it only occupies a certain portion in the middle-bottom part of the whole frame. The code looks something like this:
let imageView = SKView()
imageView.frame = CGRect(x: ..., y: ..., width: ..., height: ...) //all are predefined constants
let sprite = SKSpriteNode(texture: SKTexture(imageNamed: "image"))
sprite.position = CGPoint(x: imageView.frame.width * 0.5, y: imageView.frame.height * 0.5) // so it's positioned in the center
let scene = SKScene(size: imageView.frame.size) // also tried with sprite.size, but not working
scene.addChild(sprite)
scene.scaleMode = .aspectFit
imageView.presentScene(scene)
self.frame.addSubview(imageView)
Now the problem is the sprite is not in its original shape; it's stretched along the vertical axis. I tried changing the scaleMode with all 5 choices: .fill / .aspectFill / .aspectFit / .resizeFill / none, but none of them give the sprite its original shape/ratio. I've also tried changing the constants for the imageView's frame, but that only cuts the sprite (if imageView.frame.height is decreased). So may I know how to address this issue?
Your code works fine as written, so the problem is likely elsewhere. I modified it a little bit so you can test it out in a Playground. Just make a new Playground and copy and paste. You'll also have to drag in an image for your sprite.
import SpriteKit
import PlaygroundSupport
// create the outer UIView and show it on the playground
let outerView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
PlaygroundPage.current.liveView = outerView
// create the SKView and add it to the outer view
let imageView = SKView(frame: CGRect(x: 25, y: 25, width: 250, height: 250))
outerView.addSubview(imageView)
// create the scene and present it
var scene = SKScene(size: imageView.frame.size)
imageView.presentScene(scene)
// create the sprite, position it, add it to the scene
let sprite = SKSpriteNode(texture: SKTexture(imageNamed: "worf.jpg"))
sprite.position = CGPoint(x: imageView.frame.width * 0.5, y: imageView.frame.height * 0.5)
scene.scaleMode = .aspectFit
scene.addChild(sprite)
Here's the result:
No stretching! So your issue is probably related to the UIView you're placing it in. For example if you add:
outerView.transform = CGAffineTransform(scaleX: 1, y: 2)
Now the image is stretched as you describe. Take a look at your containing view and everything above it.

Swift. Masking a SKTexture on top of a SKSpriteNode

Okay so I have som problems, trying to mask a SKTexture on top op a SKSpriteNode. I've been looking in to SKCropNode, but cant figure it out.
(I'm kinda new to this)
How can i mask this SKTexture: (This is the image called "Mask")
on top of this SKSpriteNode:
so its going to turn out like this:
I tried this, but nothing showed up:
picture.size = CGSize(width: menuLine.frame.height, height: menuLine.frame.height)
picture.zPosition = 10
let cropNode = SKCropNode()
cropNode.addChild(picture)
cropNode.maskNode = SKSpriteNode(imageNamed("Mask")
self.addChild(cropNode)
cropNode.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
cropNode.zPosition = 10

How to contain SKEmitterNode particles in parent Node?

I would like to add a SKEmitterNode to SKNode but have its particles stay inside the parent node's frame. Kinda like clipsToBounds property on UIView.
Example: the particles from the emitter should not leave the black square SKSpriteNode:
You could do it with SKCropNode. Like this:
if let particles = SKEmitterNode(fileNamed: "rain.sks") {
let cropNode = SKCropNode()
cropNode.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
cropNode.zPosition = 3
cropNode.maskNode = SKSpriteNode(color: SKColor.blackColor(), size: CGSize(width: 150, height: 150))
cropNode.addChild(particles)
addChild(cropNode)
}
Unfortunately this works only on iOS8... When you try to add an emitter into crop node in iOS9, you will probably run into some issues, eg. nothing will be rendered and fps drop may occur. And this is already known issue.
Like it's said in that link, instead of particles being rendered, nothing actually happens. Personally, I haven't experienced fps issues , but particles are definitely not rendered.
A workaround would be to add a node which will hold an emitter, and then mask that container node. So, let's add an SKSpriteNode to make that black background like from your example. Let's call it background:
if let particles = SKEmitterNode(fileNamed: "rain.sks") {
let cropNode = SKCropNode()
cropNode.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
cropNode.zPosition = 3
let blackNode = SKSpriteNode(color: .blackColor(), size: CGSize(width: 200, height: 200))
blackNode.addChild(particles)
cropNode.maskNode = SKSpriteNode(color: SKColor.blackColor(), size: CGSize(width: 200, height: 200))
cropNode.addChild(blackNode)
addChild(cropNode)
}

Add SKShapeNode in another one

I want to draw a square in another square; but I can't position the second one in the right way.
What can I do for positioning based on first square coordinates?
var tileBackground = SKShapeNode(rectOfSize: CGSize(width: screenWidth, height: screenWidth))
tileBackground.name = "tileBackground"
tileBackground.fillColor = SKColor.whiteColor()
tileBackground.position = CGPoint(x: frame.midX, y: frame.midY);
self.addChild(tileBackground)
var tile = SKShapeNode(rectOfSize: CGSize(width: tileSize, height: tileSize))
tile.name = "tile1"
tile.fillColor = SKColor.redColor()
tile.position = CGPointMake(100,100)
tileBackground.addChild(tile)
You should use SKSpriteNode instead. That way you can add it easily and without setting the position manually. Because in an SKSpriteNode, the center is always the center of the node:
var tileBackground = SKSpriteNode(color: UIColor.whiteColor(), size: CGSizeMake(width: screenWidth, height: screenWidth))
tileBackground.name = "tileBackground"
tileBackground.position = CGPoint(x: frame.midX, y: frame.midY);
self.addChild(tileBackground)
var tile = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: tileSize, height: tileSize))
tile.name = "tile1"
tileBackground.addChild(tile)
A node's position is relative to its parent position.
If you want the tile node to be in the center of its parent then set its position as:
tile.position = CGPoint(x: tileBackground.size.width / 2.0, y: tileBackground.size.height / 2.0)
which will place the tile in center of the tileBackground node.
also note that you do not need to update the tile position to "follow" the tileBackground node. Updating the tileBackground position will automatically keep the tile in its center

Position of a Node after addChild

I have an SKSpriteNode like a light gray square in the view, and I want to put a label inside it... I do this way:
let puntosCubo = SKSpriteNode(color: SKColor.lightGrayColor(), size: CGSize(width: gameoverTitle.frame.width, height: gameoverTitle.frame.height*4))
puntosCubo.position = CGPoint(x: CGRectGetMinX(self.frame)-100, y:y2)
I put a SKLabelNode inside puntosCubo this way:
let puntosCuboTitle1 = SKLabelNode(fontNamed: "Apple SD Gothic Neo")
puntosCuboTitle1.fontColor = SKColor.blackColor()
puntosCuboTitle1.fontSize = 20
puntosCuboTitle1.text = "Score"
puntosCubo.addChild(puntosCuboTitle1)
puntosCuboTitle1.position = CGPoint(x: 0, y: puntosCubo.position.y)
But the result is that the position of the SKLabelNode is not inside puntosCubo. I think i am using the position of puntosCubo on a wrong way...
Any ideas/help. Thanks.
Because of
puntosCubo.addChild(puntosCuboTitle1)
the position of the label puntosCuboTitle1 is relative to the postion of its parent (puntosCubo)
puntosCuboTitle1.position = CGPoint(x: 0, y: 0)
makes the position of the puntosCuboTitle1 in the middle of its parent puntosCubo