Move nodes by x and by y at the same time - swift

I want to create a game with rectangles which move by x and by y.
My question is: Have I move the view (viewer of the player) or have I move the rectangles by x and by y at the same time?
I tried to move rectangles by x and by y at the same time, with the following code, but the rectangles move only by y.
#objc func addRects() {
rects = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: rects) as! [String]
rect = SKSpriteNode(imageNamed: rects[0])
rect.position = CGPoint(x: self.frame.width / 256 + 320, y: self.frame.height / 256)
rect.size = CGSize(width: 180, height: 120)
rect.zPosition = 1
self.addChild(rect)
moveByX = SKAction.moveTo(x: -500, duration: 2.0)
moveByY = SKAction.moveTo(y: -800, duration: 2.0)
removeRects = SKAction.removeFromParent()
wait = SKAction.wait(forDuration: 2.0)
rect.run(SKAction.sequence([moveByY,moveByY]))
rect.run(SKAction.sequence([wait,removeRects]))
}
How can I resolve this problem ?
Thank you

Don't use a sequence:
rect.run(moveByY)
rect.run(moveByX)
then it should move at the same time "moveByY" and "moveByX"
The other problem is, that you used:
rect.run(SKAction.sequence([moveByY,moveByY]))
I Hope my answer helps!

Related

I'm trying to create an infinite vertical scrolling background with SpirteKit, however I can't seem to get the code to work

