iOS传感器:使用陀螺仪完成一个小球撞壁的小游戏

转载 2018年01月10日 00:00:00

点击上方“iOS开发”,选择“置顶公众号”

关键时刻,第一时间送达!

640?wxfrom=5&wx_lazy=1

0.gif?wxfrom=5&wx_lazy=1


上一次借着实现一个随屏幕旋转的小玩意,了解了iPhone内置的加速计。今天咱们继续搞点好玩的东东。按照计划这次要看看陀螺仪了。


?wx_fmt=jpeg&wxfrom=5&wx_lazy=1


最终咱们会完成一个小球撞壁的小游戏,一个超级贱的利用陀螺仪的APP。小球可以感受到重力,从而能够随着手机的运动来一起运动。为了增加一点点趣味性,对小球的运动范围做了限制。当小球碰到屏幕的边缘的时候,会进行反弹,相反方向运动。咱们一起来看看实现后的实况录像:


?wx_fmt=gif


今天的代码比起上次的加速计稍微多了一点点,所以就提供了源码供大家批评。同时由于这部分Swfit和Objective-C略微有不太一样的地方,所以源码提供了两版。

其实不管是加速计还是今天的陀螺仪,都是用到了上次说的iOS当中的那个核心运动框架CoreMotion。


1. 陀螺仪介绍


陀螺仪主要是用来测量沿着某个特定的坐标轴旋转速度的。在使用中,陀螺仪始终指向一个固定的方向,当运动物体的运动方向偏离预定方向时,陀螺仪就可以感受出来。


在手机上,仅用加速度计没办法测量或重构出完整的3D动作,测不到转动的动作的,加速计只能检测轴向的线性动作。但陀螺仪则可以对转动、偏转的动作做很好的测量,这样就可以精确分析判断出使用者的实际动作。而后根据动作,可以对手机做相应的操作。


1.1 陀螺仪的应用场景


各位童鞋相比都玩过Wii,那个体感手柄肯定就用到了陀螺仪。玩家通过挥动运动手柄,来控制游戏。例如乒乓球、网球、赛车等等。有一些酷炫的APP会通过小幅度的倾斜,偏转手机,实现彩蛋功能,例如放大缩小之类的。或者把手机屏幕翻转,就可以拒接电话或者静音啥的。拍照类的APP也会通过陀螺仪把拍照时候手的抖动反馈交给图像处理器,以便抓到更清晰稳定的图片。


还有一些是最近刚刚看到的好贱好贱的APP。例如Send Me To Heaven,游戏的玩法超级简单,只需向天空抛掷手机,扔得越高,分数也就越高。


?wx_fmt=jpeg


Throw Me App另外一个贱不拉几的APP。这是一个相机APP,使用时打开APP并将手机抛向空中,当手机在空中时,使用陀螺仪和加速计探测手机是否达到了最高点,且摄像头是否向下。随后,该应用将激活摄像头快门进行拍照。


?wx_fmt=jpeg


1.2 陀螺仪在iOS中的使用


iPhone、iPad、iWatch都有内置的陀螺仪,也都可以让开发者进行调用。同样,用一张图展现一下:


?wx_fmt=jpeg


2. 陀螺仪的使用


2.1 使用步骤


陀螺仪同样也是通过CoreMotion这个框架来管理的,所以和加速计一样,四个标准步骤:


  1. 初始化CMMotionManager管理对象;

  2. 调用管理对象的对象方法获取数据;

  3. 处理数据;

  4. 当不需要使用的时候,停止获取数据。


2.2 陀螺仪数据获取的两种方法


CoreMotion中有2种获取数据方式,一种叫做PUSH的方式,一种叫做PULL的方式。顾名思义,PUSH就是被动的获取。设定完了之后,线程定时把获取到的数据推送回来。可想而知,对于资源的消耗是会稍微大一点的。PULL,就是要去索取。拉一下才会获取到数据。不要不给。上一次加速计咱们给出的代码是OC的,今天咱们就用Swift的。


2.2.1 PULL的方式


    private func useGyroPull() {

        //判断陀螺仪可不可用

        if manager.isGyroAvailable {

            //设置陀螺仪多久采样一次

            manager.gyroUpdateInterval = 0.1

            //开始更新,后台线程开始运行。这是Pull方式。

            manager.startGyroUpdates()

            

        }

        //获取并处理陀螺仪数据。这里我们就只是简单的做了打印。

        print("X = (manager.gyroData?.rotationRate.x ?? 0)","Y = (manager.gyroData?.rotationRate.y ?? 0)","Z = (manager.gyroData?.rotationRate.z ?? 0)")


    }


2.2.2 PUSH的方式


    private func useGyroPush() {

        //判断陀螺仪可不可用

        if manager.isGyroAvailable {

            //设置陀螺仪多久采样一次

            manager.gyroUpdateInterval = 0.1

            //Push方式获取和处理数据,这里我们一样只是做了简单的打印。把采样的工作放在了主线程中。

            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("陀螺仪不可用")

        }


    }


3. 开始我们的小游戏


3.1 思维导图


?wx_fmt=jpeg


3.2 实现


3.2.1 以X轴边界值处理及碰壁后速度处理为例


//            对球在X轴碰壁进行处理

            if currentPoint.x <=  imageWidth / 2 {

              currentPoint.x = imageWidth / 2

                ballXVelocity = -ballXVelocity * 0.8

            }

            

            if currentPoint.x >= bounds.size.width - imageWidth / 2 {

                currentPoint.x = bounds.size.width - imageWidth / 2

                ballXVelocity = -ballXVelocity * 0.8


            }


