Moving an object across the screen at a certain speed.(Sprite Kit) - swift

I have an object that needs to move up and down the screen. When you first click it moves down the screen to an endpoint with a duration of 3 seconds. You can click at anytime to stop it from moving down and make it start moving up to a different endpoint, again at a duration of 3 seconds. The problem with doing it this way is if you click to move the object down but then immediately click again to move it up, the object moves up but at a very slow rate because it has a duration of 3 seconds. (I hope this makes sense) So what I want is to stop using the duration to set the pace/speed at which the object moves. Is there a way to say move to point x.y at blank speed? Thank you. (No matter where the object is and has to move to I want it to always move at the same pace.)
This is what I use to move the object right now:
func moveObject(){
let endpoint = CGPoint(x: self.size.width / 2 , y: self.size.height / 1.8888888888 )
let moveObject = SKAction.moveTo(endpoint, duration: 3.0 )
let moveObjectSequence = SKAction.sequence([moveLine])
Object.runAction(moveLineSequence)
}
Code after corrections:
func dropLine(){
if hookNumber == 1{
let endpoint = CGPoint(x: self.size.width / 2 , y: self.size.height / 1.8888888888 )
let moveLine = SKAction.moveTo(endpoint, duration: getDuration(fishLine.position,pointB:endpoint,speed:300.0))
let moveLineSequence = SKAction.sequence([moveLine])
fishLine.runAction(moveLineSequence)
}
}
func dropHook(){
if hookNumber == 1{
let endpoint = CGPoint(x: self.size.width / 2 , y: self.size.height - 2030)
let moveLine = SKAction.moveTo(endpoint, duration: getDuration(fishHook.position,pointB:endpoint,speed:300.0))
let moveLineSequence = SKAction.sequence([moveLine])
fishHook.runAction(moveLineSequence)
hookNumber = 2
}
}
func raiseLine(){
if hookNumber == 2{
let endpoint = CGPoint(x: self.size.width / 2 , y: 3050 )
let moveLine = SKAction.moveTo(endpoint, duration: getDuration(fishLine.position,pointB:endpoint,speed:300.0))
let moveLineSequence = SKAction.sequence([moveLine])
fishLine.runAction(moveLineSequence)
}
}
func raiseHook(){
if hookNumber == 2{
let endpoint = CGPoint(x: self.size.width / 2 , y: self.size.height - 3 )
let moveLine = SKAction.moveTo(endpoint, duration: getDuration(fishHook.position,pointB:endpoint,speed:300.0))
let moveLineSequence = SKAction.sequence([moveLine])
fishHook.runAction(moveLineSequence)
}
}

I think you could revise your approach based on the calculation speed.
So, if you know your speed, you can calculate how many time a node takes to arrive to a point and change your speed to a reasonable value.
// #-#-#-#-#-#-#-#-#-#-#-#-#-#-#
//MARK: - Calculate action duration btw two points and speed
// #-#-#-#-#-#-#-#-#-#-#-#-#-#-#
func getDuration(pointA:CGPoint,pointB:CGPoint,speed:CGFloat)->NSTimeInterval {
let xDist = (pointB.x - pointA.x)
let yDist = (pointB.y - pointA.y)
let distance = sqrt((xDist * xDist) + (yDist * yDist));
let duration : NSTimeInterval = NSTimeInterval(distance/speed)
return duration
}
Suppose you have your node with a speed of 150.0
Your move will be:
let moveObject = SKAction.moveTo(endpoint, duration: getDuration(node.position,pointB:endpoint,speed:150.0))
With this approach you speed dont' change and you don't have this disagreeable slowness.
P.S. Don't forgot to change the uppercase to your properties: in swift is a bad attitude, use object instead of Object.

Related

My SKSpriteNode speed values are not updating properly

