Search code examples
swift3sprite-kitskaction

Cant make Spritenode move in one direction forever?


Ok, this is frustrating because this should not be this hard. Whenever The user has their finger down, I need my sprite node to move forever in one direction. Here I create my sprite node

character.size = CGSize(width: 58, height: 139)
        character.color = UIColor.red
        character.position = CGPoint(x: (scene?.size.width)!/2, y: (scene?.size.height)!/2)
        character.zPosition = 3
        character.physicsBody = SKPhysicsBody(rectangleOf: character.size)
        character.physicsBody?.isDynamic = true
        character.physicsBody?.affectedByGravity = false
        character.physicsBody?.allowsRotation = false

Then in touches began, I have tried applying a force directly and having a repeating skaction that is removed when touches ended, however using SKaction.moveBy, the node moves 10 then snaps back to the original position:

override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touch!")
        isTouching = true
        let touch = touches.first!
//        
        let movement = CGVector(
            dx: 10,
            dy: 1
        )
        let move = SKAction.moveBy(x: character.position.x+10, y: 0, duration: 1)
        //let move = SKAction.applyForce(movement, duration: 0.5)
        character.run(SKAction.repeatForever(move), withKey: "moving")

I am using the character.position.x so I don't know why it is not just moving forever to the right. How can I make the node move continuously in a direction?


Solution

  • In your case, an action will move a node from one starting point to the end point. If you repeat it, it will teleport the node to where it was at the beginning, and move it again to its final position. Conclusion - SKAction is not suitable for this.

    You have a few options:

    1) Affecting on sprite's position property manually - eg. inside of an update: method, you will increment/decrement position.x/position.y property over time.

    sprite.position.y += 1
    

    2) You will apply force in every frame inside of an update: method

    sprite.physicsBody.applyForce(CGVector(dx:dxValue, dy:dyValue)
    

    3) Affecting on physics body velocity vector directly:

    sprite.physicsBody.velocity = CGVector(dx:dxValue, dy:dyValue)
    

    Probably you could go with applying an impulse to the node, but I think that more appropriate for your situation is to apply force each frame.

    Hope this make sense and is helpful.