zoukankan      html  css  js  c++  java
  • iOS 神秘而又强大的传感器系统 (附demo)

    iOS中的各种传感器:

           随着科技的发展,机器感知人的行为!Goole的无人驾驶汽车到李彦宏的无人驾汽车,都带入了各种计算及传感。

            为了研究自然现象和制造劳动工具,人类必须了解外界的各类信息。了解外界信息的最初通道是大自然赋予人体的生物体感官,如五官、皮肤等。随着人类实践的发展,仅靠感官获取外界信息是远远不够了,人们必须利用已掌握的知识和技术制造一些器件或装置,以补充或替代人体感官的功能,于是出现了传感器。能够把特定的被测量信息(如物理量、化学量、生物量等)按一定规律转换成某种可用信号的器件或装置,称为传感器。传感器是生物体感官的工程模拟物;反过来,生物体的感官则可以看作是天然的传感器。所谓“可用信号”,是指便于传输、便于处理的信号。就目前而言,电信号最能满足便于传输、便于处理的要求。因此,也可以把传感器狭义地定义为:能把外界非电量信息转换成电信号输出的器件或装置。目前只要谈到传感器,指的几乎都是以电信号为输出的传感器。除电信号以外,人们在不断探索和利用新的信号媒介。可以预料,当人类跨入光子时代,光信号能够更为快速、高效地传输与处理时,一大批以光信号为输出的器件和装置将加入到传感器的家族里来。

    传感器的定义:

    为了研究自然现象和制造劳动工具,人类必须了解外界的各类信息。了解外界信息 的最初通道是大自然赋予人体的生物体感官,如五官、皮肤等。随着人类实践的发展,仅 靠感官获取外界信息是远远不够了,人们必须利用已掌握的知识和技术制造一些器件或 装置,以补充或替代人体感官的功能,于是出现了传感器。 

    能 够 把 特 定 的 被 测 量 信 息 ( 如 物 理 量 、化 学 量 、生 物 量 等 ) 按 一 定 规 律 转 换 成 某 种 可 用信号的器件或装置,称为传感器。传感器是生物体感官的工程模拟物;反过来,生物体 的感官则可以看作是天然的传感器。 

    所谓“可用信号”,是指便于传输、便于处理的信号。就目前而言,电信号最能满足便 于传输、便于处理的要求。因此,也可以把传感器狭义地定义为:能把外界非电量信息转 换成电信号输出的器件或装置。目前只要谈到传感器,指的几乎都是以电信号为输出的 传感器。除电信号以外,人们在不断探索和利用新的信号媒介。可以预料,当人类跨入光 子时代,光信号能够更为快速、高效地传输与处理时,一大批以光信号为输出的器件和装 置将加入到传感器的家族里来。 

    传感器的分类 

    现已发展起来的传感器用途纷繁、原理各异、形式多样,其分类方法也有多种,其中有 两种分类法最为常用。一是按外界输入信号转换至电信号过程中所利用的效应来分类。 如利用物理效应进行转换的为物理传感器;利用化学反应进行转换的为化学传感器;利用 生物效应进行转换的为生物传感器等。表 1-1 列出了与五官对应的几种传感器及其效 应。二是按输入量分类。比如,输入信号是用来表征压力大小的,就称为压力传感器。这 种分类法可将传感器分为位移(线位移和角位移)、速度、角速度、力、力矩、压力、流速、液 面、温度、湿度、光、热、电压、电流、气体成分、浓度和粘度传感器等。

    iOS的传感器包括:

    一、环境光传感器

    有对光照强度敏感的材料,可以制成“光敏电阻”,在不同光照条件下电阻值不同

    如果有一种对光照强度足够敏感的光敏电阻,根据其电阻值即可确定光照强度

    手机的光传感器,即环境光传感器,能感知设备周围光线情况。手机操作系统利用光线传感器的数据,自动调节显示屏亮度————当环境亮度高时,显示屏亮度会相应调高;当环境亮度低时,显示屏亮度也会相应调低。自动亮度一方面保证了手机在不同环境中的屏幕阅读体验,一方面降低了电量损耗,最大限度地延长设备工作时间。

          12号苹果推送iOS 11 Beta 6,而在这个测试版中,开发者发现了新iPhone的一个新秘密,那就是它将确定使用True Tone屏幕。

    从理论上来看,这种可调节的屏幕让用户可以更舒服的阅读或绘画素描。不过这种色温调节可能用处绝对不会有苹果在宣传中强调的那么大,除非出于某种原因需要更多的色彩补偿。

    iOS代码开发:

    #pragma mark————————————代码分割线—————————————

    #import "ViewController.h"

    @import AVFoundation;

    #import <ImageIO/ImageIO.h>

    @interface ViewController ()< AVCaptureVideoDataOutputSampleBufferDelegate>

    @property (nonatomic, strong) UIButton *button;

    @property (nonatomic, strong) AVCaptureSession *session;

    @end

    @implementation ViewController

    /*

     1、根据光线强弱去打开闪光灯;

     2、根据灯光去调节屏幕亮度

      **/

    - (void)viewDidLoad {

        [super viewDidLoad];

        // Do any additional setup after loading the view.

        self.view.backgroundColor = [UIColor whiteColor];

        

        _button = [UIButton buttonWithType:UIButtonTypeCustom];

        _button.frame = CGRectMake(100, 300, 250, 44);

        _button.layer.borderColor = [UIColor darkGrayColor].CGColor;

        _button.layer.borderWidth = 1;

        [_button setTitle:@"阴暗道路来电闪光" forState:UIControlStateNormal];

        [_button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];

        [self.view addSubview:self.button];

        

    }

    - (void)btnClick:(id)sender{

        [self lightSensitive];

    }

    - (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

    }

    #pragma mark- 光感

    - (void)lightSensitive {

        

        // 1.获取硬件设备

        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

        

        // 2.创建输入流

        AVCaptureDeviceInput *input = [[AVCaptureDeviceInput alloc]initWithDevice:device error:nil];

        

        // 3.创建设备输出流

        AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];

        [output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

        

        

        // AVCaptureSession属性

        self.session = [[AVCaptureSession alloc]init];

        // 设置为高质量采集率

        [self.session setSessionPreset:AVCaptureSessionPresetHigh];

        // 添加会话输入和输出

        if ([self.session canAddInput:input]) {

            [self.session addInput:input];

        }

        if ([self.session canAddOutput:output]) {

            [self.session addOutput:output];

        }

        

        // 9.启动会话

        [self.session startRunning];

        

    }

    /*

     iOS的检测,如果iPhone在黑暗的房间-堆栈溢出沿途见识

     这里有一个更简单的方法,用相机来观察场景的亮度。(很明显,它只读取可以在相机视野中看到的数据,所以它不是一个真正的环境光传感器…)

     利用AVFoundation框架,设置视频输入,然后使用ImageIO框架,读取元数据来对视频的每一帧(你可以忽略实际的视频数据):

     你现在有亮度值为现场更新(通常你可以配置此)每秒15-30倍。较低的数字更暗。

     */

    #pragma mark- AVCaptureVideoDataOutputSampleBufferDelegate的方法

    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {

        

        CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate);

        NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];

        CFRelease(metadataDict);

        NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];

        float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue];

        

        NSLog(@"brightnessValue==========%f",brightnessValue);

        

        

        // 根据brightnessValue的值来打开和关闭闪光灯

    //    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    //    BOOL result = [device hasTorch];// 判断设备是否有闪光灯

    //    if ((brightnessValue < 0) && result) {// 打开闪光灯

    //        

    //        [device lockForConfiguration:nil];

    //        

    //        [device setTorchMode: AVCaptureTorchModeOn];//开

    //        

    //        [device unlockForConfiguration];

    //        

    //    }else if((brightnessValue > 0) && result) {// 关闭闪光灯

    //        

    //        [device lockForConfiguration:nil];

    //        [device setTorchMode: AVCaptureTorchModeOff];//关

    //        [device unlockForConfiguration];

    //    }

        

        //调节屏幕亮度

        [UIScreen mainScreen].brightness = brightnessValue;

        

    }

    @end

    #pragma mark————————————代码分割线———————————

    二、距离传感器

    距离传感器一种传感器,是利用“飞行时间法”(flying time)的原理:是通过发射特别短的并测量此光脉冲从发射到被物体反射回来的时间,通 过测时间间隔来计算与物体之间的距离。主要产品有手机距离传感器、远距离测量传感器等,应用于智能皮带中。

    手机距离传感器:

    你接电话的时候距离传感器会起作用,当你脸靠近屏幕,屏幕灯会熄灭,并自动锁屏,可以防止你的脸误操作,当你脸离开,屏幕灯会自动开启,并且自动解锁

    应用于智能皮带:

    皮带扣里嵌入了距离传感器。当你把皮带调整至合适宽度、卡好皮带扣后,如果皮带在10秒钟内没有重新解开,传感器就会自动生成你本次的腰围数据。皮带与皮带扣连接处的其中一枚铆钉将被数据传输装置所替代。当你将智能手机放在铆钉处保持两秒钟静止,手机里的自我健康管理App会被自动激活,并获取本次腰围数据。

    iOS代码开发:

    #pragma mark————————————代码分割线———————————

    - (void)viewDidLoad

    {

        [super viewDidLoad];

        // [UIApplication sharedApplication].proximitySensingEnabled = YES;

    注意:使用前要打开当前设备距离传感器的开关(默认为:NO):

        [UIDevice currentDevice].proximityMonitoringEnabled = YES;

        // 监听方式:添加观察者,监听通知(UIDeviceProximityStateDidChangeNotification)

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(proximityStateDidChange) name:UIDeviceProximityStateDidChangeNotification object:nil];

    }

    //监听状态:观察者的对应回调方法中,判断[UIDevice currentDevice].proximityState

    - (void)proximityStateDidChange

    {

        if ([UIDevice currentDevice].proximityState) {

            NSLog(@"有物品靠近");

        } else {

            NSLog(@"有物品离开");

        }

    }

    #pragma mark————————————代码分割线———————————

    三、磁力传感器(加速计、陀螺仪、磁力计)

    地磁场是一个矢量,对于一个固定的地点来说,这个矢量可以被分解为两个与当地水平面平行的分量和一个与当地水平面垂直的分量。如果保持电子罗盘和当地的水平面平行,那么罗盘中磁力计的三个轴就和这三个分量对应起来

    今天咱们就用用第三个传感器—磁力计—来做一个AR的场景。说到AR这个词,请大家不要喷我哈,并没有用到WWDC刚出的ARKit。而且今天这个例子重点是学习使用磁力计,本质上来讲和AR关系并不大(最后的彩蛋我会演示ARkit的新效果)。

    磁力大家都不陌生,地球都是一个大磁场,罗盘指针!

    磁力计跟前面的加速计、陀螺仪,都是用到了上次说的iOS当中的那个核心运动框架CoreMotion, 也都用了CMMotionManager。

    四、温度传感器

    从 iPad一代开始,iOS设备都加入了一个内部温度传感器,用于检测内部组件温度,当温度超过系统设定的阈值时,会出现以下提示 

    内部温度传感器,对于提升iOS设备自身安全性与稳定性有很大的帮助 

    五、湿度传感器

    湿度传感器跟其他基于微电子的传感器不同,是一个简单的物理传感器

    简单来说,湿度传感器就是一张遇水变红的试纸

    Apple的维修人员就是通过检测试纸是否变红,来判断设备是否进水

    (设备进水不在保修范围之内)

    六、陀螺仪(加速计、陀螺仪、磁力计)

    在所有之前解释一下陀螺仪

     根据Wiki的定义:「陀螺仪是用于测量角度或维持方向的设备,基于角动量守恒原理。」

     这句话的要点是测量角度或维持方向,这是 iPhone 4 为何搭载此类设备的原因。机械陀螺仪–例如下面这只–中间有一转盘,用以侦测方向的改变。iPhone 4 采用了微型的,电子化的振动陀螺仪,也叫微机电陀螺仪。这东西应该就是这个样子一个东西(下图),看起来很像手表里的一个机密零件!

    8_110520143250_1.gif

    三轴陀螺仪工作原理

        注意上图的中间是一个高速旋转的金黄颜色的转子,由于惯性作用它是不会受到外力的影响而改变姿态的,而周边的设备的任何姿态的改变就可以检测出来,用来判别物体在各个方向上旋转的角度。

        这里插一句,大家小时候玩过陀螺的,知道在一定的速度下,就能一直保持一个竖直的方向。

        三轴陀螺仪最大的作用就是“测量角速度,以判别物体的运动状态,所以也称为运动传感器“,换句话说,这东西可以让我们的iPhone知道自己”在哪儿和去哪儿“(where they are or where they’re going)。

    三轴陀螺仪与加速传感器配合是如何实现辅助GPS进行定位导航的呢

        从MEMS陀螺仪的应用方向来看,陀螺仪能够测量沿一个轴或几个轴运动的角速度,可与MEMS加速度计(加速计)形成优势互补,如果组合使用加速度计和陀螺仪这两种传感器,设计者就能更好地跟踪并捕捉三维空间的完整运动,为最终用户提供现场感更强的用户使用体验、精确的导航系统以及其它功能。

        要准确地描述线性(直线运动)和旋转运动(有转弯变化的运动),需要设计者同时用到陀螺仪和加速度计。

    单纯使用陀螺仪的方案可用于需要高分辨率和快速反应的旋转检测;

    单纯使用加速度计的方案可用于有固定的重力参考坐标系、存在线性或倾斜运动但旋转运动被限制在一定范围内的应用。但同时处理直线运动和旋转运动时,就需要使用加速度和陀螺仪计的方案。

        此外,为让设计和制作的陀螺仪具有较高的加速度和较低的机械噪声,或为校正加速度计的旋转误差,一些厂商会使用磁力计来完成传统上用陀螺 仪实现的传感功能,以完成相应定位,让陀螺仪术业有专攻。这表明,混合的陀螺仪、加速度计或磁感应计结合的方案正成为MEMS陀螺仪技术应用的趋势。若只 使用传统的加速度计,用户得到的要么是反应敏捷的但噪声较大的输出,要么是反应慢但较纯净的输出,而如将加速度计与陀螺仪相结合,就能得到既纯净又反应敏 捷的输出。

        加速度计是惯性导航和惯性制导系统的基本测量元件之一,加速度计本质上是一个振荡系统,安装于运动载体的内部,可以用来测量载体的运动加速度,利用已知的 GPS测量等等的初始速度,对加速度积分,就可知道载体的速度和位置等信息。因此,加速度计的性能和精度直接影响导航和制导系统的精度。

    简而言之,言而简之

        室外:GPS——用于在室外能够搜索到足够卫星情况下的导航

        室内:

    加速度计用于测量加速度,结合GPS所提供的初始速度,可以计算出现有的速度运动的距离。

    陀螺仪用于测量设备的转弯或坡度变化大小

        在GPS信号被阻挡或受到干扰而不能进行定位的环境中,通过陀螺仪与加速度计就可以进行另一种方式的导航,可以大幅提升定位导航的效率与准确度。IPhone装上陀螺仪与加速度计后,会带动一大批手机厂商的跟进,这将会有力地推动LBS服务的进一步增长。

    代码示例:

    使用步骤:(iOS5之前)

    UIAccelerometer

    废弃由Core Motion framework取代。

    Core Motion获取数据的两种方式:

    push : 实时采集所有数据,采集频率高;

    pull : 在有需要的时候,才去采集数据;

    Core Motion的使用步骤—push

    //1.创建运动管理对象

    CMMotionManager*mgr = [[CMMotionManageralloc]init];

    //2.判断加速器是否可用(最好判断)

    if(mgr.isAccelerometerAvailable){

      //加速计可用

    }

    //3.设置采样间隔

    mgr.accelerometerUpdateInterval= 1.0/30.0;// 1秒钟采样30次

    //4.开始采样(采样到数据就会调用handler,handler会在queue中执行)

    -(void)startAccelerometerUpdatesToQueue:(NSOperationQueue*)queue withHandler:(CMAccelerometerHandler)handler;

    #pragma mark————————————代码分割线———————————

    #import "ViewController.h"

    #import <CoreMotion/CoreMotion.h>

    @interface ViewController () <UIAccelerometerDelegate>

    /** 运动管理者 */

    @property (nonatomic, strong) CMMotionManager *mgr; // 保证不死

    @end

    @implementation ViewController

    #pragma mark - 懒加载

    - (CMMotionManager *)mgr

    {

        if (_mgr == nil) {

            _mgr = [[CMMotionManager alloc] init];

        }

        return _mgr;

    }

    - (void)viewDidLoad {

        [super viewDidLoad];

        // 1.判断加速计是否可用

        if (!self.mgr.isAccelerometerAvailable) {

            NSLog(@"加速计不可用");

            return;

        }

        // 2.设置采样间隔

        self.mgr.accelerometerUpdateInterval = 0.3;

        // 3.开始采样

        [self.mgr startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { // 当采样到加速计信息时就会执行

            if (error) return;

            // 4.获取加速计信息

            CMAcceleration acceleration = accelerometerData.acceleration;

            NSLog(@"x:%f y:%f z:%f", acceleration.x, acceleration.y, acceleration.z);

        }];

    }

    @end

    #pragma mark————————————代码分割线———————————

    Core Motion的使用步骤—pull

    说明 : pull是在需要时获取数据,我们此时以点击了屏幕就获取一次数据为例说明;

    1.创建运动管理对象

    CMMotionManager*mgr = [[CMMotionManageralloc]init];

    2.判断加速器是否可用(最好判断)

    if(mgr.isAccelerometerAvailable){

      //加速计可用

    }

    3.开始采样

    -(void)startAccelerometerUpdates;

    4.在需要时获取数据

    CMAcceleration acc = mgr.accelerometerData.acceleration;

    NSLog(@"%f,%f, %f", acc.x,acc.y,acc.z);

    #pragma mark————————————代码分割线———————————

    #import "ViewController.h"

    @interface ViewController () <UIAccelerometerDelegate>

    /** 运动管理者 */

    @property (nonatomic, strong) CMMotionManager *mgr; // 保证不死

    @end

    @implementation ViewController

    #pragma mark - 懒加载

    - (CMMotionManager *)mgr

    {

        if (_mgr == nil) {

            _mgr = [[CMMotionManager alloc] init];

        }

        return _mgr;

    }

    - (void)viewDidLoad {

        [super viewDidLoad];

        // 1.判断加速计是否可用

        if (!self.mgr.isAccelerometerAvailable) {

            NSLog(@"加速计不可用");

            return;

        }

        // 2.开始采样

        [self.mgr startAccelerometerUpdates];

    }

    @end

        // 3.数据采样(以点击了屏幕为例说明)

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

    {

        // 获取加速计信息

        CMAcceleration acceleration = self.mgr.accelerometerData.acceleration;

        NSLog(@"x:%f y:%f z:%f", acceleration.x, acceleration.y, acceleration.z);

    }

    #pragma mark————————————代码分割线———————————

    七、加速计

    加速计有什么用?

    · 检测设备的运动

    应用场景

    · 摇一摇

    · 计步器

    加速计的原理 

    · 检测设备在X、Y、Z轴上的加速度 (哪个方向有力的作用,哪个方向运动了)

    · 根据加速度数值,就可以判断出在各个方向上的作用力度

    加速计的加速度范围为-1到1,因为设备正常情况下会受到重力影响,所以在上述几种情况中会有向下的为1的加速度,加速传感器

        加速度计是惯性导航和惯性制导系统的基本测量元件之一,加速度计本质上是一个振荡系统,安装于运动载体的内部,可以用来测量载体的运动加速度。

    MEMS类(

    相关知识:MEMS

        MEMS是微机电系统(Micro-Electro-Mechanical Systems)的英文缩写。MEMS是美国的叫法,在日本被称为微机械,在欧洲被称为微系统,它是指可批量制作的,集微型机构、微型传感器、微型执行器 以及信号处理和控制电路、直至接口、通信和电源等于一体的微型器件或系统。MEMS是随着半导体集成电路微细加工技术和超精密机械加工技术的发展而发展起 来的,目前MEMS加工技术还被广泛应用于微流控芯片与合成生物学等领域,从而进行生物化学等实验室技术流程的芯片集成化。

    加速度计的工作原理是当加速度计连同外界物体(该物体的加速度就是待测的加速度)一起作加速运动时,质量块就受到惯性力的作用向相反的方向运动。质量块发生的位移受到弹簧和阻尼器的限制,通过输出电压就能测得外界的加速度大小。

    新建工程,我们在ViewDidLoad中加入以下代码

    //获得单例对象

    2     UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];

    3     //设置代理

    4     accelerometer.delegate = self;

    5     //设置采样间隔 1/60.0 就是 1秒采集60次

    6     accelerometer.updateInterval = 1 / 60.0;

    实现代理方法

    1 -(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration

    2 {

    3     NSLog(@"x加速度%f--y加速度%f--z加速度%f",acceleration.x,acceleration.y,acceleration.z);

    4 }

    代理方法给我们返回了加速计对象和结果对象,运行程序结果如下

    1 2015-02-10 11:11:06.168 UIAccelerometer[1147:60b] x加速度-0.060181--y加速度0.094147--z加速度-0.988922

    2 2015-02-10 11:11:06.186 UIAccelerometer[1147:60b] x加速度-0.059189--y加速度0.093430--z加速度-0.987961

    3 2015-02-10 11:11:06.204 UIAccelerometer[1147:60b] x加速度-0.059387--y加速度0.092224--z加速度-0.987488

    4 2015-02-10 11:11:06.221 UIAccelerometer[1147:60b] x加速度-0.061752--y加速度0.092514--z加速度-0.987228

    5 2015-02-10 11:11:06.239 UIAccelerometer[1147:60b] x加速度-0.057999--y加速度0.092453--z加速度-0.988937

    6 2015-02-10 11:11:06.257 UIAccelerometer[1147:60b] x加速度-0.060883--y加速度0.095367--z加速度-0.985062

    7 2015-02-10 11:11:06.275 UIAccelerometer[1147:60b] x加速度-0.058121--y加速度0.095779--z加速度-0.988708

    8 2015-02-10 11:11:06.292 UIAccelerometer[1147:60b] x加速度-0.060349--y加速度0.093201--z加速度-0.986755

    9 2015-02-10 11:11:06.310 UIAccelerometer[1147:60b] x加速度-0.054764—y加速度0.093338--z加速度-0.990158

    我们看到设备平放,在Z轴负方向受到大约为-1的加速度

    初步了解了加速计的用法,接下来我们做一个程序,屏幕上有一个小球,可以随着重力上下左右移动,我们先在屏幕上画一个小球,并在控制器中连线

    @property (weak, nonatomic) IBOutlet UIImageView *ball;

    让小球运动就是修改小球的x,y,我们怎么让x,y和加速度发生关系呢

    初中物理我们学过,位移=速度*时间=加速度*时间*时间,因为我们设置了采样率为1/60,所以每次调用代理方法的时间为1/60秒,所以每个时刻的瞬时速度为加速度的累加,而每个时刻的位移为速度的累加,所以代理方法中我们这样写:

    1 -(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration

    2 {

    3     _volecity.x += acceleration.x;

    4     _volecity.y += acceleration.y;

    5     

    6     self.ball.x += _volecity.x;

    7     self.ball.y -= _volecity.y;

    8 }

    我们设置了一个属性来记录速度

    @property (assign, nonatomic) CGPoint volecity;

    运行程序,我们发现小球确实可以做运动,而且具有加速度,但是小球会超出边界,在代理方法中继续加入如下代码

     if(self.ball.x<=0){

     2         self.ball.x = 0;

     3     }

     4     if (self.ball.y<=0) {

     5         self.ball.y = 0;

     6     }

     7     if (self.ball.maxX>=self.view.width) {

     8         self.ball.maxX = self.view.width;

     9     }

    10     if (self.ball.maxY>=self.view.height) {

    11         self.ball.maxY = self.view.height;

    12     }

    小球被囚禁在框框中了,我们再添加一些代码,让小球碰到边界时可以反弹

    //边界检测

     2     if(self.ball.x<=0){

     3         self.ball.x = 0;

     4         //加入反弹,削弱速度

     5         _volecity.x *= -0.5;

     6     }

     7     if (self.ball.y<=0) {

     8         self.ball.y = 0;

     9         _volecity.y *= -0.5;

    10     }

    11     if (self.ball.maxX>=self.view.width) {

    12         self.ball.maxX = self.view.width;

    13         _volecity.x *= -0.5;

    14     }

    15     if (self.ball.maxY>=self.view.height) {

    16         self.ball.maxY = self.view.height;

    17         _volecity.y *= -0.5;

    18     }

    传感器的算法:

    附件:文件夹

    彩蛋:

    iOS 动力学UIDynamic

    UIDynamic是苹果在iOS7之后添加的一套动力学框架,简单来说就是类似与Box2d之类的物理引擎,运用它我们可以极其方便地模拟现实生活中的运动,比如重力,碰撞等等。它是通过添加行为的方式让动力学元素参与运动的。

    iOS7.0中提供的动力学行为包括:

    UIGravityBehavior:重力行为

    UICollisionBehavior:碰撞行为

    UIAttachmentBehavior:附着行为

    UISnapBehavior:吸附行为

    UIPushBehavior:推行为

    UIDynamicItemBehavior:动力学元素行为

    下面先来接触一下重力行为和碰撞行为:

    @implementation ViewController

    {

        UIDynamicAnimator    *_animator;      //物理仿真器

        UIGravityBehavior       *_gravity;         //重力行为

        UICollisionBehavior     *_collision;       //碰撞行为

        

        UIView                        *_view;             //模拟运动的视图对象

    }

    1.  先初始化要模拟运动的视图对象(只有遵循了UIDynamicItem协议的对象才能参与仿真模拟,而UIView正遵循了此协议,因此所有视图控件都能参与仿真运动)

        _view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 50, 50)];

        _view.backgroundColor = [UIColor blueColor];

        [self.view addSubview:_view];

    2. 初始化物理仿真器(相当于box2d引擎中的物理世界,凡是要参与运动的对象必须添加到此容器中)

        _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

        *这里是通过一个视图来初始化的,代表着整个控制器视图范围内就是一个物理仿真器

    3. 添加重力行为

        _gravity = [[UIGravityBehavior alloc] initWithItems:@[_view]];    //让_view对象参与重力行为运动    [_animator addBehavior:_gravity];         //所有行为必须添加到仿真器中才能生效

           到这里我们就可以运行一下程序了,可以看到视图确实可以受到重力影响而下落了,不过会掉出屏幕,为了让物体保留在屏幕内我们要为物体加上碰撞行为。

    4 添加碰撞行为

        _collision = [[UICollisionBehavior alloc] initWithItems:@[_view]];

        _collision.translatesReferenceBoundsIntoBoundary = YES;         //边界检测

        [_animator addBehavior:_collision];

          再次运行程序,物体在下落后就不会掉出屏幕了,为了让碰撞行为更为直观,我们可以添加更多的物体参与进来,比如点击一下屏幕就产生一个物体。

    添加触摸事件

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

    {

        //获取点击点的坐标

        CGPoint point = [[touches anyObject] locationInView:self.view];

        

        //初始化一个视图参与运动,颜色随机

        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];

        view.center = point;

        CGFloat red = arc4random()% 200 + 55;

        CGFloat green = arc4random()% 200 + 55;

        CGFloat blue = arc4random()% 200 + 55;

        view.backgroundColor = [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1.0];

        [self.view addSubview:view];

        

        //添加重力行为

        [_gravity addItem:view];

        

        //添加碰撞行为

        [_collision addItem:view];

        

    }

    AR SDK11演示 相关demo地址 https://github.com/PureLovePeter/DataSensing

  • 相关阅读:
    协程基础及其创建和使用方法
    创建进程池与线程池concurrent.futures模块的使用
    线程队列queue的使用
    线程操作之锁的使用
    linux内核调试指南
    在开发板Linux上挂载"驱动"挂载不成功,出现提示server 172.27.52.100 not responding, still trying
    LPC1788 SDRAM运行程序
    Altium designer 原理图库快速创建
    NFS挂载启动
    网站记录
  • 原文地址:https://www.cnblogs.com/PeterWolf/p/8603164.html
Copyright © 2011-2022 走看看