Sprite positioning at wrong points in y axis - swift

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)

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)
}

Move nodes by x and by y at the same time

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!

SKSpriteNode animation to appear bottom-up

According to the following code, i am displaying a mountain (hill) in the scene at x = 400 and y = self.frame.height / 2
However, I want the hill to appear from bottom-up (from below the scene) like an animation. How can I code this ?
let hill = SKSpriteNode(imageNamed: "hill")
hill.position = CGPoint(x: 400, y: self.frame.height / 2 )
hill.setScale(1)
hill.physicsBody = SKPhysicsBody(rectangleOfSize: hill.size)
hill.physicsBody?.categoryBitMask = 1
hill.physicsBody?.collisionBitMask = 2
self.addChild(hill)
To create an animation that makes the sprite slide up from "under" the scene, do this:
Set its initial position to below the scene:
hill.position = CGPoint(x: 400, y: self.frame.height / CGFloat(2) - self.frame.height)
Note: - self.frame.height is used to place the node 1 full frame height below the desired location
Then start an action that moves it up to its desired position in didMoveToView, or wherever you want the animation to start:
let moveUpAnimation = SKAction.move(to: CGPoint(x: 400, y: self.frame.height / CGFloat(2)), duration: 0.75)
hill.run(moveUpAnimation)
This example creates an action that takes 0.75 seconds to move the sprite up one full frame height. You can set its initial position to anywhere below the visible scene to create this effect, and change the duration to any desired speed.

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.

How can I make the player not able to go through certain boundaries? (off-screen)

Hey so I was watching Ray Wenderlich's tutorial on How to Make a Game Like Mega Jump! and tried to create a similar project on my own. So during the tutorial you set the player to be able to go off the screen whenever you tilt the device.
override func didSimulatePhysics() {
player.physicsBody?.velocity = CGVector(dx: xAcceleration * 400.0, dy: player.physicsBody!.velocity.dy)
if player.position.x < -20.0 {
player.position = CGPoint(x: self.size.width + 20.0, y: player.position.y)
} else if (player.position.x > self.size.width + 20.0) {
player.position = CGPoint(x: -20.0, y: player.position.y)
}
return;
}
This is the code I have which makes the player go off the screen. How can I do this but for the player NOT being able to go off the screen? For example if you tilt your device all the way to the right make the player to stay on the right side until you move it the other way! Thank you in advance.
Currently you check if the player is out of screen (more then 20px) and then set his position to the other side, 20px out of the screen.
But you want to stop the player at 0px and your screen width. You can do it like this:
if player.position.x <= 0.0 {
player.position = CGPoint(x: 0.0, y: player.position.y)
} else if (player.position.x >= self.size.width) {
player.position = CGPoint(x: self.size.width, y: player.position.y)
}
This just set's the position of the player to 0.0 if he's moving out to the left, or your screen width, if he's moving out to the right.
The current code "loops around" so moving all the way to the left means you end up on the right.
Just change the coordinates in the if blocks to pin to the edges. Something like this:
if player.position.x < -20.0 {
player.position = CGPoint(x: -20.0, y: player.position.y)
} else if (player.position.x > self.size.width + 20.0) {
player.position = CGPoint(x: self.size.width + 20.0, y: player.position.y)
}
Notice that if the player is beyond the left edge (x < -20) then you just leave the x-position at -20. Similar thing on the right edge.
You'll have to try this out to see how it works with the physics and acceleration but that should be the general idea.