The loop isn't timed correctly and resets too quickly. The looped image is also cut off showing only a fraction of it rather than the full looped background image stitched to the previous one.
I've attempted playing around with the .position, .size, and the SKAction values, but I just can't seem to tweak it to where it works properly.
func scrollingBackground() {
let BGTexture = SKTexture(imageNamed: "Background")
for i in 0 ... 1 {
let background = SKSpriteNode(texture: BGTexture)
background.zPosition = -30
background.anchorPoint = CGPoint(x: 0, y: 0)
background.size = CGSize(width: (frame.size.width), height: (frame.size.height))
background.position = CGPoint(x: 0, y: -BGTexture.size().height + (BGTexture.size().height + (BGTexture.size().height * CGFloat(i))))
addChild(background)
let scrollUp = SKAction.moveBy(x: 0, y: BGTexture.size().height, duration: 20)
let scrollReset = SKAction.moveBy(x: 0, y: -BGTexture.size().height, duration: 0)
let scrollLoop = SKAction.sequence([scrollUp, scrollReset])
let scrollForever = SKAction.repeatForever(scrollLoop)
background.run(scrollForever)
}
I hoping to get a seamless infinite background loop that runs indefinitely rather than this jumpy mess I currently have. I might add that my background image isn't originally sized perfectly to the devices, but I'm wanting to make sure my background fits to all iPhone devices.
Your first BG is at y = 0, Your second BG is at y = height. I am assuming that you are on anchor point 0.5 0.5, which would make height / 2 off screen. Your action moves BG 1 exactly to where it is off screen, then bumps back to 0. Your BG2 starts off screen, continues to move off screen, then when it hits 2 * height, resets to 1 * height, thus never appears on the screen. This is going to give the appearance of a black bar at the bottom, because BG2 is never drawn. Multiply your i by negative height instead, and that should cause the BG2 to appear on the bottom instead.
func scrollingBackground() {
let BGTexture = SKTexture(imageNamed: "Background")
for i in 0 ... 1 {
let background = SKSpriteNode(texture: BGTexture)
background.zPosition = -30
background.anchorPoint = CGPoint(x: 0, y: 0)
background.size = CGSize(width: (frame.size.width), height: (frame.size.height))
background.position = CGPoint(x: 0, y: -BGTexture.size().height + (BGTexture.size().height + (-BGTexture.size().height * CGFloat(i))))
addChild(background)
let scrollUp = SKAction.moveBy(x: 0, y: BGTexture.size().height, duration: 20)
let scrollReset = SKAction.moveBy(x: 0, y: -BGTexture.size().height, duration: 0)
let scrollLoop = SKAction.sequence([scrollUp, scrollReset])
let scrollForever = SKAction.repeatForever(scrollLoop)
background.run(scrollForever)
}

Sprite positioning at wrong points in y axis

so I know this is a dumb question, but maybe it'll help other people like me out too. Basically, I'm making a sprite appear at the top of the screen and then move to the bottom but in a random x position. There's nothing wrong with moving to the random x position, the problem is that it doesn't start out at the top of the screen. Here is my code:
let sprite = SKSpriteNode(imageNamed: "comet")
sprite.size = CGSize(width: 150, height: 100)
sprite.position = CGPoint(x: self.frame.size.width/2, y: 0)
sprite.zPosition = 100
self.addChild(sprite) `
let randomNum = CGPoint(x:Int (arc4random() % 1000), y: 1)
let actionMove = SKAction.moveTo(randomNum, duration: 1)
let actionComet = SKAction(actionMove)
sprite.runAction(actionComet)
Any help is appreciated.
You are placing your sprite at location (0,0) which is left bottom of the screen. If you want to place the sprite at the top use:
sprite.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height + sprite.size.height / 2.0)

How to connect two SCNSpheres in 3D space using Bezier path in Swift?

I have the following code:
func createScene(){
count += 1
let sphereGeom = SCNSphere(radius: 1.5)
sphereGeom.firstMaterial?.diffuse.contents = UIColor.redColor()
let path = UIBezierPath()
path.moveToPoint(CGPoint(x: 0, y: 0))
let radius = 3.0
var radians = Double(0)
var yPosition = Float(5.4)
while count <= 20 {
if radians >= 2{
radians -= 2
}
let sphereNode = SCNNode(geometry: sphereGeom)
let angle = Double(radians * M_PI)
let xPosition = Float(radius * cos(angle))
let zPosition = Float(radius * sin(angle))
sphereNode.position = SCNVector3(xPosition, yPosition, zPosition)
let cgX = CGFloat(xPosition)
let cgY = CGFloat(yPosition)
path.addQuadCurveToPoint(CGPoint(x: cgX, y: cgY), controlPoint: CGPoint(x: (cgX / 2), y: (cgY / 2)))
path.addLineToPoint(CGPoint(x: (cgX - (cgX * 0.01)), y: cgY))
path.addQuadCurveToPoint(CGPoint(x: 1, y: 0), controlPoint: CGPoint(x: (cgX / 2), y: ((cgY / 2) - (cgY * 0.01))))
let shape = SCNShape(path: path, extrusionDepth: 3.0)
shape.firstMaterial?.diffuse.contents = UIColor.blueColor()
let shapeNode = SCNNode(geometry: shape)
shapeNode.eulerAngles.y = Float(-M_PI_4)
self.rootNode.addChildNode(shapeNode)
count += 1
radians += 0.5556
yPosition -= 1.35
self.rootNode.addChildNode(sphereNode)
}
I want to add a Bezier path connecting each sphere to the next one, creating a spiral going down the helix. For some reason, when I add this code, the shape doesn't even appear. But when I use larger x and y values, I see the path fine, but it is no way oriented to the size of the spheres. I don't understand why it disappears when I try to make it smaller.
Your SCNShape doesn't ever get extruded. Per Apple doc,
An extrusion depth of zero creates a flat, one-sided shape.
With larger X/Y values your flat shape happens to become visible. You can't build a 3D helix with SCNShape, though: the start and end planes of the extrusion are parallel.
You'll have to use custom geometry, or approximate your helix with a series of elongated SCNBox nodes. And I bet someone out there knows how to do this with a shader.

Obstacle random gap not working [SpriteKit] [Swift]

I have a problem in my code. When I run the game, I have two obstacles (one on the left and one on the right). I coded a gap between each obstacle and it has been working. I have a problem where the gap sometimes spawns off of the screen where the player cannot get to. How can I fix this?
Here's my code:
let gapWidth = square.size.width * 1.5
var movementAmount = arc4random() % UInt32(self.frame.size.width/2)
var obstacleOffset = CGFloat(movementAmount) - self.frame.size.width / 2
var obstacle1 = SKSpriteNode(imageNamed: "Obstacle")
obstacle1.zPosition = 30
obstacle1.size = CGSize(width: self.frame.size.width, height: 300)
obstacle1.position = CGPoint(x: CGRectGetMidX(self.frame) + obstacle1.size.width / 2 + gapWidth / 2 + obstacleOffset, y: CGRectGetMidY(self.frame))
self.addChild(obstacle1)
var obstacle2 = SKSpriteNode(imageNamed: "Obstacle")
obstacle2.zPosition = 30
obstacle2.size = CGSize(width: self.frame.size.width, height: 300)
obstacle2.position = CGPoint(x: CGRectGetMidX(self.frame) - obstacle2.size.width / 2 - gapWidth / 2 + obstacleOffset, y: CGRectGetMidY(self.frame))
self.addChild(obstacle2)
You need to make sure the values of the random positions will always be on the screen. You can do that by using code similar to this:
var height = UInt32(self.frame.size.height)
var randomYPos = CGFloat(arc4random_uniform(UInt32(height)))
You can do the same for the random x value, just use the screen width. You only need to do this for obstacle 1, then set the position of obstacle 2 relative to obstacle 1.

Swift - sprite kit - make SKPhysicsJointPin have less motion

I'm trying to create a snake with multiple body parts that moves left and right. Im using a pin, but upon the snake stopping, the body keeps moving and doesn't stop. I've messed around with the max and min angles, and the torque, but nothing seems to work. Should I use a different type of joint?
Sorry i cant log into my other account, but heres the code. Basically the second part just wobbles a lot. I wish to add 7-8 parts, but they just keep on wobbling, especially after moving "head". i would like a fluid "swoop" motion when i move the snake.
self.physicsWorld.gravity = CGVectorMake(0, -100)
self.physicsWorld.contactDelegate = self
head.size = CGSize(width: 25,height: 25)
head.physicsBody = SKPhysicsBody(texture: head.texture, size: head.size)
head.position = CGPointMake(100,400)
head.anchorPoint = CGPoint(x: 0.5, y: 1)
head.physicsBody!.dynamic = false
head.zPosition = 3
self.addChild(head)
var p1 = SKSpriteNode(imageNamed: "snakeBodyPart.png")
p1.size = CGSize(width: 25,height: 25)
p1.physicsBody = SKPhysicsBody(texture: p1.texture, size: p1.size)
p1.position = CGPointMake(100,380)
p1.anchorPoint = CGPoint(x: 0.5, y: 1)
p1.physicsBody!.dynamic = true
addChild(p1)
var joint = SKPhysicsJointPin.jointWithBodyA(head.physicsBody, bodyB: p1.physicsBody, anchor: CGPoint(x: CGRectGetMidX(head.frame), y: CGRectGetMinY(head.frame) + 10))
joint.upperAngleLimit = 0.1
joint.rotationSpeed = 0.1
self.physicsWorld.addJoint(joint)