Use PhysicsBody with SKShapenode line. Swift, iOS, SpriteKit - ios

I need to add simple line using ShapeBody to interact with.
I'am trying code below, by Xcode gives me next response:
PhysicsBody: Could not create physics body.
let testPath = UIBezierPath()
testPath.move(to: CGPoint(x:-100, y: 200))
testPath.addLine(to: CGPoint(x:100, y: 200))
let testShape = SKShapeNode()
testShape.path = testPath.cgPath
testShape.position = CGPoint(x:0, y:250)
testShape.zPosition = 5
testShape.lineWidth = 5
testShape.strokeColor = .red
testShape.physicsBody = SKPhysicsBody(polygonFrom: testPath.cgPath)

Used edgeChainFrom instead of polygonFrom, and it works!
testShape.physicsBody = SKPhysicsBody(edgeChainFrom: testPath.cgPath)

A path cannot intersect any of its lines with a SKPhysicsBody, your line needs to be a thin rectangle
let testPath = UIBezierPath()
testPath.move(to: CGPoint(x:-100, y: 200))
testPath.addLine(to: CGPoint(x:100, y: 200))
testPath.addLine(to: CGPoint(x:100, y: 201))
testPath.addLine(to: CGPoint(x:-100, y: 201))
testPath.close()
let testShape = SKShapeNode()
testShape.path = testPath.cgPath
testShape.position = CGPoint(x:0, y:250)
testShape.zPosition = 5
testShape.lineWidth = 5
testShape.strokeColor = .red
testShape.physicsBody = SKPhysicsBody(polygonFrom: testPath.cgPath)

Related

Slice an SKShapeNode into two

Is there an easy method to slice an SKShapeNode into 2 seperate SKShapeNodes?
In this example I have created an SKShapeNode using a closed bezier path as well as a single line.
let squareShape = SKShapeNode()
squareShape.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 256, height: 256), cornerRadius: 10).cgPath
squareShape.position = CGPoint(x: frame.midX-128, y: frame.midY+200-128)
squareShape.fillColor = UIColor.green
squareShape.strokeColor = UIColor.blue
squareShape.lineWidth = 2
addChild(squareShape)
let lineShape1 = SKShapeNode()
let line1 = UIBezierPath()
line1.move(to: CGPoint(x: -200, y: 300))
line1.addLine(to: CGPoint(x: 200, y: 100))
lineShape1.path = line1.cgPath
lineShape1.strokeColor = UIColor.white
lineShape1.lineWidth = 2
addChild(lineShape1)
How can I transform the existing SKShapeNode into 2 seperate SKShapeNodes separated by the line?
I need to be able to do this with varying line positions and shapes types (or even with multiple shapes and a single line).
Thanks

How Can I Create a Dashed Line SKShapeNode from a UIBezierPath, Using Swift?

All of the explanations I've found seem to say the same thing. I can't figure out why this isn't working.
var linePath = UIBezierPath()
linePath.move(to: CGPoint(x: 50, y: 50))
linePath.addLine(to: CGPoint(x: 100, y: 100))
var pattern : [CGFloat] = [10.0, 10.0]
linePath.setLineDash(pattern, count: pattern.count, phase: 0)
linePath.lineWidth = 10
linePath.lineCapStyle = .round
let shape = SKShapeNode()
shape.path = linePath.cgPath
shape.strokeColor = UIColor.white
self.addChild(shape)
This code successfully draws a line but shape does not inherit the dashed properties of linePath, including even the width. Any ideas?
let linePath = UIBezierPath()
linePath.move(to: CGPoint(x: 50, y: 50))
linePath.addLine(to: CGPoint(x: 100, y: 100))
var pattern: [CGFloat] = [10.0, 10.0]
let dashed = CGPathCreateCopyByDashingPath (linePath.CGPath, nil, 0, pattern, 2)
var shape = SKShapeNode(path: dashed)
shape.strokeColor = UIColor.white
self.addChild(shape)
NOTE: In Swift 3 CGPathCreateCopyByDashingPath has been replaced by path.copy(dashingWithPhase:lengths:)
e.g.
let dashed = SKShapeNode(path: linePath.cgPath.copy(dashingWithPhase: 2, lengths: pattern))

Setting line cap style doesn't work UIBezierPath

