【问题标题】:Swift Configuring Accelerometer tracking with CMMotionManager使用 CMMotionManager Swift 配置加速度计跟踪
【发布时间】:2015-12-03 22:33:40
【问题描述】:

我一直在寻找一种方法来为加速计在我的游戏中跟踪玩家移动的方式添加偏移量。 在我的游戏中,你通过前后倾斜手机来控制玩家角色。这由加速度计转换为屏幕上的 x 和 y 坐标。不幸的是,这意味着为了阻止角色一直在屏幕底部,您必须平放手机。这对玩家来说不是很舒服。

所以我试图实现一种方式,即无论手机在开始游戏会话时的角度是什么,这是默认角度,然后倾斜由该角度的增量而不是原始数据确定我猜这将反对 0,0...

这是我的尝试:

func instantiateAcceleration() {
    if motionManager.accelerometerAvailable{
        let queue = NSOperationQueue()


        motionManager.startAccelerometerUpdatesToQueue(queue) { data, error in
            let currentX = self.player.position.x
            let currentY = self.player.position.y

            if(!self.hasCapturedOffset){

                /* So the first time we enter this loop. we'll cature the offset */

                self.offsetY = data!.acceleration.y;
                self.offsetX = data!.acceleration.x;

                print("captured offset : x - \(self.offsetX) y - \(self.offsetY)")
                self.hasCapturedOffset = true;
            }

            /* x coords */
            if data!.acceleration.y < (0 - self.offsetY) {
                self.destX = currentX + CGFloat(data!.acceleration.y * 100)
            }

            else if data!.acceleration.y > (0 + self.offsetY) {
                self.destX = currentX + CGFloat(data!.acceleration.y * 100)
            }

            /* y coords */
            if data!.acceleration.x > (0.1 - self.offsetX){
                self.destY = currentY - CGFloat(data!.acceleration.x * 100)
            }

            else if data!.acceleration.x < (0.1 + self.offsetX) {
                self.destY = currentY - CGFloat(data!.acceleration.x * 100)
            }

            /* keep it in bounds */
            if(self.destY > self.size.height){
                self.destY = self.size.height;

            }else if(self.destY < 0){
                self.destY = 0;
            }

            if(self.destX > self.size.width){
                self.destX = self.size.width;

            }else if(self.destX < 0){
                self.destX = 0;
            }

        }

    } else {
        print("Accelerometer is not available")
    }

}

上面的func在viewDidLoad上被调用,self.DestX,self.DestY在update方法中用于更新播放器:

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
    /* Accelerometer data */
    let action = SKAction.moveTo(CGPoint(x:destX, y:destY), duration: 0.1)
    self.player.runAction(action)

}

我真的很想学习如何正确地做到这一点,我知道这背后肯定有一些我不熟悉的数学。如果有人能指出我正确的方向,我将不胜感激:)

【问题讨论】:

    标签: ios swift sprite-kit swift2.1


    【解决方案1】:

    您可以将起始方向存储为 referenceAttitude 并使用

     currentattitude.multiplyByInverseOfAttitude(referenceAttitude) 
    

    计算运动。

    这是我前段时间做的一个代码示例:

    import Foundation
    import CoreMotion
    
    // Damping factor
    let cLowPassFactor: Float = 0.95
    
    class MotionManagerSingletonSwift: NSObject {
    
    
    var motionManager: CMMotionManager
    var referenceAttitude:CMAttitude?=nil
    var bActive = false
    var lastVector:[Float] = [0.0, 0.0, 0.0]
    
    
    override init()  {
        motionManager=CMMotionManager()
        motionManager.deviceMotionUpdateInterval = 0.25
        motionManager.startDeviceMotionUpdates()
        bActive=true;
    }
    
    // only one instance of CMMotionManager can be used in your project.
    // => Implement as Singleton which can be used in the whole application
    class var sharedInstance: MotionManagerSingletonSwift {
    struct Singleton {
        static let instance = MotionManagerSingletonSwift()
        }
        return Singleton.instance
    }
    
    class func getMotionManager()->CMMotionManager {
        if (sharedInstance.bActive==false) {
            sharedInstance.motionManager.startDeviceMotionUpdates()
            sharedInstance.bActive=true;
    
        }
        return sharedInstance.motionManager
    }
    
    // Returns an array with the movements
    // At the first time a reference orientation is saved to ensure the motion detection works
    // for multiple device positions
    class func getMotionVectorWithLowPass() -> [Float] {
        // Motion
        var attitude: CMAttitude? = getMotionManager().deviceMotion?.attitude
    
        if sharedInstance.referenceAttitude==nil {
            // Cache Start Orientation to calibrate the device. Wait for a short time to give MotionManager enough time to initialize
            dispatch_after(250, dispatch_get_main_queue(), {
                MotionManagerSingletonSwift.calibrate()
                })
        } else if attitude != nil {
            // Use start orientation to calibrate
            attitude!.multiplyByInverseOfAttitude(sharedInstance.referenceAttitude)
        }
    
        if attitude != nil {
            return lowPassWithVector([Float(attitude!.yaw), Float(attitude!.roll), Float(attitude!.pitch)])
        } else {
            return [0.0, 0.0, 0.0]
        }
    }
    
    // Stop collection motion data to save energy
    class func stop() {
        sharedInstance.motionManager.stopDeviceMotionUpdates()
        sharedInstance.referenceAttitude=nil
        sharedInstance.bActive=false
    }
    
    // Calibrate motion manager with a ne reference attitude
    class func calibrate() {
        sharedInstance.referenceAttitude = getMotionManager().deviceMotion?.attitude?.copy() as? CMAttitude
    }
    
    
    // Damp the jitter caused by hand movement
    class func lowPassWithVector(var vector:[Float]) -> [Float]
    {
        vector[0] = vector[0] * cLowPassFactor + sharedInstance.lastVector[0] * (1.0 - cLowPassFactor)
        vector[1] = vector[1] * cLowPassFactor + sharedInstance.lastVector[1] * (1.0 - cLowPassFactor)
        vector[2] = vector[2] * cLowPassFactor + sharedInstance.lastVector[2] * (1.0 - cLowPassFactor)
    
        sharedInstance.lastVector = vector
        return sharedInstance.lastVector
    }
    }
    

    完整教程:http://developerplayground.net/?p=19

    【讨论】:

    • 非常感谢!我现在将尝试将这种方法应用于我的代码
    • 可能是个愚蠢的问题,但我认为您为 lastvector 制作的浮点数组具有 x、y、z 值的顺序?因此,如果我要从中拉动运动,我将在 viewDidLoad 中实例化 MotionManger,然后调用 lastVector 并在更新中的每个滴答声中计算我的位置?
    猜你喜欢
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    相关资源
    最近更新 更多