4

スプライト キットを使用して簡単なゲームを作成しています。画面は回転しませんが、ゲーム メカニックのためにユーザーが携帯電話を持っている角度を知りたいです。

取得したい値は加速度計 (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 = ??????????
}

data.acceleration.xを使用するのと同等のものを計算するにはどうすればよいCMDeviceMotionですか?

4

3 に答える 3

8

回転値にジャイロと加速度計の入力を考慮に入れたい場合は、モーションマネージャーのデバイス motionが必要なようです。ドキュメントによると:

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

詳細については、この画像を参照してください。

ここに画像の説明を入力

于 2014-07-20T21:15:12.003 に答える
2

CoreMotion が提供するジャイロ データを読み取ることで、角度を取得できます。次のように CM オブジェクトを初期化します。

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

次に、更新機能でそれを読み取ることができます。

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
}
于 2014-07-14T09:04:06.593 に答える
0

これが私が今試していることです。私は実験を通してそれにたどり着いたので、それが正しいかどうかはわかりません。おそらくもっと良い解決策があります。

            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))
            }
于 2014-08-01T18:32:18.150 に答える