I learned about the iPhone’s built-in accelerometer last time by implementing a gadget that rotates with the screen. Let’s do some more fun stuff today. The plan is to look at the gyroscope this time.
We’ll end up with a little ball hitting a wall game, a super cheap gyroscope-using APP. The ball senses gravity and moves with the phone. To add a little interest, the ball’s range of movement has been limited. When the ball hits the edge of the screen, it bounces and moves in the opposite direction. Let’s take a look at the live video of the implementation:
Today’s code is a little bit more than the accelerometer last time, so the source code is provided for everyone to criticize. And because this part of Swfit is slightly different from Objective-C, the source code is available in two versions.
In fact, both accelerometers and today’s gyroscopes are used in the CoreMotion framework CoreMotion of iOS mentioned last time.
1. Gyroscope introduction
Gyroscopes are mainly used to measure the speed of rotation along a specific coordinate axis. In use, the gyroscope is always pointed in a fixed direction, when the movement of a moving object is deviated from the predetermined direction, the gyroscope can sense.
On mobile phones, the accelerometer alone cannot measure or reconstruct a complete 3D motion. If rotational motion cannot be measured, the accelerometer can only detect linear axial motion. Gyroscopes, on the other hand, do a good job of measuring the movement of rotation and deflection, so that the actual movement of the user can be accurately analyzed and judged. Then according to the action, you can do the corresponding operation to the mobile phone.
1.1 Application scenarios of gyroscopes
If you’ve ever played with a Wii, you’re sure to use a gyroscope for your tactile controller. The player controls the game by waving a motion controller. Such as table tennis, tennis, racing and so on. There are some cool apps that do Easter egg functions by tilting and deflecting the phone slightly, such as zooming in and out. Or flip the screen so you can reject calls or mute them. The camera APP will also feed the shaking feedback of the hand to the image processor through the gyroscope, so as to capture clearer and more stable pictures.
And some of the meanest, meanest apps I’ve seen recently. Send Me To Heaven, for example, is a super simple game where you just throw your phone into the sky and the higher you throw it, the higher your score.
Throw Me App Another cheap App. This is a camera APP. When using the APP, open the APP and throw the phone into the air. When the phone is in the air, use the gyroscope and accelerometer to detect whether the phone has reached the highest point and whether the camera is downward. The app then activates the camera shutter to take a picture.
1.2 Gyroscope in iOS
The iPhone, iPad and iWatch all have built-in gyroscopes that developers can call up. Again, here’s a picture:
2. Use of gyroscopes
2.1 Procedure
Gyroscopes are also managed through the CoreMotion framework, so like accelerometers, there are four standard steps:
- Initialize the CMMotionManager managed object.
- Call the object method of the managed object to get the data;
- Processing data;
- Stop fetching data when it is no longer needed.
2.2 Two methods of gyroscope data acquisition
There are two ways to get data in CoreMotion, one called PUSH and one called PULL. As the name implies, PUSH is passive acquisition. Once set, the thread periodically pushes the data back. It is conceivable that the consumption of resources will be slightly greater. PULL is to take. You have to pull it to get the data. Don’t refuse. Last time we gave the accelerometer code is OC, today we will use Swift.
2.2.1 Method of PULL
private func useGyroPull() {// Check whether the gyroscope is availableifManager. IsGyroAvailable {/ / set the gyroscope how long sampling time manager. GyroUpdateInterval = 0.1 / / update, background threads began to run. This is Pull. Manager.startgyroupdates ()} // Obtain and process gyroscope data. So here we're just simply printing.print("X = \(manager.gyroData? .rotationRate.x ?? 0)"."Y = \(manager.gyroData? .rotationRate.y ?? 0)"."Z = \(manager.gyroData? .rotationRate.z ?? 0)")}Copy the code
2.2.2 PUSH Mode
private func useGyroPush() {// Check whether the gyroscope is availableifManager. IsGyroAvailable {/ / set the gyroscope how long sampling time manager. GyroUpdateInterval = 0.1 / / Push way to obtain and deal with the data, here we just do a simple print. Put the sampling work in the main thread. manager.startGyroUpdates(to: OperationQueue.main, withHandler: { (gyroData, error)in
print("X = \(self.manager.gyroData? .rotationRate.x ?? 0)"."Y = \(self.manager.gyroData? .rotationRate.y ?? 0)"."Z = \(self.manager.gyroData? .rotationRate.z ?? 0)")})}else {
print("Gyro not available.")}}Copy the code
3. Start our little game
3.1 Mind mapping
3.2 implementation
3.2.1 Take the processing of X-axis boundary value and velocity after hitting the wall as examples
// The ball hits the wall in the X-axisifCurrentpoint. x <= imageWidth / 2 {currentPoint.x = imageWidth / 2 ballXVelocity = -ballxvelocity * 0.8}ifcurrentPoint.x >= bounds.size.width - imageWidth / 2 { currentPoint.x = bounds.size.width - imageWidth / 2 ballXVelocity = -ballxvelocity * 0.8}Copy the code
3.2.2 Start and update the gyroscope
Manager. DeviceMotionUpdateInterval = 1/60 / / pay attention to, in a Swift NSOperation. Replaced by OperationQueue. manager.startDeviceMotionUpdates(to: OperationQueue.main) { (motion, error)inself.ballView! .accelleration = (motion? .gravity)! // Start the main queue asynchronous thread to update the ball position. DispatchQueue.main.async { self.ballView! .updateLocation(multiplier: 5000) }Copy the code
3.2.3 Update the position of the ball
func updateLocation(multiplier : Double) {
if(lastUpdateTime ! = nil) {let updatePeriod : Double = Date.init().timeIntervalSince(lastUpdateTime!)
ballXVelocity = ballXVelocity + accelleration.x * updatePeriod
ballYVelocity = ballYVelocity + accelleration.y * updatePeriod
let coefficient = updatePeriod * multiplier
currentPoint = CGPoint(x: currentPoint.x + (CGFloat)(ballXVelocity * coefficient), y: currentPoint.y - (CGFloat)(ballYVelocity * coefficient))
}
lastUpdateTime = Date()
}
Copy the code
3.3 About rewriting set/get in Swift
We’ve never said how Swift overrides Set/Get. And I don’t seem to have shared anything about multithreading in iOS development. The next series of geek geeks can write about multithreading. If you don’t understand multithreading, I’m sorry, I’m sorry, I’m sorry.
In fact, rewriting set is not common in SWIFT, but this is the stink left by OC, so what should we do again? Please do your own search and no link to the * book will be provided.
That’s not the point, we’re going to use didSet when we write balls. What is this? This is the observer in Swift that monitors property changes other than initialization.
didSet
DidSet can take an oldName argument to indicate the old attribute, if not, the default name is oldValue.willSet
: fires before the property value changes. It can take a newName argument. If not, the argument is named newValue by default.
Source code download address: OC+Swift two versions. Download address