What I'm trying to do is update my SKSpriteNodes so I can change their scrolling speeds dynamically, however they aren't really working consistently. I didn't include the code, but I have another method with a switch case that sets the value of platformSpeed whenever the state is changed (in this case, the switch case is changed with UIButtons). In my code I have an SKSpriteNode array and a platformSpeed property that includes didSet so my value is updated properly.
In my method to create the platforms, I grouped my SpriteNodes into platformGroup then looped through them with addChild(). Not sure why it's acting this way but here's a quick video of what it looks like in action:
demonstration clip
So with the buttons I'm changing the switch case, and as you can see, not all of the nodes speeds are updating properly and some get faster than others and eventually pass them. I need them to stay equal distance between each other.
Now here's my code:
class GameScene: SKScene, SKPhysicsContactDelegate {
var platformGroup = [SKSpriteNode]()
var platformSpeed: CGFloat = 1.0 {
didSet {
for platforms in platformGroup {
platforms.speed = platformSpeed
}
}
}
let platformTexture = SKTexture(imageNamed: "platform")
var platformPhysics: SKPhysicsBody!
func createPlatforms() {
let platformLeft = SKSpriteNode(texture: platformTexture)
platformLeft.physicsBody = platformPhysics.copy() as? SKPhysicsBody
platformLeft.physicsBody?.isDynamic = false
platformLeft.scale(to: CGSize(width: platformLeft.size.width * 4, height: platformLeft.size.height * 4))
platformLeft.zPosition = 20
let platformRight = SKSpriteNode(texture: platformTexture)
platformRight.physicsBody = platformPhysics.copy() as? SKPhysicsBody
platformRight.physicsBody?.isDynamic = false
platformRight.scale(to: CGSize(width: platformRight.size.width * 4, height: platformRight.size.height * 4))
platformRight.zPosition = 20
let scoreNode = SKSpriteNode(color: UIColor.clear, size: CGSize(width: frame.width, height: 32))
scoreNode.physicsBody = SKPhysicsBody(rectangleOf: scoreNode.size)
scoreNode.physicsBody?.isDynamic = false
scoreNode.name = "scoreDetect"
scoreNode.zPosition = 40
platformGroup = [platformLeft, platformRight, scoreNode]
let yPosition = frame.width - platformRight.frame.width
let max = CGFloat(frame.width / 4)
let xPosition = CGFloat.random(in: -80...max)
let gapSize: CGFloat = -50
platformLeft.position = CGPoint(x: xPosition + platformLeft.size.width - gapSize, y: -yPosition)
platformRight.position = CGPoint(x: xPosition + gapSize, y: -yPosition)
scoreNode.position = CGPoint(x: frame.midX, y: yPosition - (scoreNode.size.width / 1.5))
let endPosition = frame.maxY + (platformLeft.frame.height * 3)
let moveAction = SKAction.moveBy(x: 0, y: endPosition, duration: 7)
let moveSequence = SKAction.sequence([moveAction, SKAction.removeFromParent()])
for platforms in platformGroup {
addChild(platforms)
platforms.run(moveSequence)
}
platformCount += 1
}
func loopPlatforms() {
let create = SKAction.run { [unowned self] in
self.createPlatforms()
platformCount += 1
}
let wait = SKAction.wait(forDuration: 1.1)
let sequence = SKAction.sequence([create, wait])
let repeatForever = SKAction.repeatForever(sequence)
run(repeatForever)
}
I think I can see what's going wrong. When you change platformSpeed, it changes the speed of all the platforms in platformGroup. And createPlatforms() is being called multiple times. Now, each time it's called you create a pair of platforms and assign these to platformGroup. Since you call the function multiple times, it's overwriting any existing values in the array. That's why changing platformSpeed only updates the speed of the latest platforms you've created---the older platforms stay the same speed because they're not in platformGroup anymore.
To fix this, my advice would be to have platformGroup store all the platforms currently on the screen. You could do this by changing
platformGroup = [platformLeft, platformRight, scoreNode]
to something like
let newNodes = [platformLeft, platformRight, scoreNode]
platformGroup += newNodes
// Alternatively, platformGroup.append(contentsOf: newNodes)
Now you need to make sure you're 1) only adding the new nodes to the scene, and 2) removing the old nodes from platformGroup when they're removed from the parent. You could do this by changing
let moveAction = SKAction.moveBy(x: 0, y: endPosition, duration: 7)
let moveSequence = SKAction.sequence([moveAction, SKAction.removeFromParent()])
for platforms in platformGroup {
addChild(platforms)
platforms.run(moveSequence)
}
to something like
let moveAction = SKAction.moveBy(x: 0, y: endPosition, duration: 7)
for node in newNodes {
let moveSequence = SKAction.sequence([
moveAction,
SKAction.removeFromParent(),
SKAction.run {
self.platformGroup.remove(node)
}
])
addChild(node)
node.run(moveSequence)
}
Now that you're keeping a track of all platforms ever made, your speed changes should be applied consistently to every platform on the screen. Hope this works!

Shooting balls from a rotating cannon

I'm making a SpriteKit game. I have six cannons that I've made rotate back and fourth. I want to shoot cannonballs from each cannon that sync with the rotation of each cannon. I want a duration of one second between each cannonball.
So basically: A cannon that is in constant rotation is shooting cannonballs in the same direction as the rotation.
For the cannons i'm using an extension:
extension CGFloat {
func degreesToRadians() -> CGFloat {
return self * CGFloat.pi / 180
}
}
I'm gonna put the code for just one cannon, since I should be able to figure out how to adjust one of the cannonball movements to the others. Here is one:
func createCannons() {
let cannonLeftBottom = SKSpriteNode(imageNamed: "Cannon")
cannonLeftBottom.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cannonLeftBottom.position = CGPoint(x: -325, y: -420)
cannonLeftBottom.zPosition = 4
cannonLeftBottom.setScale(0.4)
cannonLeftBottom.zRotation = CGFloat(65).degreesToRadians()
let rotateLB = SKAction.rotate(byAngle:
CGFloat(-65).degreesToRadians(), duration: 2)
let rotateBackLB = SKAction.rotate(byAngle:
CGFloat(65).degreesToRadians(), duration: 2)
let repeatRotationLB =
SKAction.repeatForever(SKAction.sequence([rotateLB,rotateBackLB]))
cannonLeftBottom.run(repeatRotationLB)
self.addChild(cannonLeftBottom)
}
Here is my function for the cannonball:
func createBalls() {
let cannonBallLB = SKSpriteNode(imageNamed: "Ball")
cannonBallLB.name = "CannonBall"
cannonBallLB.position = CGPoint(x: -325, y: -420)
cannonBallLB.physicsBody = SKPhysicsBody(circleOfRadius:
cannonBallLB.size.height / 2)
cannonBallLB.physicsBody?.affectedByGravity = false
cannonBallLB.zPosition = 3
cannonBallLB.setScale(0.1)
self.addChild(cannonBallLB)
}
THX!
You need to convert from Polar Coordinates to Rectangular Coordinates.
You do this by using sin and cos
E.G.
let speed = 100 //This would mean move 100 points per second
let force = CGVector(dx:cos(cannon.zRotation) * speed,dy:sin(cannon.zRotation) * speed)
cannonBall.applyForce(force)
Note: Now unless they changed this, force used to be in units of points, if they fixed it to units of meters, then you need to divide your speed by 150, since 150 points = 1 meter in Spritekit

Swift - SKAction moveByX, How to get my node to move from the top/down

please forgive me as I'm a bit of a Swift noob and am creating my first game :D
Ok, so I have two nodes... one is Guava and the other is Pepper. Guava moves from the bottom of the screen to the top. I want the Pepper to move from the top of the screen to the bottom. Here's the code I have, which works fine for the Guava.
// movement of guavas
let guavaToMove = CGFloat(self.frame.size.width + 2.0 * guavaNodeTexture.size().width)
let moveGuava = SKAction.moveByX(-guavaToMove, y: self.frame.size.width, duration: NSTimeInterval(0.01 * guavaToMove))
let removeGuava = SKAction.removeFromParent()
// movement of peppers
let pepperToMove = CGFloat(self.frame.size.width + 2.0 * pepperNodeTexture.size().width)
let movePepper = SKAction.moveByX(-pepperToMove, y: self.frame.size.width, duration: NSTimeInterval(0.01 * pepperToMove))
let removePepper = SKAction.removeFromParent()
GuavaMoveAndRemove = SKAction.sequence([moveGuava,removeGuava])
PepperMoveAndRemove = SKAction.sequence([movePepper,removePepper])
Now I have the Guava Node anchored to the bottom of the screen and it floats up perfectly. I have the Pepper Node anchored to the top of the screen and am trying to get it to float down in a similar fashion.
Here is the code for both functions, spawnGuava and spawnPepper where both nodes/textures are anchored:
func spawnPepper(){
//The way the Guava spawn and move
let pepperNode = SKNode()
let pepper = SKSpriteNode(texture: pepperNodeTexture)
pepper.setScale(0.30)
pepper.position = CGPointMake (self.size.width + 140, self.size.height * 0.75)
pepper.alpha = 0.75
pepper.physicsBody = SKPhysicsBody(rectangleOfSize: pepper.size)
pepper.physicsBody?.affectedByGravity = false
pepper.physicsBody?.dynamic = true
pepper.physicsBody?.categoryBitMask = PhysicsCatagory.Guava
pepper.physicsBody?.collisionBitMask = 1
pepper.physicsBody?.contactTestBitMask = PhysicsCatagory.Boognish
pepper.zPosition = 50
pepperNode.addChild(pepper)
pepper.runAction(PepperMoveAndRemove)
self.addChild(pepperNode)
if scoreIncreased == true {
}
//the way the pepper collide
}
func spawnGuava(){
//The way the Guava spawn and move
let guavaNode = SKNode()
let guava = SKSpriteNode(texture: guavaNodeTexture)
guava.setScale(0.75)
guava.position = CGPointMake (self.size.width - 40, self.size.height * 0.05)
guava.physicsBody = SKPhysicsBody(rectangleOfSize: guava.size)
guava.physicsBody?.affectedByGravity = false
guava.physicsBody?.dynamic = true
guava.alpha = 0.75
guava.physicsBody?.categoryBitMask = PhysicsCatagory.Guava
guava.physicsBody?.collisionBitMask = 1
guava.physicsBody?.contactTestBitMask = PhysicsCatagory.Boognish
guava.zPosition = 0
guavaNode.addChild(guava)
guava.runAction(GuavaMoveAndRemove)
self.addChild(guavaNode)
if scoreIncreased == true {
}
//the way the guava collide
}
Please help me configure this code accordingly so that the peppers fall from the sky :)
THANKS in advance. First post :)
FYI: I have tried modifying the code many times myself to no avail, so I have reverted it to the baseline you see now. IF I anchored the pepper to where the Guava is anchored then both would float up at the same time.
You're trying to move guavas and peppers in the opposite direction, but it seems like you are moving them in the same direction. Try removing or adding negative signs in movePepper:
let movePepper = SKAction.moveByX(-pepperToMove, y: -self.frame.size.width, duration: NSTimeInterval(0.01 * pepperToMove))
// movement of peppers
let pepperToMove = CGFloat(self.frame.size.width + 2.0 * pepperNodeTexture.size().width)
let movePepper = SKAction.moveByX(-pepperToMove, y: self.frame.size.height / -1, duration: NSTimeInterval(0.01 * pepperToMove))
let removePepper = SKAction.removeFromParent()
just has to divide the y value by a negative, derp... :D