This is my code:
let cross = UIBezierPath()
cross.move(to: CGPoint(x: skull.bounds.maxX, y: skull.bounds.minY))
cross.addLine(to: CGPoint(x: skull.bounds.minX, y: skull.bounds.maxY))
cross.close()
UIColor.red.set()
cross.lineWidth = 3.0
cross.lineCapStyle = .round
cross.stroke()
I want to round the end of the line, but it's still square, how should I do it?
just tested on PlayGround, Hope it will help
let cross = UIBezierPath()
cross.moveToPoint(CGPoint(x: 10, y: 100)) // your point
cross.addLineToPoint(CGPoint(x: 100, y: 10)) // your point
cross.closePath()
cross.lineWidth = 23.0
cross.lineJoinStyle = .Round
cross.stroke()
Swift 5.0
let cross = UIBezierPath()
cross.move(to: CGPoint(x: 10, y: 100)) // your point
cross.addLine(to: CGPoint(x: 100, y: 10)) // your point
cross.close()
cross.lineWidth = 23.0
cross.lineJoinStyle = .round
cross.stroke()
Result
The line cap style configures the style of the line ending. You have closed path, i.e. you have no line ending.
You are probably looking for the line join style, which affects all "corners" or "vertexes" of a path.
Alternatively, if you just want a straight, don't close the path. Otherwise you get two line segments: one from the starting point to the end point and another one back to the start.
Swift 4.1 update to Umair Afzal's code:
let cross = UIBezierPath()
cross.move(to: CGPoint(x: 10, y: 100)) // your point
cross.addLine(to: CGPoint(x: 100, y: 10)) // your point
cross.lineWidth = 12
cross.lineCapStyle = .round
cross.stroke()

How to create a node in another node

I have a circle, an SKShapeNode, and I want to create a child node inside it. How I can do this?
func AddCircle() {
Circle = SKShapeNode(circleOfRadius: circleRadius)
Circle.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
Circle.strokeColor = UIColor.whiteColor()
self.addChild(Circle)
Circle.addChild(BooCharacter)
}
Main Character:
func AddCharacter() {
BooCharacter.size = CGSize(width: 30, height: 30)
BooCharacter.anchorPoint.y = 0
BooCharacter.zRotation = CGFloat(-M_PI_2)
BooCharacter.position.y += circleRadius
}
I want to create an object in my circle but I don't know how you write it.
For example, I've tried to add a rect inside of my circle:
func AddRect() {
Rect = SKShapeNode()
Rect.path = UIBezierPath(roundedRect: CGRect(x:0, y: 250, width: 256, height: 256), cornerRadius: 64).CGPath
Rect.fillColor = UIColor.whiteColor()
}
func AddCircle() {
Circle = SKShapeNode(circleOfRadius: circleRadius)
Circle.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
Circle.strokeColor = UIColor.whiteColor()
self.addChild(Circle)
Circle.addChild(BooCharacter)
Circle.addChild(Rect)
but it's still not working.
I want to create and add triangles inside of my circle like this
You're doing exactly the right thing, although I don't see where BooCharacter is being created – are you definitely creating that somewhere? Using addChild() to add a node to your scene, or to add one node to another node, is correct, and should work for all types of SKNode.

Switching sprite positions with each other

I have 6 sprites that I want to switch positions with each other every time a function is called. I also don't want any two (or more) sprites to ever be in the same position. I tried using this function but it didn't do anything.
func newPositionPipe() {
let pipePosition1 = CGPoint(x: 63, y: 1275)
let pipePosition2 = CGPoint(x: 188, y: 1275)
let pipePosition3 = CGPoint(x: 315, y: 1275)
let pipePosition4 = CGPoint(x: 443, y: 1275)
let pipePosition5 = CGPoint(x: 565, y: 1275)
let pipePosition6 = CGPoint(x: 687, y: 1275)
var randomNumberBetween0And6 = Int(arc4random_uniform(6))
let pipePositions = [pipePosition1, pipePosition2, pipePosition3, pipePosition4, pipePosition5, pipePosition6]
greenPipe.position = pipePositions[randomNumberBetween0And6]
redPipe.position = pipePositions[randomNumberBetween0And6]
greenPipe.position = pipePositions[randomNumberBetween0And6]
yellowPipe.position = pipePositions[randomNumberBetween0And6]
greyPipe.position = pipePositions[randomNumberBetween0And6]
purplePipe.position = pipePositions[randomNumberBetween0And6]
}
The way you have it setup now will make every pipe position the same because it will be referencing the same random index number you've generated with randomNumberBetween0And6. Put this in a loop and generate a new random number each time. You could also use a Tuple to swap the values.
(greenPipe.position, redPipe.position) = (redPipe.position, greenPipe.position)

Resources