Spawning down the middle of the screen - swift

Is there a way to spawn an SKSpriteNode continuously down the middle of the screen. For example I have a circle that I want to spawn in the middle of the x axis and then for that node to spawn all the way down the screen?
These circles are different colours so when they spawn is there a way to randomly change the the colour of the circles when they are spawned?
I understand I can spawn them individually but is there a better way? ( I am using SpriteKit on swift)

You need to learn some basics bruh.
Learn about For loops, arrays and arc4random.
var circleDiameter: CGFloat = 80.0
for var y = self.frame.height; y > 0; y = y - circleDiameter
{
let coloroptions = [UIColor.greenColor(), UIColor.blueColor(), UIColor.redColor()]
let randomNumber = Int(arc4random_uniform(UInt32(coloroptions.count)))
let color = coloroptions[randomNumber]
var rect = CGRectMake(self.frame.width / 2, y, circleDiameter, circleDiameter)
var circle = SKShapeNode()
circle.path = UIBezierPath(ovalInRect: rect).CGPath
circle.fillColor = color
circle.lineWidth = 0
circle.physicsBody = SKPhysicsBody(circleOfRadius: circle.frame.width / 2)
circle.physicsBody?.dynamic = false
self.addChild(circle)
}

Related

SpriteKit Inelastic Collision Reducing Velocity

I'm building a pong/breaker game with a ball and non-static blocks. I'd like the ball to never stop moving, but whenever it hits a block it loses velocity.
I have the restitusion = 1 for all sprites involved, I've tried setting the mass equal to each other and the density and the friction = 0. But, the ball still loses velocity on a bounce.
When the ball hits a block I'm removing it in the didBegin(contact:) function. I've also tried delaying the removal and it didn't help.
I'd like for the ball to have a constant velocity, but still be able to interact with the blocks as later I'd like to add blocks that can be hit without immediately being broken. So, the blocks can't be static but the ball needs to have a constant velocity.
My code for creating the ball node:
func ballNode(_ position: CGPoint?) -> SKSpriteNode {
let node = SKSpriteNode()
node.position = position == nil ? CGPoint(x: size.width/2, y: 100) : position!
node.size = CGSize(width: 17, height: 17)
//background
let background = SKShapeNode(circleOfRadius: 8.5)
background.fillColor = UIColor.white
node.addChild(background)
//physics
node.physicsBody = SKPhysicsBody(circleOfRadius: 8.5)
node.physicsBody?.allowsRotation = true
node.physicsBody?.friction = 0
node.physicsBody?.restitution = 1
node.physicsBody?.linearDamping = 0
node.physicsBody?.angularDamping = 0
node.physicsBody?.categoryBitMask = BallCategory
node.physicsBody?.contactTestBitMask = AddBlockBorderCategory | PaddleCategory
node.physicsBody?.collisionBitMask = PaddleCategory | BlockCategory | BorderCategory
return node
}
My code for creating the block node:
func createBlockNode() -> BlockNode {
let width = (size.width-CGFloat(6*layout[0].count))/CGFloat(layout[0].count)
let height = width*0.5
let nodeSize = CGSize(width: width, height: height)
let node = BlockNode(texture: nil, size: nodeSize)
let background = SKShapeNode(rectOf: nodeSize)
background.fillColor = .darkGray
background.strokeColor = .lightGray
//physics
node.physicsBody = SKPhysicsBody(rectangleOf: nodeSize)
node.physicsBody?.restitution = 1
node.physicsBody?.allowsRotation = true
node.physicsBody?.friction = 0
node.physicsBody?.categoryBitMask = BlockCategory
node.physicsBody?.contactTestBitMask = BallCategory
node.addChild(background)
return node
}
And a screen recording:
screen recording of the ball losing velocity
I'm starting the ball using this:
ball!.physicsBody?.applyForce(CGVector(dx: 0, dy: 50))

