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
}
}
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)
{
currentLocation = recognizer.location(in: gameScene)
let getLocation: CGPoint = recognizer.location(in: gameScene)
let panHitTestResults = gameScene.hitTest(getLocation, options: hitTestOptions)
if(data.gameState == .endWave || data.gameState == .endGame ||
data.gameState == .defenseAdd || data.gameState == .defenseUpgrade)
{
dragMode = .none
selectorActive = false
lastPanelSelected = ""
return
}
// State Begins
if recognizer.state == UIGestureRecognizerState.began
{
dragMode = .drag
beginLocation = recognizer.location(in: gameScene)
data.panX = currentLocation.x
data.lastMouseX = Float(beginLocation.x)
data.lastMouseY = Float(beginLocation.y)
dragBegins(vRecognizer: recognizer)
selectorActive = false
}
// State Changes
if(recognizer.state == UIGestureRecognizerState.changed)
{
dragChanges(vRecognizer: recognizer)
if(data.gameState == .run && dragMode == .drag)
{
// If we were selecting cursor and want to cancel, just touch with 2 fingers
if(recognizer.numberOfTouches == 2)
{
dragMode = .none
selectorActive = false
grid.cancelCursor()
return
}
for vHit in panHitTestResults
{
if(vHit.node.name?.prefix(5) == "Panel")
{
selectorActive = true
lastPanelSelected = vHit.node.name!
data.panelSelected = lastPanelSelected
let _ = grid.selectCursor()
return
}
}
}
}
if(recognizer.state == UIGestureRecognizerState.ended)
{
dragEnds(vRecognizer: recognizer)
dragMode = .none
if(selectorActive == true)
{
gameControl.selectPanel(vPanel: lastPanelSelected)
lastPanelSelected = ""
selectorActive = false
return
}
}
}
//**************************************************************************
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
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.