SceneKit SCNNode跟随触摸运动

时间:2018-11-12 03:14:24

标签: ios swift4 uigesturerecognizer scenekit uipangesturerecognizer

我试图让“球体”节点仅跟随手指在屏幕上的x轴方向运动,而不影响球体的y或z值。我不确定是否应该对物理物体施加力或使用SCNAction对其进行移动。球体将在占据屏幕宽度的多维数据集节点上反弹。到目前为止,我最大的问题是弄清楚在手势功能中应包含什么内容。这是我要复制的示例,用户在屏幕上滑动手指,球镜像其位置。

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)
    }
}

上面的代码有些起作用,当我在屏幕上拖动手指时,y位置会突然跳开,并且即使我的代码从未编辑球的y值,它也会非常迅速地上下移动。每次我在屏幕上拖动时,将球的y位置添加到场景的根节点时,它的y位置都会重置为其原始值。 Hop

根据您的回答,这就是我所使用的,并且正是我所需要的。

@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

    }

}

1 个答案:

答案 0 :(得分:1)

尝试handlePan并设置/保存dragMode状态变量。下面的代码是我用来选择面板和扫视屏幕的代码,因此其中包含一些额外的代码,但是我认为您可以对其进行修改以适合您的需求。就您而言,我的“跨越屏幕”应该类似于您将球拖向指尖的操作。

如果在dragChanges()中将球对象设置为currentLocation.x,则它应该在指尖上完全对齐,并且响应应迅速发生。根据您的图片,我的猜测是您希望稍稍延迟一下,以便更加真实。如果是这种情况,我建议您添加一个计时器并处理一小列已保存的X位置队列,以使其以很小的增量到达您的指尖。

希望有帮助。

//**************************************************************************
    @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
    }