How do you pass through a Spritekit joint anchor?

I have tree that is built out of a series of joints. The anchor is the base/stump of the tree. My hero is currently not able to walk through the anchor. Setting collisionBitMask = 0 isn't working for the anchor but that approach does work for the individual joint segments.
So, essentially I just want to avoid this collision. Here is the code:
//code for anchor
let chunkHolder = SKSpriteNode(imageNamed: ImageName.ChunkHolder)
chunkHolder.position = anchorPoint
chunkHolder.physicsBody = SKPhysicsBody(circleOfRadius: chunkHolder.size.width / 2)
chunkHolder.physicsBody?.isDynamic = false
chunkHolder.physicsBody?.categoryBitMask = PhysicsCategory.chunkAnchor.rawValue
chunkHolder.physicsBody?.collisionBitMask = 0
addChild(chunkHolder)
//individual tree segements where hero correctly passes through:
for i in 0..<length {
let treeSegment = SKSpriteNode(imageNamed: ImageName.ChunkTexture)
let offset = treeSegment.size.height * CGFloat(i + 1)
treeSegment.position = CGPoint(x: anchorPoint.x, y: anchorPoint.y - offset)
treeSegment.name = "tree" + String(i)
treeSegments.append(treeSegment)
addChild(treeSegment)
treeSegment.physicsBody = SKPhysicsBody(rectangleOf: treeSegment.size)
treeSegment.physicsBody?.collisionBitMask = 0
}
//joints
for i in 1..<length {
let nodeA = treeSegments[i - 1]
let nodeB = treeSegments[i]
let joint = SKPhysicsJointPin.joint(withBodyA: nodeA.physicsBody!, bodyB: nodeB.physicsBody!, anchor: CGPoint(x: nodeA.frame.midX, y: nodeA.frame.minY))
scene.physicsWorld.add(joint)
}
//for reference here is Hero's physics body:
self.physicsBody?.categoryBitMask = PhysicsCategory.hero.rawValue
self.physicsBody?.contactTestBitMask = PhysicsCategory.ground.rawValue
Also setting hero's collisionBitMask to 0 will not currently help because then hero will also fall through the ground / floor.
This was resolved by also setting the categoryBitMask to 0.
chunkHolder.physicsBody?.categoryBitMask = 0
chunkHolder.physicsBody?.collisionBitMask = 0

SpriteKit Spin circle on center Swift

I want to spint a circular node on its center. I have been trying to following:
var earthBase = SKSpriteNode(imageNamed: "earthBase")
earthBase.position = CGPoint(x: 667, y: 20)
earthBase.physicsBody = SKPhysicsBody(texture: earthBase.texture!, size: earthBase.size)
earthBase.physicsBody!.allowsRotation = true
earthBase.physicsBody!.linearDamping = 1
earthBase.physicsBody!.affectedByGravity = false
earthBase.physicsBody!.isDynamic = false
earthBase.name = "earthBase"
earthBase.zPosition = 9
addChild(earthBase)
let spin = SKAction.rotate(byAngle: CGFloat.pi, duration: 60)
let spinForever = SKAction.repeatForever(spin)
earthBase.run(spinForever)
When I do this it spins like the blue circle picture below but I want to to spin on its center like the green circle. I have tried changing the anchor point (none in the code above / default) but this will just move it farther away from the red dot.
Any thoughts?

How do I rotate sprites on a perimeter of a circle towards the center?

