0

Ok, I am working in Swift 3 playgrounds and need to move a sprite node to a certain point ONLY when the user's mouse is down, stopping when it's released. So far I have:

override func mouseDown(with event: NSEvent) {
   mouseIsDown = true
}

override func mouseDragged(with event: NSEvent) {       
}

override func mouseUp(with event: NSEvent) {
    mouseIsDown = false
}

func moveGuy() {
    let action = SKAction.move(to: CGPoint(x: size.width / 2,y: 200), duration: 2)
    action.timingMode = .easeInEaseOut
    guy.run(action)   
}

//UPDATE
override func update(_ currentTime: CFTimeInterval) {
    if(mouseIsDown)
    {
       moveGuy()
    }
}

This works somewhat, the problem is only after I release the mouse (mouseIsDown is false) does the SKAction actually run (smoothly). I think this is because it is being called again and again.

Normally I would use a moveBy action in little increments, but I need my node to move to a specific point.

How can I make my node move on its way to a point only when the mouse is down?

mtmk
  • 6,176
  • 27
  • 32
blue
  • 7,175
  • 16
  • 81
  • 179
  • 1
    Running `SKAction` inside of an `update:` is a wrong way to go (in general), especially in your case, where action has a duration of 2 seconds, and update: is executed 60 times per sec. It is not performant, (nor make sense) because you are re-creating `SKAction` objects over and over again, in order to move a sprite from point A to point B. You need, and should create only one SKAction object for this ... Like stated in the @nateslager's answer below. – Whirlwind Mar 19 '17 at 17:57
  • Of course, if you are implementing something like [homing missile](http://stackoverflow.com/a/36235426/3402095) you may want to use `update:` method (without `SKActions`). If you need to make a node to move from point A to point B, then actions are more convenient. Still, the point is, don't put actions into `update:` method in the way you are doing it ( creating action objects each frame). If you are still stuck, try to describe everything a bit more (eg. is your target changes its position or it is static) and let me know... – Whirlwind Mar 19 '17 at 18:13

1 Answers1

0

When you call

guy.run(action)

sprite-kit will run the action on the guy until completion. You're correct, moveGuy() is being called again and again (every time the frame is update, i.e. every ~33ms assuming 30fps).

Try placing moveGuy() in mouseDown(). As soon as you click, the guy will move smoothly to his destination, but he won't stop if you stop clicking. You need to somehow stop the action. What you can do is replace

guy.run(action)

with

guy.run(action, withKey: "moveGuy")

This will associate a key with your action, that you can look up later on in mouseUp():

guy.removeAction(forKey: "moveGuy")

After this, your node will move to a point only when your mouse is down. But as you've pointed out, the node's movement is still irregular if you re-click. Try changing .easeInEaseOut to .linear. The movement will then be consistent, albeit abrupt when starting/stopping.

I highly recommend the reading documentation on SKActions to gain a better understanding of how to use them.

Ralph
  • 471
  • 5
  • 14
  • Thanks! only problem is due to the duration, he moves progressively slower if you start the action after mouseup once he has traveled a little bit to destination. How can I keep speed constant? – blue Mar 19 '17 at 23:00