Syed Qamar Abbas
Syed Qamar Abbas

Reputation: 3677

Shake Gesture with swift 3

I am trying to hit a ball on the left and right side of a box with a speed depends upon the shake gesture speed/acceleration. I am unable to get this i have tried many thing but i cannot get the speed/acceleration of gesture. I detect the gesture with core motion as well as with motionBegun and motionEnded method but unable to detect the speed so that i could create a logic of hitting the ball on both side of a box. Here is my code that how i detect the direction of shake with CoreMotion and shake gesture detection with motionBegun and motionEnded

var startedLeftTilt = false
var startedRightTilt = false
var dateLastShake = NSDate(timeIntervalSinceNow: -2)
var dateStartedTilt = NSDate(timeIntervalSinceNow: -2)
var motionManager = CoreMotion.CMMotionManager()
let tresholdFirstMove = 3.0
let tresholdBackMove = 0.5



override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    motionManager.startGyroUpdates(to: OperationQueue.current!, withHandler: { (gyroData, error) -> Void in
        self.handleGyroData(rotation: (gyroData?.rotationRate)!)
    })

}

private func handleGyroData(rotation: CMRotationRate) {

    if fabs(rotation.z) > tresholdFirstMove && fabs(dateLastShake.timeIntervalSinceNow) > 0.3
    {
        if !startedRightTilt && !startedLeftTilt
        {
            dateStartedTilt = NSDate()
            if (rotation.z > 0)
            {
                startedLeftTilt = true
                startedRightTilt = false
            }
            else
            {
                startedRightTilt = true
                startedLeftTilt = false
            }
        }
    }

    if fabs(dateStartedTilt.timeIntervalSinceNow) >= 0.3
    {
        startedRightTilt = false
        startedLeftTilt = false
    }
    else
    {
        if (fabs(rotation.z) > tresholdBackMove)
        {
            if startedLeftTilt && rotation.z < 0
            {
                dateLastShake = NSDate()
                startedRightTilt = false
                startedLeftTilt = false


            }
            else if startedRightTilt && rotation.z > 0
            {
                dateLastShake = NSDate()
                startedRightTilt = false
                startedLeftTilt = false


            }
        }
    }

}

override func becomeFirstResponder() -> Bool {
    return true
}
override func motionBegan(_ motion: UIEventSubtype, with event: UIEvent?) {
    if motion == .motionShake {
        NSLog("Motion is Started");
    }
}
override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
    if motion == .motionShake {
        NSLog("Motion is Ended");
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    motionManager.gyroUpdateInterval = 0.01
    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

Upvotes: 1

Views: 1270

Answers (2)

nouman
nouman

Reputation: 108

Use gyro and motion at the same time to get your trigger. Gyro will provide you the direction and motion will provide you some kind of speed analysis. Implementing both at the same time with your custom logic will you what exactly you are trying to get. Use the last answer for finding the direction. StackAnswer

Upvotes: 1

Duncan C
Duncan C

Reputation: 131398

Core motion has lots of options. You can use high level events like shake events, or you can get gyro or acellerometer updates.

The code you posted is monitoring gyro events. If you're looking for the force of a shake you want acellerometer events, not gyro events.

Upvotes: 2

Related Questions