I have n sprites on the perimeter of a circle:
let radius = 100
let n = 10
let parentNode = SKSpriteNode(color: NSColor.yellowColor(), size: CGSizeMake(CGFloat(radius), CGFloat(radius)))
parentNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
parentNode.zPosition = 1.5
for sprite in 0...n {
let aSprite = SKSpriteNode(imageNamed: "image.png")
aSprite.setScale(0.15)
aSprite.name = "sprite"+String(sprite)
let theta = Float(Double(sprite) * ((2 * M_PI)/n))
let x = radius * Double(cosf(theta))
let y = radius * Double(sinf(theta))
aSprite.position = CGPointMake(CGFloat(x), CGFloat(y))
parentNode.addChild(aSprite)
}
I want to rotate each sprite towards the center of the circle:
CGPoint(CGRectGetMidX(parentNode.frame),CGRectGetMidY(parentNode.frame))
I tried using atan2 to accomplish this, but it didn't work:
aSprite.zRotation = atan2(CGRectGetMidY(parentNode.frame)-aSprite.position.y, CGRectGetMidX(parentNode.frame) - aSprite.position.x)

Swinging Beam that Doesn't Stop Swinging in Swift SpriteKit

I have a ios 9 spritekit game. I am adding a i-beam or a wrecking ball that should swing from a jointed rope like a pendulum. My game requires gravity and I want the beam to react to gravity and sprites that jump on the beam or hit the beam from below. When I use the following code, the beam eventually slows down and comes to rest without any interaction with other sprites. The top node in the jointed node is fixed (i.e., modeling attachment to a crane or building) I start the beam swinging by applying an impulse on the bottom node in the jointed node. I have set the friction, linear dampening, and angular dampening to 0.
What I need the beam to do prior to interacting with any sprites is to swing back and forth where the maximum height on the left swing and right swing is nearly the same throughout time. I want the beam or wrecking ball to act like its swinging from a frictionless pivot. The beam or ball doesn't go in a full circle, so I cannot use a constant angular velocity.
I tried something similar to:
Constant speed orbit around point with SKNode but neither the linear nor angular velocity is constant after the initial impulse as the beam or ball will arc up, slow down, stop at the top of the arc, and then circle back in the other direction.
let (actionSceneObjectNode, jointArray) = ActionSceneObject.createActionJointedSceneObjectAtPosition(CGPoint(x: positionX, y: positionY), ofType: actionSceneObject.type!, withImage: actionSceneObject.imageName, withActionDirection: actionSceneObject.imageDirection)
foregroundNode.addChild(actionSceneObjectNode)
if let bottomNode = actionSceneObjectNode.childNodeWithName("bottomObject") {
bottomNode.physicsBody?.applyImpulse(CGVector(dx: 50000.0, dy: 0))
}
// add the joints
for joint in jointArray {
self.physicsWorld.addJoint(joint)
}
Function
class func createActionJointedSceneObjectAtPosition(position: CGPoint, ofType type: ActionSceneObjectType, withImage imageName: String, withActionDirection actionDirection: DirectionValue) -> (ActionSceneObjectNode, [SKPhysicsJoint]) {
let node = ActionSceneObjectNode()
node.position = position
node.name = SceneObjectType.Action.rawValue
node.actionType = type
node.actionDirection = actionDirection
var jointArray = [SKPhysicsJoint]()
var sprite: SKSpriteNode
////////
// adapted from https://stackoverflow.com/questions/20811931/how-to-create-a-rope-in-spritekit
let countJointElements:Int = 3
let texture = SKTexture(imageNamed: "Rope.png")
//let textureSize = CGSize(width: texture.size().width*SceneObjectSizeScale.ActionSceneObject, height: texture.size().height*SceneObjectSizeScale.ActionSceneObject)
let topAnchor = SKSpriteNode(texture: texture, size: texture.size())
topAnchor.name = "topAnchor"
//topAnchor.position = CGPointMake(position.x, position.y) // the node holds the joint start position
topAnchor.physicsBody = SKPhysicsBody(rectangleOfSize: texture.size())
topAnchor.physicsBody?.categoryBitMask = PhysicsCategoryBitmask.None
topAnchor.physicsBody?.affectedByGravity = false
topAnchor.physicsBody?.friction = 0.0
topAnchor.physicsBody?.restitution = 1.0
topAnchor.physicsBody?.linearDamping = 0.0
topAnchor.physicsBody?.angularDamping = 0.0
topAnchor.physicsBody?.mass = 10.0
node.addChild(topAnchor)
// by default, the joints build top to bottom
for index in 0 ..< countJointElements {
let item = SKSpriteNode(texture: texture, size: texture.size())
item.name = "ropeitem_" + String(index)
item.position = CGPointMake(0, 0 - CGFloat(index+1) * item.size.height)
item.physicsBody = SKPhysicsBody(rectangleOfSize: texture.size())
item.physicsBody?.categoryBitMask = PhysicsCategoryBitmask.None
item.physicsBody?.affectedByGravity = true
item.physicsBody?.friction = 0.0
item.physicsBody?.restitution = 1.0
item.physicsBody?.linearDamping = 0.0
item.physicsBody?.angularDamping = 0.0
item.physicsBody?.mass = 10.0
node.addChild(item)
var bodyA = SKPhysicsBody()
if (index == 0)
{
bodyA = topAnchor.physicsBody!;
}
else
{
let nameString = "ropeitem_" + String(index - 1)
let nodeItem = node.childNodeWithName(nameString) as! SKSpriteNode
bodyA = nodeItem.physicsBody!
}
// needs to in terms of the physics world - the item position in the node is already negative
let joint = SKPhysicsJointPin.jointWithBodyA(bodyA, bodyB: item.physicsBody!, anchor: CGPointMake(position.x, position.y + item.position.y + item.size.height/2))
jointArray.append(joint)
}
let nameString = NSString(format: "ropeitem_%d", countJointElements - 1)
let lastLinkItem = node.childNodeWithName(nameString as String)
let bottomObject = SKSpriteNode(imageNamed: "I-Beam.png")
bottomObject.name = "bottomObject"
bottomObject.setScale(SceneObjectSizeScale.Platform)
bottomObject.position = CGPointMake(0, 0 + lastLinkItem!.position.y - lastLinkItem!.frame.size.height/2.0 - bottomObject.frame.size.height/2.0)
bottomObject.physicsBody = SKPhysicsBody(rectangleOfSize: bottomObject.size)
bottomObject.physicsBody?.categoryBitMask = PhysicsCategoryBitmask.Platform
bottomObject.physicsBody?.affectedByGravity = true
bottomObject.physicsBody?.friction = 0.0
//bottomObject.physicsBody?.restitution = 1.0
bottomObject.physicsBody?.linearDamping = 0.0
bottomObject.physicsBody?.angularDamping = 0.0
bottomObject.physicsBody?.mass = 500.0
node.addChild(bottomObject)
let jointLast = SKPhysicsJointFixed.jointWithBodyA(lastLinkItem!.physicsBody!, bodyB: bottomObject.physicsBody!, anchor: CGPointMake(position.x, position.y + bottomObject.position.y + bottomObject.frame.size.height/2.0))
jointArray.append(jointLast)
///////
///////
sprite = SKSpriteNode(imageNamed: imageName)
//sprite.setScale(SceneObjectSizeScale.ActionSceneObject)
node.sprite = sprite
//node.addChild(sprite)
node.physicsBody = SKPhysicsBody(texture: texture, size: sprite.size)
node.physicsBody!.categoryBitMask = PhysicsCategoryBitmask.None
switch actionDirection {
case .Left:
node.sprite.zRotation = CGFloat(M_PI_2)
case .Right:
node.sprite.zRotation = CGFloat(-M_PI_2)
case .Down:
node.sprite.zRotation = CGFloat(M_PI)
case .Up, .Unknown:
break
}
node.physicsBody?.dynamic = true
node.physicsBody?.restitution = 0.0 // bounciness
node.physicsBody?.categoryBitMask = PhysicsCategoryBitmask.ActionSceneObject
node.physicsBody?.collisionBitMask = 0
return (node, jointArray)
}