使用 CMDeviceMotion 获得绝对旋转?[英] Obtain absolute rotation using CMDeviceMotion?

本文是小编为大家收集整理的关于使用 CMDeviceMotion 获得绝对旋转?的处理方法,想解了使用 CMDeviceMotion 获得绝对旋转?的问题怎么解决?使用 CMDeviceMotion 获得绝对旋转?问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我正在使用 Sprite Kit 构建一个简单的游戏,屏幕不会旋转,但我想知道用户拿着手机的角度以便游戏机制.

使用加速度计 (x, y) 可以轻松检索我想要获得的值,但我发现这不可靠,因此我尝试使用 CMDeviceMotion 存档更好的结果.我可以获得 data.acceleration.y 的等效项,但我不知道如何获得 data.acceleration.x 的等效项.

if let data = motionManager.accelerometerData? {
    let y = CGFloat(data.acceleration.y)
    let x = CGFloat(data.acceleration.x)
}

// Device Motion
if let attitude = motionManager.deviceMotion?.attitude? {
    let y = CGFloat(-attitude.pitch * 2 / M_PI) // This matches closely with data.acceleration.y
    let x = ??????????
}

如何使用 CMDeviceMotion 计算 data.acceleration.x 的等效值?

推荐答案

这就是我现在正在尝试的.我是通过实验得出的,所以我不知道它是否正确,可能有更好的解决方案.

            if let attitude = motionManager.deviceMotion?.attitude? {
                 // Convert pitch and roll to [-1, 1] range
                let pitch = CGFloat(-attitude.pitch * 2 / M_PI)
                let roll = CGFloat(abs(attitude.roll) > M_PI / 2 ? (2 - abs(attitude.roll) * 2 / M_PI) * (attitude.roll > 0 ? 1 : -1) : attitude.roll * 2 / M_PI)

                // Calculate x and y
                let y = pitch
                let x = roll*(1.0-abs(pitch))
            }

其他推荐答案

听起来你想要运动管理器的设备运动,如果您希望旋转值考虑陀螺仪和加速度计输入.根据文档:

<块引用>

CMDeviceMotion 的一个实例封装了对设备的姿态、旋转速率和加速度的测量.

因此,与其直接监视陀螺仪数据,不如监视设备运动.下面的示例演示了如何逐帧获取设备运动.我刚刚决定直接打印 CMAttitude 对象,但是从这个对象中,您可以直接访问设备的俯仰、滚动和偏航(等等),如果我没记错的话,这正是你在找什么.

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

如果您使用的是 Swift 2,则需要进行一些小的更改,如下所示.

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

有关这方面的更多信息,请参阅此图片.

在此处输入图片描述

其他推荐答案

可以通过读取CoreMotion提供的陀螺仪数据来获取角度.像这样初始化一个 CM 对象:

class GameScene: SKScene {
    var motionManager = CMMotionManager()
    override func didMoveToView(view: SKView) {
        motionManager.startGyroUpdates()
    }
}

然后在update函数中,就可以读取了:

override func update(currentTime: CFTimeInterval) {
    if let data = motionManager.gyroData {
        let x = data.rotationRate.x
        let y = data.rotationRate.y
        let z = data.rotationRate.z
    }
}

您现在可以为您的游戏机制使用 x、y 和 z 值.但是,请注意,它给出的是当前旋转速率,而不是绝对旋转.如果这是您的需要,您可以自己跟踪它.或者,您可以使用加速度计数据:

motionManager.startAccelerometerUpdates()
...
if let data = motionManager.accelerometerData {
    let x = data.acceleration.x
}

本文地址:https://www.itbaoku.cn/post/924567.html