Search code examples
swiftsprite-kitskphysicsbodytouches

How to make SKSpriteNode with fixed position (after adding physics)?


I have several programmatically made SKSpriteNode's. Some of them I want to move around, some I want to be static (have a fixed position). When adding physics to the nodes (need that to be able to do collision detection, right?) and set physicsBodyXXXX.dynamic = false they stay in the same position when moving other object over them. That's fine!

But, I'm still able to grab the node I want to be statically positioned, and move them around. How can I mask out the node I don't want to move in touches function? Or is there another solution?

Tried to find a property like static which made the node's position fixed, but can't find it...

Here's my code for auto generating nodes (in override func didMoveToView(view: SKView):

for Character in englishWord{

   // Make letters:
   let letterToMove = SKSpriteNode(imageNamed: "\(Character)")
   //then setting size and position
   var physicsBodyLetterToMove = SKPhysicsBody(rectangleOfSize: letterToMove.size)
   physicsBodyLetterToMove.affectedByGravity = false
   physicsBodyLetterToMove.allowsRotation = false
   physicsBodyLetterToMove.dynamic = false 
   letterToMove.physicsBody = physicsBodyLetterToMove

   self.addChild(letterToMove)

   // Make empty boxes for the letters:
   let letterRecBox = SKSpriteNode(imageNamed: "EmptyBox")
   //then setting size and position
   var physicsBodyLetterRecBox = SKPhysicsBody(rectangleOfSize: letterRecBox.size)
   physicsBodyLetterToMove.affectedByGravity = false            
   physicsBodyLetterRecBox.dynamic = false
   letterRecBox.physicsBody = physicsBodyLetterRecBox

   self.addChild(letterRecBox)
}

So the touches func's:

var selected: [UITouch: SKNode] = [:]

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    /* Called when a touch begins */

    selected = [:]
    for touch: AnyObject in touches {
        let location = touch.locationInNode(self)
        selected[touch as UITouch] = nodeAtPoint(location)
    }
}

override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
    for touch: AnyObject in touches {
        let location = touch.locationInNode(self)

        for (touch, node) in selected{
            if !contains([self], node){
                let action = SKAction.moveTo(location, duration: 0.1)
                node.runAction(SKAction.repeatAction(action, count: 1))
            }
        }

    }

}

Any idea?


Solution

  • Setting dynamic to false will make the node unaffected by physics. SKActions and touch events are not considered physics so they will still affect your nodes that are not dynamic.

    You could do something like:

    YourSpriteNode.name = @"staticNode"; //Right after you create it
    

    Then alter your touch method:

    for (touch, node) in selected{
            if !contains([self], node){
                if(![node.name isEqualToString:@"staticNode"])
                {
                   let action = SKAction.moveTo(location, duration: 0.1)
                   node.runAction(SKAction.repeatAction(action, count: 1))
                }
            }
        }
    

    The newly introduced if statement will prevent any node named "staticNode" from getting moved due to your SKActions. Other nodes will move as expected.