3.2.2 开启陀螺仪并更新


        manager.deviceMotionUpdateInterval = 1 / 60

        //注意一下,在Swift没有了NSOperation。被OperationQueue取代了。

        manager.startDeviceMotionUpdates(to: OperationQueue.main) { (motion, error) in

            

            self.ballView!.accelleration = (motion?.gravity)!

            //开启主队列异步线程,更新球的位置。

            DispatchQueue.main.async {

                self.ballView!.updateLocation(multiplier: 5000)


            }


3.2.3 更新小球的位置


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


    }


3.3 关于Swift中重写set/get


其实写到这里的时候才突然想起来,咱们从来没有说过Swift怎么重写Set/Get方法。而且貌似也没有分享过iOS开发中多线程的东东。下个系列非典型技术宅就可以写写多线程相关的玩意儿吧,如果多线程这部分不太明白的话,对不住对不住对不住,马上补上。


在swift中其实重写set不太常见,但这都是OC留下来的臭毛病,就非要重新咋办?请自行搜索,就不提供链接到*书了。


这个不是重点,咱们在写小球的时候用到的是didSet这个方法。这是啥呐?这是swift当中的观察者,用来监视属性除了初始化之外的属性变化。


  • didSet:在属性值改变后触发,didSet可以带一个oldName的参数,表示旧的属性,不带的话默认命名为oldValue。

  • willSet:在属性值改变前触发,可以带一个newName的参数,没有的话,该参数默认命名为newValue。


源代码下载地址:OC+Swift两版。https://github.com/Stanbai/sensorDemo


640?

  • 作者:非典型技术宅

  • 链接:https://juejin.im/post/5a39d7735188257d38441a79

  • iOS开发整理发布,转载请联系作者授权

0.gif

0?【点击成为Android大神】

iOS传感器:使用陀螺仪完成一个小球撞壁的小游戏

本文来自简书,原文地址:http://www.jianshu.com/p/0763d4ac256d 上一次借着实现一个随屏幕旋转的小玩意,了解了iPhone内置的加速计。今天咱们继续搞点好玩的东...
  • qq_30513483
  • qq_30513483
  • 2017年06月08日 09:23
  • 660

IOS的一个关于球碰撞的小游戏

这个游戏是关于一个球随机在屏幕上移动,可以用手指来操纵令一个球,如果两个球碰撞到一起,就表示输了,非常简单的一个游戏 在StoryBoard里定义两个UIImageView和一个start按钮...
  • baidu_nod
  • baidu_nod
  • 2014年06月26日 19:54
  • 1737

iOS中的传感器---摇一摇, 计步器,距离感应,陀螺仪

前几天项目中用到了一下CoreMotion框架,觉得iOS中的传感器还是挺好玩的,又花了点时间去了解了一下iOS中其他一些常用的传感器应用,今天简单做下总结。 iOS中的传感器大致有以下几种: 运动...
  • SandyLoo
  • SandyLoo
  • 2016年09月28日 17:29
  • 1198

iOS 传感器(加速计 + 陀螺仪)

iOS中常用的传感器主要有以下2种  (1)加速计  加速计使用度量单位g,这是重力(gravity)的简称。1g是物体在地球的海平面上收到的下拉力(9.8米/秒)  加速计以相对于自由落体的方...
  • chy555chy
  • chy555chy
  • 2016年06月21日 00:30
  • 1073

加速度、陀螺仪、电源、距离传感器的使用方法

import UIKit import CoreMotion //传感器的使用,引入库 CoreMotion import CoreLocation //磁场传感器的使用,引入库 CoreLoc...
  • u010306762
  • u010306762
  • 2016年03月16日 22:14
  • 448

iOS传感器:实现一个随屏幕旋转的图片

作者 非典型技术宅 关注 2017.05.24 17:22* 字数 1568 阅读 351评论 7喜欢 14 在写上一个动画系列的时候学到了非常多的知识,也认识了很多人。例如受...
  • qq_34047841
  • qq_34047841
  • 2017年06月07日 09:58
  • 618

小球撞墙以及反弹

这篇小球撞墙反弹代码是看了一遍书之后写的,分享给像我一样爱好java,并在学习java 的同学们!欢迎大家指导,! package com.ball; import java.awt.Color; ...
  • qq_28631165
  • qq_28631165
  • 2016年11月05日 22:20
  • 1102

iOS根据陀螺仪等传感器获得夹角等数据

1、上代码__weak typeof(self) weakSelf = self; if ([self.motionManager isDeviceMotionAvailable]) { ...
  • sgliquangang
  • sgliquangang
  • 2016年11月10日 15:25
  • 2712

IOS开发----CMDeviceMotion陀螺仪的使用

原文地址:http://www.cocoachina.com/ios/20141103/10111.html
  • Dev_Ho
  • Dev_Ho
  • 2014年11月03日 18:27
  • 3280

碰撞球小游戏开发总结

最近有空的时候自己用java开发了一个小游戏,也算是弥补自己对这方面的空白。其实游戏开发中考虑的东西大部分都一样,比如碰撞检测,背景位移,计分,生命值计算等。在开发碰撞球的过程中,对android中的...
  • zjfengdou30
  • zjfengdou30
  • 2014年11月29日 10:14
  • 759
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS传感器:使用陀螺仪完成一个小球撞壁的小游戏
举报原因:
原因补充:

(最多只允许输入30个字)