Obtain absolute rotation using CMDeviceMotion?

后端 未结 3 1405
醉酒成梦
醉酒成梦 2021-01-03 06:42

I\'m building a simple game with Sprite Kit, the screen doesn\'t rotate but I want to know the angle the user is holding the phone for a game mechanic.

The values I

3条回答
  •  余生分开走
    2021-01-03 07:29

    It sounds like you want the motion manager's device motion, if you want the rotation values to take gyro and accelerometer input into account. According to the docs:

    An instance of CMDeviceMotion encapsulates measurements of the attitude, rotation rate, and acceleration of a device.

    So, instead of monitoring gyro data directly, monitor device motion instead. The example below demonstrates how to obtain device motion on a frame by frame basis. I've just decided to print the CMAttitude object directly, but from this object, you can directly access the pitch, roll, and yaw of the device (and more) which if I'm not mistaken, is exactly what you're looking for.

    import SpriteKit
    import CoreMotion
    
    class GameScene: SKScene {
        let motionManager = CMMotionManager()
    
        override func didMoveToView(view: SKView) {
            motionManager.deviceMotionUpdateInterval = 1.0 / 30.0
            motionManager.startDeviceMotionUpdates()
        }
    
        override func willMoveFromView(view: SKView!) {
            motionManager.stopDeviceMotionUpdates()
        }
    
        override func update(currentTime: CFTimeInterval) {
            if let attitude = motionManager.deviceMotion?.attitude? {
                println(attitude)
                let y = CGFloat(-attitude.pitch * 2 / M_PI)
                let x = CGFloat(-attitude.roll * 2 / M_PI)
            }
        }
    }
    

    If you're using Swift 2, there are some minor changes that need to be made, which are shown below.

    class GameScene: SKScene {
        let motionManager = CMMotionManager()
    
        override func didMoveToView(view: SKView) {
            motionManager.deviceMotionUpdateInterval = 1.0 / 30.0
            motionManager.startDeviceMotionUpdates()
        }
    
        override func willMoveFromView(view: SKView) {
            motionManager.stopDeviceMotionUpdates()
        }
    
        override func update(currentTime: CFTimeInterval) {
            if let attitude = motionManager.deviceMotion?.attitude {
                print(attitude)
                let y = CGFloat(-attitude.pitch * 2 / M_PI)
                let x = CGFloat(-attitude.roll * 2 / M_PI)
            }
        }
    }
    

    For more info on this, consult this image.

提交回复
热议问题