Astrum
Astrum

Reputation: 375

Moving an SKSpritenode towards another SKSpriteNode (Magnet)

My Goal: To get an SKSpriteNode to move to another SKSpriteNodes position. (To create a magnet for my sprite kit game)

Hi, I am trying to get multiple SKSpriteNodes with the same name to move towards and collide with an sprite node that i’m going to be calling a magnet i just don’t understand where or how i would go about doing this, i have tried using this code but i’m left scratching my head on what to do:

func update(_ currentTime: TimeInterval) {

   let node = childNode(withName: "specialObstacle")

        let magnetLocation = magnet.position
        let specialObjectLocation = node?.position

        let x = node?.position.x - magnetLocation.x
        let y = node?.position.y - magnetLocation.y

}

Note: My magnet’s location will be changing due to the fact the user will be moving the magnet around the screen and would like it to keep going towards the magnet but i just can’t figure out how to do this.

EDIT 1

I tried using the code you had whirlwind and it seems to work for the x-axis but it seems to not work for the y axis for some reason it looks like it tries to go down but fails and just vibrates in the one spot. i have added my code below and a image

whirlwind

HERE is the code i'm using:

 let playerLocation:CGPoint = self.convert(thePlayer.position, from: worldNode)

        let location = playerLocation
        let nodeSpeed:CGFloat = 3.5

        worldNode.enumerateChildNodes(withName: "levelUnit"){
            node, stop in

            let levelUnit:LevelUnit = node as! LevelUnit  //cast as an actual LevelUnit class


            levelUnit.enumerateChildNodes(withName: "specialObstacle"){
                node, stop in

                //Aim
                let dx = location.x - (node.position.x)
                let dy = location.y - (node.position.y)
                let angle = atan2(dy, dx)

                node.zRotation = angle

                //Seek
                let vx = cos(angle) * nodeSpeed
                let vy = sin(angle) * nodeSpeed

                node.position.x += vx
                node.position.y += vy

            }
        }

Upvotes: 4

Views: 641

Answers (1)

Luca Angeletti
Luca Angeletti

Reputation: 59516

Something like this?

enter image description here

Code

First of all here's the code

import SpriteKit

class GameScene: SKScene {

    let magnet = SKFieldNode.linearGravityField(withVector: vector_float3(0, 9.8 * 2, 0))
    let circle = SKShapeNode(circleOfRadius: 30)
    override func didMove(to view: SKView) {
        circle.fillColor = .white
        circle.position.x = 0
        circle.position.y = frame.maxY
        addChild(circle)

        magnet.region = SKRegion(size: self.frame.size)
        magnet.isEnabled = false
        magnet.categoryBitMask = 0x1            
        circle.addChild(magnet)

        self.physicsBody = SKPhysicsBody(edgeLoopFrom: frame)

        for i in 0..<20 {
            let ball = SKShapeNode(circleOfRadius: 30)
            ball.fillColor = .yellow
            ball.physicsBody = SKPhysicsBody(circleOfRadius: 30)
            ball.position.x = CGFloat(i) * 10
            ball.physicsBody!.fieldBitMask = 0x1
            addChild(ball)
        }

        let ball = SKShapeNode(circleOfRadius: 30)
        ball.fillColor = .green
        ball.physicsBody = SKPhysicsBody(circleOfRadius: 30)
        ball.position.y = 40
        ball.physicsBody!.fieldBitMask = 0x2
        addChild(ball)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        circle.fillColor = .red
        magnet.isEnabled = true
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        circle.fillColor = .white
        magnet.isEnabled = false
    }
}

How does it work?

Here there are the core concepts

  1. There's an SKFieldNode on top of the screen whose categoryBitMask is 0x1
  2. The yellow balls have a physics body with fieldBitMask = 0x1 (this will make the interact with the FieldNode)
  3. The green ball has a physics body with fieldBitMask = 0x2 (which makes it not affected by the SKFieldNode)

Finally I am simply turning on/off the SKFieldNode when you touch/untouch the screen.

Oh, and there's a red sprite exactly at the same position of the SKFieldNode but that's only for UI reasons.

Upvotes: 3

Related Questions