SceneKit SCNNode follow touch movement










0















I'm trying to have a Sphere node follow the movement of my finger on the screen on it's x axis only, without affecting the y or z values of the sphere. I'm not sure if I should be applying a force to the physics body or moving it with an SCNAction. The sphere will be bouncing on a cube node that takes up the width of the screen. My biggest problem as of now is figuring out what to put inside the pangesture function. Here is an example of what I'm trying to replicate, where the user slides their finger across the screen and the ball mirrors its location.



override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) 

for t in touches

let touchLocation = t.location(in: self.view)
let touchCoordinatesX = (touchLocation.x - self.scnView.frame.width / 2)
ballNode.position.x = Float(touchCoordinatesX/75)




The code above works somewhat, when I drag my finger across the screen the y-position freaks out, and lags up and down really quickly even though my code never edits the y-value of the ball. Everytime I drag across the screen, the y-position of the ball is reset to its original value when it was added to the scene's root node.
Hop



Based off your answer this is what I used and does exactly what I need it to.



@objc func handlePan(recognizer: UIPanGestureRecognizer)

currentLocation = recognizer.location(in: self.view)

let touchCoordinatesX = (currentLocation.x - self.scnView.frame.width / 2)



if recognizer.state == .changed



ballNode.position.x = Float(touchCoordinatesX/75)
ballNode.position.y = ballNode.presentation.position.y













