SceneKit SCNNode следит за движением касания - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь, чтобы узел Sphere следил за движением пальца по экрану только по его оси 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 шара сбрасывается до его первоначального значения, когда он был добавлен в корневой узел сцены. 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 голосов
/ 13 ноября 2018

Попробуйте handlePan и настройте / сохраните переменную состояния dragMode. Приведенный ниже код - это то, что я использовал, чтобы выбрать панель и выделить экран, поэтому для этих вещей есть некоторый дополнительный код, но я думаю, что вы можете изменить его в соответствии со своими потребностями. В твоем случае мой "стрельба по экрану" должна быть похожа на твою необходимость перетаскивать шарик к кончику пальца.

Если вы установите объект ball в currentLocation.x в dragChanges (), то он должен выстроиться точно на кончике пальца, и ответ должен произойти быстро. Я полагаю, исходя из вашей картины, что вам нужна небольшая задержка, чтобы она была более реалистичной. Если это так, я бы предложил добавить таймер и обработать небольшую очередь сохраненных позиций 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
    }
...