Spawn Balls random position out of the screen

I would like to bring up enemy (var enemis) from outside the screen whether the top, bottom, left and right of the screen. And these enemy have a random direction in tranversant the screen. For the moment, my code do spawning enemy out of the screen top, bottom, left and right but with one direction only and I want make a random direction
func CreationEnnemis(){
let Enemis = SKSpriteNode(imageNamed: "Meteroites.png")
let choixDeCote = arc4random() % 4 + 1
switch choixDeCote {
case 1 : //Haut
let MinValue = self.size.width / 8
let MaxValue = self.size.width - 200
SpawnX = UInt32(MaxValue - MinValue)
SpawnX = arc4random_uniform(SpawnX)
SpawnY = UInt32(self.size.height)
break
case 2 ://Bas
let MinValue = self.size.width / 8
let MaxValue = self.size.width - 200
SpawnX = UInt32(MaxValue - MinValue)
SpawnX = arc4random_uniform(SpawnX)
SpawnY = UInt32(self.size.height) - UInt32(self.size.height)
break
case 3 : //Gauche
let MinValue = self.size.height / 8
let MaxValue = self.size.height - 200
SpawnX = 0
SpawnY = UInt32(MaxValue - MinValue)
SpawnY = arc4random_uniform(SpawnY)
break
case 4 ://Droite
let MinValue = self.size.height / 8
let MaxValue = self.size.height - 200
SpawnX = UInt32(self.size.width)
SpawnY = UInt32(MaxValue - MinValue)
SpawnY = arc4random_uniform(SpawnY)
break
default :
break
}
Enemis.position = CGPoint(x: CGFloat(SpawnX), y: CGFloat(SpawnY))
Enemis.setScale(4)
Enemis.physicsBody = SKPhysicsBody(rectangleOfSize: Enemis.size)
Enemis.physicsBody?.affectedByGravity = false
Enemis.physicsBody?.dynamic = true
let action = SKAction.moveTo(CGPoint(x: -50,y: -10),duration: 2.5)
let actionFini = SKAction.removeFromParent()
Enemis.runAction(SKAction.sequence([action, actionFini]))
Enemis.runAction(SKAction.repeatActionForever(action))
self.addChild(Enemis)
}
This is just an example to give you an idea how you can spawn enemies at random positions and move them in random directions. I don't use Swift extensively, and this is more like just to show you at which direction you can go, and how to solve the problem. I left to you to care about Swift 2 syntax :D Also, I am currently on outdated version of Swift, so not sure what works for me, will work for you, but the logic is the same.
Here you will see how you can:
spawn a node and move it to the opposite side of a screen
move a node to the random point of the opposite side of a screen
randomize duration of spawning
create a random point along the one of the screen's borders
create a random number between two numbers
using SKAction to do all this
One thing which is important here is how to use strong reference to self inside closure. Because of my Swift version, as I said, what works for me, probably will not work for you, but the logic is the same. Read more here about strong reference cycles if interested :
Shall we always use [unowned self] inside closure in Swift
Always pass weak reference of self into block in ARC?
What is the difference between a weak reference and an unowned reference?
Here is an code example:
import SpriteKit
class GameScene:SKScene, SKPhysicsContactDelegate{
override func didMoveToView(view: SKView) {
self.physicsWorld.contactDelegate = self
createEnemies()
}
deinit{
print("deinit called")
}
func randomBetweenNumbers(firstNum: CGFloat, secondNum: CGFloat) -> CGFloat{
return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum - secondNum) + min(firstNum, secondNum)
}
//Helper method for spawning a point along the screen borders. This will not work for diagonal lines.
func randomPointBetween(start:CGPoint, end:CGPoint)->CGPoint{
return CGPoint(x: randomBetweenNumbers(start.x, secondNum: end.x), y: randomBetweenNumbers(start.y, secondNum: end.y))
}
func createEnemies(){
//Randomize spawning time.
//This will create a node every 0.5 +/- 0.1 seconds, means between 0.4 and 0.6 sec
let wait = SKAction .waitForDuration(0.5, withRange: 0.2)
weak var weakSelf = self //Use weakSelf to break a possible strong reference cycle
let spawn = SKAction.runBlock({
var random = arc4random() % 4 + 1
var position = CGPoint()
var moveTo = CGPoint()
var offset:CGFloat = 40
println(random)
switch random {
//Top
case 1:
position = weakSelf!.randomPointBetween(CGPoint(x: 0, y: weakSelf!.frame.height), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x:weakSelf!.frame.width, y:0))
break
//Bottom
case 2:
position = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x: weakSelf!.frame.width, y: 0))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: 0, y: weakSelf!.frame.height), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
break
//Left
case 3:
position = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: weakSelf!.frame.height))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: weakSelf!.frame.width, y: 0), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
break
//Right
case 4:
position = weakSelf!.randomPointBetween(CGPoint(x: weakSelf!.frame.width, y: 0), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: weakSelf!.frame.height))
break
default:
break
}
weakSelf!.spawnEnemyAtPosition(position, moveTo: moveTo)
})
let spawning = SKAction.sequence([wait,spawn])
self.runAction(SKAction.repeatActionForever(spawning), withKey:"spawning")
}
func spawnEnemyAtPosition(position:CGPoint, moveTo:CGPoint){
let enemy = SKSpriteNode(color: SKColor.brownColor(), size: CGSize(width: 40, height: 40))
enemy.position = position
enemy.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size)
enemy.physicsBody?.affectedByGravity = false
enemy.physicsBody?.dynamic = true
enemy.physicsBody?.collisionBitMask = 0 // no collisions
//Here you can randomize the value of duration parameter to change the speed of a node
let move = SKAction.moveTo(moveTo,duration: 2.5)
let remove = SKAction.removeFromParent()
enemy.runAction(SKAction.sequence([move, remove]))
self.addChild(enemy)
}
func didBeginContact(contact: SKPhysicsContact) {
}
/*
Added for debugging purposes
override func touchesBegan(touches: NSSet, withEvent event: UIEvent?) {
//Just make a transition to the other scene, in order to check if deinit is called
//You have to make a new scene ... I named it WelcomeScene
var scene:WelcomeScene = WelcomeScene(fileNamed: "WelcomeScene.sks")
scene.scaleMode = .AspectFill
self.view?.presentScene(scene )
}
*/
}
And here is the result:
The important part is located in createEnemies() method:
//Top
case 1:
position = weakSelf!.randomPointBetween(CGPoint(x: 0, y: weakSelf!.frame.height), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x:weakSelf!.frame.width, y:0))
break
Here you define spawning location, which can be any point along the top border. Or more precisely a little bit above top border. Nodes are spawned offscreen. And next, you create (randomize) a point where you would like to move a node, and that is an opposite side in compare to spawn location. So, that can be any random point along bottom border.
If you want to stop spawning, you will do this:
if(self.actionForKey("spawning") != nil){
self.removeActionForKey("spawning")
}
About your physics bodies setup... Note that I've set collisionBitMask of nodes to 0.
enemy.physicsBody?.collisionBitMask = 0 // no collisions
When moving nodes by actions in SpriteKit you are pulling them out of physics simulation and you can get unexpected behaviours if you are expecting to see realistic physics simulation. So, use actions only if you are not interested in collisions (or other sort of physics simulation), but rather just in contact detection. If you need collisions as well, use physics engine and move nodes by applying impulses or forces.
Hope this helps!
Thanks a lot !
I make a different version of your code because i found solution before your answer
func CreationMeteorites(){
let Meteorites = SKSpriteNode(imageNamed: "Meteroites.png")
let choixDeCote = arc4random() % 4 + 1
switch choixDeCote {
case 1 : //Haut
let MinValue = self.size.width / 8
let MaxValue = self.size.width - 200
SpawnX = UInt32(MaxValue - MinValue)
SpawnX = arc4random_uniform(SpawnX)
SpawnY = UInt32(self.size.height)
directionX = Int(arc4random()) % Int(self.frame.size.width)
directionY = 0
action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 4)
break
case 2 ://Bas
let MinValue = self.size.width / 8
let MaxValue = self.size.width - 200
SpawnX = UInt32(MaxValue - MinValue)
SpawnX = arc4random_uniform(SpawnX)
SpawnY = 0
directionX = Int(arc4random()) % Int(self.frame.size.width)
directionY = Int(self.frame.size.height)
action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 4)
break
case 3 : //Gauche
let MinValue = self.size.height / 8
let MaxValue = self.size.height - 200
SpawnX = 0
SpawnY = UInt32(MaxValue - MinValue)
SpawnY = arc4random_uniform(SpawnY)
directionY = Int(arc4random()) % Int(self.frame.size.height)
directionX = Int(self.frame.size.width)
action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 3)
break
case 4 ://Droite
let MinValue = self.size.height / 8
let MaxValue = self.size.height - 200
SpawnX = UInt32(self.size.width)
SpawnY = UInt32(MaxValue - MinValue)
SpawnY = arc4random_uniform(SpawnY)
directionY = Int(arc4random()) % Int(self.frame.size.height)
directionX = 0
action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 3)
break
default :
break
}
//Positioner les météorites
Meteorites.position = CGPoint(x: CGFloat(SpawnX), y: CGFloat(SpawnY))
Meteorites.setScale(4)
Meteorites.physicsBody = SKPhysicsBody(circleOfRadius: 30)
Meteorites.physicsBody?.affectedByGravity = false
Meteorites.physicsBody?.dynamic = true
Meteorites.physicsBody?.categoryBitMask = PhysicsCategories.Meteorites
Meteorites.physicsBody?.contactTestBitMask = PhysicsCategories.Meteorites
let actionFini = SKAction.removeFromParent()
Meteorites.runAction(SKAction.sequence([action, actionFini]))
Meteorites.runAction(SKAction.repeatActionForever(action))
self.addChild(Meteorites)
}
And about the collisions do you know a tutorial with a good explain because i don't understand how make collisions.
For anyone that is interested to do this in objective C inside GameScene:
-(void) randomSpawnPosition{
NSUInteger randPos = arc4random_uniform(4);
CGPoint spawnPosition;
CGFloat randFloatX = arc4random_uniform(self.frame.size.width + 10);
CGFloat randFloatY = arc4random_uniform(self.frame.size.height + 10);
switch (randPos) {
//top
case 1:
spawnPosition = CGPointMake(randFloatX, self.frame.size.height+10);
break;
//bottom
case 2:
spawnPosition = CGPointMake(randFloatX, 0-10);
break;
//left
case 3:
spawnPosition = CGPointMake(0 - 10, randFloatY);
break;
//right
case 4:
spawnPosition = CGPointMake(self.frame.size.width + 10, randFloatY);
break;
}
[self addEnemy:spawnPosition];
}