share|improve this question




























    0















    I'm trying to have a Sphere node follow the movement of my finger on the screen on it's x axis only, without affecting the y or z values of the sphere. I'm not sure if I should be applying a force to the physics body or moving it with an SCNAction. The sphere will be bouncing on a cube node that takes up the width of the screen. My biggest problem as of now is figuring out what to put inside the pangesture function. Here is an example of what I'm trying to replicate, where the user slides their finger across the screen and the ball mirrors its location.



    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) 

    for t in touches

    let touchLocation = t.location(in: self.view)
    let touchCoordinatesX = (touchLocation.x - self.scnView.frame.width / 2)
    ballNode.position.x = Float(touchCoordinatesX/75)




    The code above works somewhat, when I drag my finger across the screen the y-position freaks out, and lags up and down really quickly even though my code never edits the y-value of the ball. Everytime I drag across the screen, the y-position of the ball is reset to its original value when it was added to the scene's root node.
    Hop



    Based off your answer this is what I used and does exactly what I need it to.



    @objc func handlePan(recognizer: UIPanGestureRecognizer)

    currentLocation = recognizer.location(in: self.view)

    let touchCoordinatesX = (currentLocation.x - self.scnView.frame.width / 2)



    if recognizer.state == .changed



    ballNode.position.x = Float(touchCoordinatesX/75)
    ballNode.position.y = ballNode.presentation.position.y













    share|improve this question


























      0












      0








      0


      0






      I'm trying to have a Sphere node follow the movement of my finger on the screen on it's x axis only, without affecting the y or z values of the sphere. I'm not sure if I should be applying a force to the physics body or moving it with an SCNAction. The sphere will be bouncing on a cube node that takes up the width of the screen. My biggest problem as of now is figuring out what to put inside the pangesture function. Here is an example of what I'm trying to replicate, where the user slides their finger across the screen and the ball mirrors its location.



      override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) 

      for t in touches

      let touchLocation = t.location(in: self.view)
      let touchCoordinatesX = (touchLocation.x - self.scnView.frame.width / 2)
      ballNode.position.x = Float(touchCoordinatesX/75)




      The code above works somewhat, when I drag my finger across the screen the y-position freaks out, and lags up and down really quickly even though my code never edits the y-value of the ball. Everytime I drag across the screen, the y-position of the ball is reset to its original value when it was added to the scene's root node.
      Hop



      Based off your answer this is what I used and does exactly what I need it to.



      @objc func handlePan(recognizer: UIPanGestureRecognizer)

      currentLocation = recognizer.location(in: self.view)

      let touchCoordinatesX = (currentLocation.x - self.scnView.frame.width / 2)



      if recognizer.state == .changed



      ballNode.position.x = Float(touchCoordinatesX/75)
      ballNode.position.y = ballNode.presentation.position.y













      share|improve this question
















      I'm trying to have a Sphere node follow the movement of my finger on the screen on it's x axis only, without affecting the y or z values of the sphere. I'm not sure if I should be applying a force to the physics body or moving it with an SCNAction. The sphere will be bouncing on a cube node that takes up the width of the screen. My biggest problem as of now is figuring out what to put inside the pangesture function. Here is an example of what I'm trying to replicate, where the user slides their finger across the screen and the ball mirrors its location.



      override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) 

      for t in touches

      let touchLocation = t.location(in: self.view)
      let touchCoordinatesX = (touchLocation.x - self.scnView.frame.width / 2)
      ballNode.position.x = Float(touchCoordinatesX/75)




      The code above works somewhat, when I drag my finger across the screen the y-position freaks out, and lags up and down really quickly even though my code never edits the y-value of the ball. Everytime I drag across the screen, the y-position of the ball is reset to its original value when it was added to the scene's root node.
      Hop



      Based off your answer this is what I used and does exactly what I need it to.



      @objc func handlePan(recognizer: UIPanGestureRecognizer)

      currentLocation = recognizer.location(in: self.view)

      let touchCoordinatesX = (currentLocation.x - self.scnView.frame.width / 2)



      if recognizer.state == .changed



      ballNode.position.x = Float(touchCoordinatesX/75)
      ballNode.position.y = ballNode.presentation.position.y










      ios swift4 uigesturerecognizer scenekit uipangesturerecognizer






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 12 '18 at 23:48







      Tiptonix Beats

















      asked Nov 12 '18 at 3:14









      Tiptonix BeatsTiptonix Beats

      87114




      87114






















          1 Answer
          1






          active

          oldest

          votes


















          1














          Try handlePan and setting/saving a dragMode state variable. The code below is something I used to select a panel and strafe the screen, so there is some extra code in for those things, but I think you could modify it to fit your needs. In your case, my "strafing the screen" should be similar to your need to drag the ball towards your fingertip.



          If you set your ball object to currentLocation.x in dragChanges(), then it should line up exactly on your finger tip and the response should happen quickly. My guess based on your picture is that you'd want a slight delay so that it's more realistic. If that's the case, I'd suggest adding a timer and processing a small queue of saved X positions so that it comes towards your finger tip in small increments.



          Hope that helps.



          //**************************************************************************
          @objc func handlePan(recognizer: UIPanGestureRecognizer)

          data.gameState == .defenseAdd
          //**************************************************************************
          func dragBegins(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(vRecognizer.numberOfTouches == 2) dragMode = .strafe


          //**************************************************************************
          func dragChanges(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(dragMode == .strafe && vRecognizer.numberOfTouches == 1)

          dragMode = .none
          return


          switch(dragMode)

          case .strafe:
          gNodes.camera.strafe(vX: Float(currentLocation.x), vY: Float(currentLocation.y))
          break
          case .none:
          break
          default:
          break



          //**************************************************************************
          func dragEnds(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          switch(dragMode)

          case .strafe:
          break
          default:
          break


          dragMode = .none






          share|improve this answer























          • This helped me out a lot, thanks. What should I put inside of the handlePan function that prevents the user from moving the ball unless it's within x amount of distance from the ball? If I pan on the far right side of the screen, and the ball is positioned on the far left, it "teleports" to the gesture location. I don't want it to do that.

            – Tiptonix Beats
            Nov 12 '18 at 23:50












          • I think I'd try the timer route. Put a timer in so that position.x only sets when the timer goes off. Then it should reduce the "teleport" affect. Save the last X (in mine its data.lastMouseX) value somewhere that it can be shared between the timer and call to it.

            – Voltan
            Nov 12 '18 at 23:59











          • You could also use a lerp to get several points between x and far right pan drag

            – Voltan
            Nov 13 '18 at 17:58










          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255523%2fscenekit-scnnode-follow-touch-movement%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          Try handlePan and setting/saving a dragMode state variable. The code below is something I used to select a panel and strafe the screen, so there is some extra code in for those things, but I think you could modify it to fit your needs. In your case, my "strafing the screen" should be similar to your need to drag the ball towards your fingertip.



          If you set your ball object to currentLocation.x in dragChanges(), then it should line up exactly on your finger tip and the response should happen quickly. My guess based on your picture is that you'd want a slight delay so that it's more realistic. If that's the case, I'd suggest adding a timer and processing a small queue of saved X positions so that it comes towards your finger tip in small increments.



          Hope that helps.



          //**************************************************************************
          @objc func handlePan(recognizer: UIPanGestureRecognizer)

          data.gameState == .defenseAdd
          //**************************************************************************
          func dragBegins(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(vRecognizer.numberOfTouches == 2) dragMode = .strafe


          //**************************************************************************
          func dragChanges(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(dragMode == .strafe && vRecognizer.numberOfTouches == 1)

          dragMode = .none
          return


          switch(dragMode)

          case .strafe:
          gNodes.camera.strafe(vX: Float(currentLocation.x), vY: Float(currentLocation.y))
          break
          case .none:
          break
          default:
          break



          //**************************************************************************
          func dragEnds(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          switch(dragMode)

          case .strafe:
          break
          default:
          break


          dragMode = .none






          share|improve this answer























          • This helped me out a lot, thanks. What should I put inside of the handlePan function that prevents the user from moving the ball unless it's within x amount of distance from the ball? If I pan on the far right side of the screen, and the ball is positioned on the far left, it "teleports" to the gesture location. I don't want it to do that.

            – Tiptonix Beats
            Nov 12 '18 at 23:50












          • I think I'd try the timer route. Put a timer in so that position.x only sets when the timer goes off. Then it should reduce the "teleport" affect. Save the last X (in mine its data.lastMouseX) value somewhere that it can be shared between the timer and call to it.

            – Voltan
            Nov 12 '18 at 23:59











          • You could also use a lerp to get several points between x and far right pan drag

            – Voltan
            Nov 13 '18 at 17:58















          1














          Try handlePan and setting/saving a dragMode state variable. The code below is something I used to select a panel and strafe the screen, so there is some extra code in for those things, but I think you could modify it to fit your needs. In your case, my "strafing the screen" should be similar to your need to drag the ball towards your fingertip.



          If you set your ball object to currentLocation.x in dragChanges(), then it should line up exactly on your finger tip and the response should happen quickly. My guess based on your picture is that you'd want a slight delay so that it's more realistic. If that's the case, I'd suggest adding a timer and processing a small queue of saved X positions so that it comes towards your finger tip in small increments.



          Hope that helps.



          //**************************************************************************
          @objc func handlePan(recognizer: UIPanGestureRecognizer)

          data.gameState == .defenseAdd
          //**************************************************************************
          func dragBegins(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(vRecognizer.numberOfTouches == 2) dragMode = .strafe


          //**************************************************************************
          func dragChanges(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(dragMode == .strafe && vRecognizer.numberOfTouches == 1)

          dragMode = .none
          return


          switch(dragMode)

          case .strafe:
          gNodes.camera.strafe(vX: Float(currentLocation.x), vY: Float(currentLocation.y))
          break
          case .none:
          break
          default:
          break



          //**************************************************************************
          func dragEnds(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          switch(dragMode)

          case .strafe:
          break
          default:
          break


          dragMode = .none






          share|improve this answer























          • This helped me out a lot, thanks. What should I put inside of the handlePan function that prevents the user from moving the ball unless it's within x amount of distance from the ball? If I pan on the far right side of the screen, and the ball is positioned on the far left, it "teleports" to the gesture location. I don't want it to do that.

            – Tiptonix Beats
            Nov 12 '18 at 23:50












          • I think I'd try the timer route. Put a timer in so that position.x only sets when the timer goes off. Then it should reduce the "teleport" affect. Save the last X (in mine its data.lastMouseX) value somewhere that it can be shared between the timer and call to it.

            – Voltan
            Nov 12 '18 at 23:59











          • You could also use a lerp to get several points between x and far right pan drag

            – Voltan
            Nov 13 '18 at 17:58













          1












          1








          1







          Try handlePan and setting/saving a dragMode state variable. The code below is something I used to select a panel and strafe the screen, so there is some extra code in for those things, but I think you could modify it to fit your needs. In your case, my "strafing the screen" should be similar to your need to drag the ball towards your fingertip.



          If you set your ball object to currentLocation.x in dragChanges(), then it should line up exactly on your finger tip and the response should happen quickly. My guess based on your picture is that you'd want a slight delay so that it's more realistic. If that's the case, I'd suggest adding a timer and processing a small queue of saved X positions so that it comes towards your finger tip in small increments.



          Hope that helps.



          //**************************************************************************
          @objc func handlePan(recognizer: UIPanGestureRecognizer)

          data.gameState == .defenseAdd
          //**************************************************************************
          func dragBegins(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(vRecognizer.numberOfTouches == 2) dragMode = .strafe


          //**************************************************************************
          func dragChanges(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(dragMode == .strafe && vRecognizer.numberOfTouches == 1)

          dragMode = .none
          return


          switch(dragMode)

          case .strafe:
          gNodes.camera.strafe(vX: Float(currentLocation.x), vY: Float(currentLocation.y))
          break
          case .none:
          break
          default:
          break



          //**************************************************************************
          func dragEnds(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          switch(dragMode)

          case .strafe:
          break
          default:
          break


          dragMode = .none






          share|improve this answer













          Try handlePan and setting/saving a dragMode state variable. The code below is something I used to select a panel and strafe the screen, so there is some extra code in for those things, but I think you could modify it to fit your needs. In your case, my "strafing the screen" should be similar to your need to drag the ball towards your fingertip.



          If you set your ball object to currentLocation.x in dragChanges(), then it should line up exactly on your finger tip and the response should happen quickly. My guess based on your picture is that you'd want a slight delay so that it's more realistic. If that's the case, I'd suggest adding a timer and processing a small queue of saved X positions so that it comes towards your finger tip in small increments.



          Hope that helps.



          //**************************************************************************
          @objc func handlePan(recognizer: UIPanGestureRecognizer)

          data.gameState == .defenseAdd
          //**************************************************************************
          func dragBegins(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(vRecognizer.numberOfTouches == 2) dragMode = .strafe


          //**************************************************************************
          func dragChanges(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          if(dragMode == .strafe && vRecognizer.numberOfTouches == 1)

          dragMode = .none
          return


          switch(dragMode)

          case .strafe:
          gNodes.camera.strafe(vX: Float(currentLocation.x), vY: Float(currentLocation.y))
          break
          case .none:
          break
          default:
          break



          //**************************************************************************
          func dragEnds(vRecognizer: UIPanGestureRecognizer)

          if(data.gameState == .run)

          switch(dragMode)

          case .strafe:
          break
          default:
          break


          dragMode = .none







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 12 '18 at 21:41









          VoltanVoltan

          160110




          160110












          • This helped me out a lot, thanks. What should I put inside of the handlePan function that prevents the user from moving the ball unless it's within x amount of distance from the ball? If I pan on the far right side of the screen, and the ball is positioned on the far left, it "teleports" to the gesture location. I don't want it to do that.

            – Tiptonix Beats
            Nov 12 '18 at 23:50












          • I think I'd try the timer route. Put a timer in so that position.x only sets when the timer goes off. Then it should reduce the "teleport" affect. Save the last X (in mine its data.lastMouseX) value somewhere that it can be shared between the timer and call to it.

            – Voltan
            Nov 12 '18 at 23:59











          • You could also use a lerp to get several points between x and far right pan drag

            – Voltan
            Nov 13 '18 at 17:58

















          • This helped me out a lot, thanks. What should I put inside of the handlePan function that prevents the user from moving the ball unless it's within x amount of distance from the ball? If I pan on the far right side of the screen, and the ball is positioned on the far left, it "teleports" to the gesture location. I don't want it to do that.

            – Tiptonix Beats
            Nov 12 '18 at 23:50












          • I think I'd try the timer route. Put a timer in so that position.x only sets when the timer goes off. Then it should reduce the "teleport" affect. Save the last X (in mine its data.lastMouseX) value somewhere that it can be shared between the timer and call to it.

            – Voltan
            Nov 12 '18 at 23:59











          • You could also use a lerp to get several points between x and far right pan drag

            – Voltan
            Nov 13 '18 at 17:58
















          This helped me out a lot, thanks. What should I put inside of the handlePan function that prevents the user from moving the ball unless it's within x amount of distance from the ball? If I pan on the far right side of the screen, and the ball is positioned on the far left, it "teleports" to the gesture location. I don't want it to do that.

          – Tiptonix Beats
          Nov 12 '18 at 23:50






          This helped me out a lot, thanks. What should I put inside of the handlePan function that prevents the user from moving the ball unless it's within x amount of distance from the ball? If I pan on the far right side of the screen, and the ball is positioned on the far left, it "teleports" to the gesture location. I don't want it to do that.

          – Tiptonix Beats
          Nov 12 '18 at 23:50














          I think I'd try the timer route. Put a timer in so that position.x only sets when the timer goes off. Then it should reduce the "teleport" affect. Save the last X (in mine its data.lastMouseX) value somewhere that it can be shared between the timer and call to it.

          – Voltan
          Nov 12 '18 at 23:59





          I think I'd try the timer route. Put a timer in so that position.x only sets when the timer goes off. Then it should reduce the "teleport" affect. Save the last X (in mine its data.lastMouseX) value somewhere that it can be shared between the timer and call to it.

          – Voltan
          Nov 12 '18 at 23:59













          You could also use a lerp to get several points between x and far right pan drag

          – Voltan
          Nov 13 '18 at 17:58





          You could also use a lerp to get several points between x and far right pan drag

          – Voltan
          Nov 13 '18 at 17:58



















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255523%2fscenekit-scnnode-follow-touch-movement%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

          Crossroads (UK TV series)

          ữḛḳṊẴ ẋ,Ẩṙ,ỹḛẪẠứụỿṞṦ,Ṉẍừ,ứ Ị,Ḵ,ṏ ṇỪḎḰṰọửḊ ṾḨḮữẑỶṑỗḮṣṉẃ Ữẩụ,ṓ,ḹẕḪḫỞṿḭ ỒṱṨẁṋṜ ḅẈ ṉ ứṀḱṑỒḵ,ḏ,ḊḖỹẊ Ẻḷổ,ṥ ẔḲẪụḣể Ṱ ḭỏựẶ Ồ Ṩ,ẂḿṡḾồ ỗṗṡịṞẤḵṽẃ ṸḒẄẘ,ủẞẵṦṟầṓế