Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
929 views
in Technique[技术] by (71.8m points)

uikit - Swift Scenekit Object Drag Barrier

I'm learning scenekit and messing around with the framework. I have everything set up to where their is a scnnode named "jumpBall," has dynamic physics, and rests on a floor object. Currently, the "jumpBall" can be dragged horizontally based on a pan gesture. The "jumpBall" can be dragged from around worldPosition "x = -3.5" to "x = 3.5." Once the ball hits this barrier, it kicks out of the pan gesture function unless it is being dragged the opposite way of barrier. However, these barriers do not always work, and fast pan gestures can sometimes see the ball clipping through these barriers. I don't want the ball being clipped outside of these drag barriers.

@objc func handlePan(panGesture: UIPanGestureRecognizer) {
    guard let jumpBall = self.jumpBall else { return }
    guard let view = view as? SCNView else { return }
    let location = panGesture.location(in: self.view)
    let ballPositionX = jumpBall.worldPosition.x
    
    switch panGesture.state {
    case .began:
        guard let hitNodeResult = view.hitTest(location, options: nil).first else { return }
        panStartZ = CGFloat(view.projectPoint(lastPanLocation).z)
        lastPanLocation = hitNodeResult.worldCoordinates

    case .changed:
        //the '380' value represents the y value CGPoint of the floor
        let worldTouchPosition = view.unprojectPoint(SCNVector3(location.x, 380, panStartZ!))
        
        //this represents the direction of the ball
        //a positive dragX means the ball is moving right
        //a negative dragX means the ball is moving left
        let dragX = (worldTouchPosition.x - lastPanLocation.x) * 1.1
        
        let movementVector = SCNVector3(dragX, worldTouchPosition.y - lastPanLocation.y, 0)
        
        //break out if the ball is around the right wall and moving right
        if(ballPositionX > 3.2 && ballPositionX < 3.6) {
            if(dragX > 0) {
                break
            }
        }

        //break out if the ball is around the left wall and moving left
        if(ballPositionX < -3.2 && ballPositionX > -3.6) {
            if(dragX < 0) {
                break
            }
        }

        jumpBall.localTranslate(by: movementVector)
        self.lastPanLocation = worldTouchPosition

    case .ended:
        
        //brute force the ball back inside the barriers
        if(jumpBall.worldPosition.x > 3.5) {
            jumpBall.worldPosition.x = 3.5
        } else if(jumpBall.worldPosition.x < -3.5) {
            jumpBall.worldPosition.x = -3.5
        }
        
    default:
        break
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...