How to add score to SpriteKit using SKAction

runAction(SKAction.repeatActionForever(
SKAction.sequence([
SKAction.runBlock(addScore),
SKAction.waitForDuration(1.0) ]) ))
func addScore() {
let scoreSprite = SKSpriteNode(imageNamed: "scoreSprite")
let actualY = random1(min: scoreSprite.size.height/2, max: size.height - scoreSprite.size.height/2)
scoreSprite.position = CGPoint(x: size.width + scoreSprite.size.width/2, y: actualY)
self.addChild(scoreSprite)
let actualDuration = random1(min: CGFloat(0.5), max: CGFloat(0.5))
let actionMove = SKAction.moveTo(CGPoint(x: -scoreSprite.size.width/2, y: actualY), duration: NSTimeInterval(actualDuration))
let actionMoveDone = SKAction.removeFromParent()
scoreSprite.runAction(SKAction.sequence([actionMove, actionMoveDone])) }
Okay, so I want my score to increase by 1 for every second the person plays the game. I looked into using NSTimeInterval but from what I could gather, the better option is to use SKAction. The only way I could think of was to use an almost clear sprite and to move it across the screen every second. What I want to know is how to make a score increase each time the node moves across the screen, or if this is no good what a better option would be. The code I am using to move the node is above. Thanks in advance.
Try adding this to your didMoveToView method
let wait = SKAction.waitForDuration(1.0)
let incrementScore = SKAction.runBlock ({
++self.score
self.scoreLabel.text = "\(self.score)"
})
self.runAction(SKAction.repeatActionForever(SKAction.sequence([wait,incrementScore])))
I fixed it using by adding this to the end of the scoreSprite function:
if scoreSprite.position.x > endOfScreenLeft {
updateScore()
}
Then did this to update the score:
func updateScore() {
score++
scoreLabel.text = String(score)
}
End of screen left is a CGFloat:
endOfScreenLeft = (self.size.width / 2) * CGFloat(-1)