bwash70
bwash70

Reputation: 1155

Make SKSpriteNode character move with SKSpriteNode platform

I'm building a platform game that has an SKSpriteNode character who jumps onto moving platforms.

When the platform moves the character doesn't and it ends up falling off the platform. If I tap the move button the character moves along nicely, but I want the character to 'stick' to the platform as it moves.

I haven't posted code as the code is working as expected. I have a feeling its a property that I can set?

EDIT:

I have a solution - just not sure it's how people should do it so I'll post below and wait for feedback. It's long and complex and probably doesn't need to be.

When the user presses the left or right directional button I move the scene from GameScene.swift by:

    func moveGround(direction: String) {


    if direction == "left" {

        [snip...]
        // move the platforms
        self.enumerateChildNodesWithName("platform") {
            node, stop in

            if let foundNode = node as? PlatformSprite {
                node.position.x += Helper().kMovingDistance
            }

        }

        // move all other nodes
        self.enumerateChildNodesWithName("*") {
            node, stop in

            if let foundNode = node as? SKSpriteNode {
                node.position.x += Helper().kMovingDistance
            }

        }
        [snip...]

    } else if direction == "right" {

        [snip...]
        // move the platforms
        self.enumerateChildNodesWithName("platform") {
            node, stop in

            if let foundNode = node as? PlatformSprite {
                node.position.x -= Helper().kMovingDistance
            }

        }

        // move all other nodes
        self.enumerateChildNodesWithName("*") {
            node, stop in

            if let foundNode = node as? SKSpriteNode {
                node.position.x -= Helper().kMovingDistance
            }

        }
        [snip...]
    }

This moves the scene along nicely. Then when the character lands on top of a platform I initiate the platform movements using SKAction sequence AND initiate the scene movements by sending the reverse sequence to GameScene:

    func startMoving() {

    if !self.isMoving {

        [snip...]

        // get the platform actions and initiate the movements
        let actions = self.getMovements()
        let seq:SKAction = SKAction.sequence(actions)

        // move the platform
        self.runAction(seq, completion: { () -> Void in
            self.completedPlatformActions()
        })

        // get the reverse actions and initiate then on the scene / ground
        let reverseActions = self.getReverseMovements()
        let reverseSeq:SKAction = SKAction.sequence(reverseActions)

        delegate!.moveGroundWithPlatform(reverseSeq)

        self.isMoving = true

    }
}

Then I have a function for moving the ground with a platform and add a key to the runAction so I can stop just that action and not the platforms actions if the user ceases to be in contact with the platform:

   func moveGroundWithPlatform(seq: SKAction) {

    [snip...]

    self.enumerateChildNodesWithName("platform") {
        node, stop in

        if let foundNode = node as? PlatformSprite {
            node.runAction(seq, withKey: "groundSeq")
        }

    }
  [snip...]
  }

Then I stop moving the scene, but let the remaining actions of the platform continue using:

    func stopMovingGroundWithPlatform() {

    [snip...]
    self.enumerateChildNodesWithName("platform") {
        node, stop in

        if let foundNode = node as? PlatformSprite {
            node.removeActionForKey("groundSeq")
        }

    }
    [snip...]
}

Ugly I know - if others have suggestions about how better to do this I'd love to know :)

Upvotes: 1

Views: 930

Answers (1)

0x141E
0x141E

Reputation: 12753

If you want friction to move your character along with the platform, you will need to move the platform with a force, impulse, or by settings its velocity. I suspect it's easier to control a platform by settings its velocity. You can do that in the update method by

platform.physicsBody?.velocity = CGVectorMake(dx,dy)

where dx and dy control the platforms speed in the x and y directions, respectively. You should also set the friction property of the platform's physics body as well.

Upvotes: 1

Related Questions