SceneKit SCNNode follow touch movement
up vote
0
down vote
favorite
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.
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
add a comment |
up vote
0
down vote
favorite
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.
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
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
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.
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
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.
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
ios swift4 uigesturerecognizer scenekit uipangesturerecognizer
edited Nov 12 at 23:48
asked Nov 12 at 3:14
Tiptonix Beats
82114
82114
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
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)
//**************************************************************************
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
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 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 at 23:59
You could also use a lerp to get several points between x and far right pan drag
– Voltan
Nov 13 at 17:58
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
up vote
1
down vote
accepted
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)
//**************************************************************************
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
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 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 at 23:59
You could also use a lerp to get several points between x and far right pan drag
– Voltan
Nov 13 at 17:58
add a comment |
up vote
1
down vote
accepted
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)
//**************************************************************************
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
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 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 at 23:59
You could also use a lerp to get several points between x and far right pan drag
– Voltan
Nov 13 at 17:58
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
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)
//**************************************************************************
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
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)
//**************************************************************************
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
answered Nov 12 at 21:41
Voltan
155110
155110
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 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 at 23:59
You could also use a lerp to get several points between x and far right pan drag
– Voltan
Nov 13 at 17:58
add a comment |
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 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 at 23:59
You could also use a lerp to get several points between x and far right pan drag
– Voltan
Nov 13 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 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 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 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 at 23:59
You could also use a lerp to get several points between x and far right pan drag
– Voltan
Nov 13 at 17:58
You could also use a lerp to get several points between x and far right pan drag
– Voltan
Nov 13 at 17:58
add a comment |
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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