美文网首页ARKITSceneKit学习SceneKit
[SceneKit专题]14.Motion Control运动控

[SceneKit专题]14.Motion Control运动控

作者: 苹果API搬运工 | 来源:发表于2017-04-16 11:53 被阅读274次

    说明

    本系列文章是对<3D Apple Games by Tutorials>一书的学习记录和体会此书对应的代码地址

    SceneKit系列文章目录

    相机约束

    // 1.拿到相机节点
    cameraNode = scnScene.rootNode.childNodeWithName("camera", recursively:
    true)!
    // 2.添加lookAt约束,让相机始终朝向ballNode小球节点
    let constraint = SCNLookAtConstraint(target: ballNode)
    cameraNode.constraints = [constraint]
    

    Gimbal locking万向节锁

    当使用SCNLookAtConstraint时,Scene Kit不管被朝向的对象如何移动,旋转都会让相机对着他.但是有些时候会转到一些奇怪的角度,导致相机发生向左或向右的倾斜,对于灯光是没问题的,但相机就不可以,我们总是希望相机保持水平方向.
    因此用到万向节锁

    constraint.gimbalLockEnabled = true
    

    更改物体的运动状态和位置

    //根据手机加速度传感器数据,移动小球
    func updateMotionControl() {
        // 1.每0.1秒更新传感器参数,构造为向量
        if game.state == GameStateType.Playing {
          motion.getAccelerometerData(0.1) { (x,y,z) in
            self.motionForce = SCNVector3(x: Float(x) * 0.05, y:0, z: Float(y+0.8) * -0.05)
          }
          // 2.小球的速度改变
          ballNode.physicsBody!.velocity += motionForce
        }
      }
      
    //让相机跟着小球平滑移动
      func updateCameraAndLights() {
        // 1.小球呈现位置与相机当前位置的差,每次移动0.01
        let lerpX = (ballNode.presentationNode.position.x - cameraFollowNode.position.x) * 0.01
        let lerpY = (ballNode.presentationNode.position.y - cameraFollowNode.position.y) * 0.01
        let lerpZ = (ballNode.presentationNode.position.z - cameraFollowNode.position.z) * 0.01
        cameraFollowNode.position.x += lerpX
        cameraFollowNode.position.y += lerpY
        cameraFollowNode.position.z += lerpZ
        // 2.灯光位置也跟随相机位置变化
        lightFollowNode.position = cameraFollowNode.position
        // 3.进入暂停状态时,相机欧拉角沿y轴旋转0.005
        if game.state == GameStateType.TapToPlay {
          cameraFollowNode.eulerAngles.y += 0.005
        }
      }
    

    传感器工具类代码

    import Foundation
    import CoreMotion
    
    class CoreMotionHelper {
      
      let motionManager = CMMotionManager()
      
      init() {
      }
      
      func getAccelerometerData(interval: NSTimeInterval = 0.1, closure: ((x: Double, y: Double, z: Double) -> ())? ){
        
        if motionManager.accelerometerAvailable {
          
          motionManager.accelerometerUpdateInterval = interval
          
          motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue()) {
            (data: CMAccelerometerData?, error: NSError?) -> Void in
            
            if closure != nil{
              closure!(x: data!.acceleration.x,y: data!.acceleration.y,z: data!.acceleration.z)
            }
            
          }
        }
      }
    }
    

    相关文章

      网友评论

        本文标题:[SceneKit专题]14.Motion Control运动控

        本文链接:https://www.haomeiwen.com/subject/tnhaattx.html