looping position for SKSpriteNode - swift

I thought I had a pretty firm understanding of while loops. I want the left_spinner to move from off the screen on the right to off the screen on the left.
Then move back to off screen on the right side and back to off the screen on the left. Code wise I don't see the problem.
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var left_spinner = SKSpriteNode()
override func didMove(to view: SKView) {
left_spinner = self.childNode(withName: "left_spinner") as! SKSpriteNode
left_spinner.position = CGPoint(x: 675, y: 0)
left_spinner.run(SKAction.move(to: CGPoint(x: -675, y: 0), duration: 3.0))
goalLoop()
}
func goalLoop(){
left_spinner.run(SKAction.move(to: CGPoint(x: -675, y: 0), duration: 3.0))
while (left_spinner.position == CGPoint(x: -675, y: 0)){
left_spinner.run(SKAction.move(to: CGPoint(x: 675, y: 0), duration: 0.0))
left_spinner.run(SKAction.move(to: CGPoint(x: -675, y: 0), duration: 3.0))
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}

You don't need any synchronisation loop here, the SKAction API provide you ways to sequence actions. Just replace your whole code with :
override func didMove(to view: SKView) {
left_spinner = self.childNode(withName: "left_spinner") as! SKSpriteNode
left_spinner.position = CGPoint(x: 675, y: 0)
// Prepare base actions
let moveLeftAction = SKAction.move(to: CGPoint(x: -675, y: 0), duration: 3.0)
let moveRightAction = SKAction.move(to: CGPoint(x: 675, y: 0), duration: 3.0)
// Prepare sequencing
let loopCount = 10
let leftRightAction = SKAction.sequence([moveLeftAction, moveRightAction])
let pingPongAction = SKAction.repeat(leftRightAction, count: loopCount)
// Run final action
left_spinner.run(pingPongAction)
}

Related

How to make a sprite move up and down forever in swift SpriteKit

I am trying to make a sprite move up and down forever, I have tried using an "if statement" which checks if the position is... than it will move up again. But it does not work.
I would really appreciate some help, thanks!
Here is the code.
var Ground = SKSpriteNode()
var Ground2 = SKSpriteNode()
override func didMoveToView(view: SKView) {
Move()
}
func Move(){
let action = SKAction.moveToY(self.frame.height / 2 - 360, duration: 5.0)
Ground.runAction(SKAction.repeatActionForever(action))
let action2 = SKAction.moveToY(self.frame.height / 2 + 140, duration: 5.0)
Ground2.runAction(SKAction.repeatActionForever(action2))
}
You can use action sequence for this:
override func didMoveToView(view: SKView) {
let sprite = SKSpriteNode(color: SKColor.purpleColor(), size: CGSize(width: 100, height: 10))
sprite.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
addChild(sprite)
let moveUp = SKAction.moveByX(0, y: 200, duration: 2)
let sequence = SKAction.sequence([moveUp, moveUp.reversedAction()])
sprite.runAction(SKAction.repeatActionForever(sequence), withKey: "moving")
}

Up and down movement in sprite kit and swift?

Right now, I am creating a new game that will involve a ball that moves up and down the screen by itself without touching a button or the screen. I have been looking everywhere for a solution, but I haven't found one. I know how to make the ball move up and down in objective-c, but not in swift or spritekit. I don't know if the following code will help or not. Any solution is accepted.
class GamePlayScene: SKScene, SKPhysicsContactDelegate {
var ball = SKSpriteNode(imageNamed: "green ball.png")
override func didMoveToView(view: SKView) {
//setup scene
physicsWorld.gravity = CGVector.zeroVector
self.scene?.backgroundColor = UIColor.blackColor()
self.scene?.size = CGSize(width: 640, height: 1136)
ball.position = CGPoint (x: self.size.width * 0.5, y: self.size.width * 0.9)
ball.size = CGSize (width: 80, height: 82)
let moveBallUp = SKAction.moveToY(600, duration: 0.4)
let moveBallDown = SKAction.moveToY(293, duration: 0.4)
self.addChild(ball)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
let moveBallUp = SKAction.moveToY(600, duration: 0.4)
let moveBallDown = SKAction.moveToY(293, duration: 0.4)
if ball.position.y == 600 {
self.ball.runAction(moveBallUp)
} else {
self.ball.runAction(moveBallDown)
}
}
}
I suggest you use repeatActionForever. If you start your ball position from the bottom of the screen this sequence should work. If you want to start the ball from the top then switch the positions of the actions in moveUpAndDown with each other.
func moveSprite() {
let moveBallUp = SKAction.moveToY(600, duration: 0.4)
let moveBallDown = SKAction.moveToY(293, duration: 0.4)
let moveUpAndDown = SKAction.sequence([moveBallUp, moveBallDown])
let moveUpAndDownForever = SKAction.repeatActionForever(moveUpAndDown)
ball.runAction(moveUpAndDownForever)
}

SKShapeNode fillTexture sometimes not working with Swift

I'm trying to fill a simple SKShapeNode square specified via points with a texture. It's supposed to be pretty simple, since you can now set the .fillTexture attribute to an SKTexture of your choosing.
However, I had really inconsistent results, with a brief period of grace where the texture would actually show. Then I would try to change to another texture and the new texture wouldn't show. It seems like the size of the square may also influence whether the texture shows or not...?
GameScene.swift
import SpriteKit
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */
// Set background
let background = SKSpriteNode(imageNamed: "background")
background.position = CGPoint(x: 0, y: 0)
background.anchorPoint = CGPoint(x: 0, y: 0)
addChild(background)
// Record scene size
let w = self.size.width
let h = self.size.height
// Screen center
let center = CGPoint(x: w/2, y: h/2)
// Make points
let squarePoints = UnsafeMutablePointer<CGPoint>.alloc(5)
squarePoints[0] = CGPoint(x: -40, y: -40)
squarePoints[1] = CGPoint(x: 40, y: -40)
squarePoints[2] = CGPoint(x: 40, y: 40)
squarePoints[3] = CGPoint(x: -40, y: 40)
squarePoints[4] = CGPoint(x: -40, y: -40)
// Make the SKShapeNode
var square = SKShapeNode(points: squarePoints, count: 5)
square.strokeColor = UIColor.whiteColor()
square.lineWidth = 2.0
square.position = center
square.fillTexture = SKTexture(imageNamed: "square")
addChild(square)
// Define an action
var action = SKAction.rotateByAngle(-1.0, duration: 1.0)
square.runAction(SKAction.repeatActionForever(action))
//
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
GameViewController.swift
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = GameScene(size: view.bounds.size)
let skView = view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
scene.scaleMode = .ResizeFill
skView.presentScene(scene)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
I really have nothing else in the code. The result is a rotating empty white square with no fill on top of the background image. I'd post a screenshot, but I can't yet.
Have you tried leaving off the last point and seeing if it will connect to the origin automatically?
Try using
SKTexture(imageNamed: "square.png")
or whatever image type you are using

Camera won't follow sprite

I am trying to make a game on swift SpriteKit (an RPG more specifically). I am having an issue with making the camera follow my character. So far all that happens is the camera appears off screen and you can't even see the character. Thanks!
import SpriteKit
class GameScene: SKScene {
let cam = SKCameraNode()
let james = SKSpriteNode()
override func didMove(to view: SKView) {
self.anchorPoint = .zero
var background = SKSpriteNode(imageNamed: "image-3")
background.size = CGSize(width: 1500, height: 1000);
background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
addChild(background)
view.ignoresSiblingOrder = false
self.camera = cam
let james = Player()
james.size = CGSize(width: 40, height: 40)
james.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
james.zPosition = 1
self.addChild(james)
}
override func didSimulatePhysics() {
self.camera!.position = james.position
}
}
You need to add camera to your scene. I would recommend making camera a child of James so that it always follows James
import SpriteKit
class GameScene: SKScene {
let cam = SKCameraNode()
let james = SKSpriteNode()
override func didMove(to view: SKView) {
self.anchorPoint = .zero
var background = SKSpriteNode(imageNamed: "image-3")
background.size = CGSize(width: 1500, height: 1000);
background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
addChild(background)
view.ignoresSiblingOrder = false
self.camera = cam
let james = Player()
james.size = CGSize(width: 40, height: 40)
james.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
james.zPosition = 1
James.addChild(cam)
self.addChild(james)
}
}
I don't see any physics happening in the code you pasted. So likely didSimulatePhysics isn't getting called. try moving the self.camera!.position = james.position to the update function.
edit
a lot of trouble lately seems to stem from the fact that the scene is being paused by default. try setting...
self.isPaused = false
inside
override func didMove(to view: SKView)
and putting abreak point on
self.camera!.position = james.position
to ensure that it is getting called

My SKSpriteNode wouldn't show even though I used addChild in swift

I tried to add an image to my Game Scene, but it won't appear. Below is my code. I hope you guys can help me
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var Ground = SKSpriteNode()
var iceCream = SKSpriteNode()
override func didMove(to view: SKView) {
Ground = SKSpriteNode(imageNamed: "background")
Ground.setScale(0.5)
Ground.position = CGPoint(x: self.frame.width / 2, y: self.Ground.frame.height / 2)
self.addChild(Ground)
iceCream = SKSpriteNode(imageNamed: "VanillaIceCream")
iceCream.size = CGSize(width: 60, height: 70)
iceCream.position = CGPoint(x: self.iceCream.frame.width, y: self.frame.height / 2)
self.addChild(iceCream)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func update(_ currentTime: CFTimeInterval) {
}
}
When you set position tox: self.iceCream.frame.width
you position it using iceCream.
I believe that changing it to x: self.frame.width / 2 will solve it.
If it is not mistake and you want to set the iceCream on the left of the screen, position the sprite after adding it to self.
It's also good to set zPosition to each element, to make sure it will not hide behind the background image.
EDIT:
Here is the full code for your method (ready to copy/paste):
Ground = SKSpriteNode(imageNamed: "background")
self.addChild(Ground)
Ground.setScale(0.5)
Ground.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
Ground.zPosition = 1.0
iceCream = SKSpriteNode(imageNamed: "VanillaIceCream")
self.addChild(iceCream)
iceCream.size = CGSize(width: 60, height: 70)
iceCream.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
iceCream.zPosition = 2.0

Resources