IOS_加速计_碰撞检测_小球位置修复_dispatch_once单例

来源:互联网 发布:私人摄像头直播软件 编辑:程序博客网 时间:2024/06/08 12:38
H:/0802/01_accelerometer加速计+小球碰撞检测_ViewController.h
////  ViewController.h//  加速计01-演练1////  Created by apple on 13-8-2.//  Copyright (c) 2013年 itcast. All rights reserved.//#import <UIKit/UIKit.h>@interface ViewController : UIViewController <UIAccelerometerDelegate>// 模拟小球视图@property (weak, nonatomic) IBOutlet UIView *ballView;@end

H:/0802/01_accelerometer加速计+小球碰撞检测_ViewController.m
//  ViewController.m//  加速计01-演练1//  Created by apple on 13-8-2.//  Copyright (c) 2013年 itcast. All rights reserved.// 千万注意:在加速计坐标系中Y轴方向和UIKit坐标系中的Y轴方向是相反的。!!!!!!#import "ViewController.h"@interface ViewController (){    // 小球速度    CGPoint     _ballVelocity;}@end@implementation ViewController- (void)viewDidLoad {   [super viewDidLoad];    // 1. 初始化小球速度为0,让小球初始状态是静止的    _ballVelocity = CGPointZero;    // 1. 实例化引用共享的加速计对象(单例UIAccelerometer)// 注意:非常耗电,用完要释放    UIAccelerometer *acce = [UIAccelerometer sharedAccelerometer];    // 2. 设置更新时间间隔,即频率,单位:赫兹HZ    [acce setUpdateInterval:1.0 / 30.0];    // 3. 设置加速计代理为当前控制器<UIAccelerometerDelegate>    [acce setDelegate:self];}#pragma mark - 加速计方法// 更新小球的位置- (void)updateBallLocation{    // 需求驱动开发    // 1. 碰撞检测,要限制住小球的运动范围    // 首先取出小球的当前位置    CGPoint center = [_ballView center];    // 需要记录一个小球的半径,以便于后续的碰撞检测计算    CGFloat r = _ballView.frame.size.width / 2;    // 需要考虑哪些问题    // 1.1 考虑水平方向小球的位置    if (center.x < r) {// 判断是不是碰到屏幕最左边,翻转x方向速度,即反弹向右运动        // 模拟弹性衰减,速度*0.8        _ballVelocity.x = 0.8 * abs(_ballVelocity.x);    } else if (center.x > self.view.bounds.size.width - r) {// 判断是不是碰到屏幕最右边,翻转x方向速度,即反弹向左运动        //模拟弹性衰减 速度*0.8        _ballVelocity.x = -0.8 * abs(_ballVelocity.x);    }    // 1.2 考虑垂直方向的小球位置    if (center.y < r) {// 判断是不是碰到屏幕最顶边,翻转y方向速度,即反弹向下运动        // 模拟弹性衰减,速度*0.8        _ballVelocity.y = 0.8 * abs(_ballVelocity.y);    } else if (center.y > self.view.bounds.size.height - r) {// 判断是不是碰到屏幕最底边,翻转y方向速度,即反弹向上运动        // 模拟弹性衰减,速度*0.8        _ballVelocity.y = -0.8 * abs(_ballVelocity.y);    }    // 2. 通过变化后的速度,设置小球最新的位置    // 用小球当前的位置+速度变化就可以计算出新的位置了//    CGPoint center = [_ballView center];    [_ballView setCenter:CGPointMake(center.x + _ballVelocity.x,center.y + _ballVelocity.y)];}// 加速计代理方法,每隔指定频率,就会调用- (void)accelerometer:(UIAccelerometer *)accelerometerdidAccelerate:(UIAcceleration *)acceleration{/*acceleration加速对象包含:x,y,z和timestamp四个属性,其中x,y,z是设备在这三个方向上的重力加速度,单位g,最后一个极少用*/    // 通过NSLog我们得到了加速计的数据,下面要做的仅是变化小球位置    NSLog(@"%@", acceleration);    // 1. 加速计过来的数据是加速度,加速度是修改速度的,因此,需要定义一个小球的速度    //    通过加速计的数据,更新小球速度的变化数值    _ballVelocity.x += acceleration.x;    // 千万注意:在加速计坐标系中Y轴方向和UIKit坐标系中的Y轴方向是相反的。!!!!!!    _ballVelocity.y -= acceleration.y;// 调用自定义方法更新小球位置    [self updateBallLocation];}@end

H:/0802/02_MotionManager+小球位置修复+碰撞检测_ViewController.h
////  ViewController.h//  加速计02.CoreMotion Push演练////  Created by apple on 13-8-2.//  Copyright (c) 2013年 itcast. All rights reserved.//#import <UIKit/UIKit.h>@interface ViewController : UIViewController// 模拟小球视图@property (weak, nonatomic) IBOutlet UIView *ballView;@end

H:/0802/02_MotionManager+小球位置修复+碰撞检测_ViewController.m
//  ViewController.m//  加速计02.CoreMotion Push演练//  Created by apple on 13-8-2.//  Copyright (c) 2013年 itcast. All rights reserved.// 注意重点问题,小球会贴在屏幕边上// 原因是碰到屏幕的瞬间,可能已经超出屏幕一点点了// 而此时没有重力,而加速度又特别小的时候,即速度*0.8也很小,// 不足以抵消小球嵌入屏幕外边的距离时,这时,小球新的坐标,仍然在屏幕外边,// 最终导致小球嵌在槽里面,出不来了// 此时,需要手动做一个小球位置的修复!#import "ViewController.h"// 需要导入第3方框架#import <CoreMotion/CoreMotion.h>@interface ViewController (){    // 运动管理器,必须是成员变量,不能是局部变量    CMMotionManager *motionManger;    // 小球速度    CGPoint _ballVelocity;}@end@implementation ViewController// 更新小球的位置- (void)updateBallLocation{    // 需求驱动开发    // 1. 碰撞检测,要限制住小球的运动范围    // 首先取出小球的当前位置    CGPoint center = [_ballView center];    // 需要记录一个小球的半径,以便于后续的碰撞检测计算    CGFloat r = _ballView.frame.size.width / 2;NSLog(@"小球的中心点---%@", NSStringFromCGPoint(center));    NSLog(@"速度---%@", NSStringFromCGPoint(_ballVelocity));    // 注意重点问题,小球会贴在屏幕边上// 原因是碰到屏幕的瞬间,可能已经超出屏幕一点点了// 而此时没有重力,而加速度又特别小的时候,即速度*0.8也很小,// 不足以抵消小球嵌入屏幕外边的距离时,这时,小球新的坐标,仍然在屏幕外边,// 最终导致小球嵌在槽里面,出不来了// 此时,需要手动做一个小球位置的修复!    if (center.x < r) {// 判断是不是碰到屏幕最左边,翻转x方向速度,即反弹向右运动        // 模拟弹性衰减,速度*0.8        _ballVelocity.x = 0.8 * abs(_ballVelocity.x);        // 修复小球位置        center.x = r;    } else if (center.x > self.view.bounds.size.width - r) {// 判断是不是碰到屏幕最右边,翻转x方向速度,即反弹向左运动        // 模拟弹性衰减,速度*0.8        _ballVelocity.x = -0.8 * abs(_ballVelocity.x);        // 修复小球位置        center.x = self.view.bounds.size.width - r;    }    if (center.y < r) {// 判断是不是碰到屏幕最顶边,翻转y方向速度,即反弹向下运动        // 模拟弹性衰减,速度*0.8        _ballVelocity.y = 0.8 * abs(_ballVelocity.y);        center.y = r;    } else if (center.y > self.view.bounds.size.height - r) {// 判断是不是碰到屏幕最底边,翻转y方向速度,即反弹向上运动        // 模拟弹性衰减,速度*0.8        _ballVelocity.y = -0.8 * abs(_ballVelocity.y);        center.y = self.view.bounds.size.height - r;    }    // 2. 通过变化后的速度,设置小球最新的位置    //    用小球当前的位置+速度变化就可以计算出新的位置了    //    CGPoint center = [_ballView center];    [_ballView setCenter:CGPointMake(center.x + _ballVelocity.x,center.y + _ballVelocity.y)];    CGFloat x = center.x + _ballVelocity.x;    CGFloat y = center.y + _ballVelocity.y;    NSLog(@"更新的小球的中心点---%@", NSStringFromCGPoint(CGPointMake(x, y)));}- (void)viewDidLoad{    [super viewDidLoad];    //    1. alloc init实例化Motion管理器    motionManger = [[CMMotionManager alloc]init];    //    2. 判断加速度传感器是否可用    if ([motionManger isAccelerometerAvailable]) {        //    3. 设定传感器数据更新频率        //    传感器目前最大采集频率是 100 Hz,而显示屏的刷新是60HZ        [motionManger setAccelerometerUpdateInterval:1 / 30];        //    4. startAccelerometerUpdatesToQueue//开启加速传感器更新到主线程队列以,Push方式,通过block指定更新Handle        [motionManger startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue]withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {            // 注意:这里如果直接Log,是不会有反应的,需要使用一下Data,才会有反应            // 更新小球速度            // 根据运行情况,加速度数值实在太大,我们需要修正一下            _ballVelocity.x += accelerometerData.acceleration.x / 10;// 加速计的Y轴与UI的坐标中Y轴相反            _ballVelocity.y -= accelerometerData.acceleration.y / 10;                        CGPoint a = CGPointMake(accelerometerData.acceleration.x / 10,-accelerometerData.acceleration.y / 10);            NSLog(@"加速度---%@", NSStringFromCGPoint(a));            //[_ballView setCenter:CGPointMake(_ballView.center.x + _ballVelocity.x,//_ballView.center.y + _ballVelocity.y)];// 调用自定义方法,更新小球位置,(需做碰撞检测)            [self updateBallLocation];        }];    } else {        NSLog(@"没有传感器");    }}@end

H:/0802/03_dispatch_once生成CMMotionManager单例+小球位置修正+碰撞检测_AppDelegate.h
//  AppDelegate.h//  加速计02.CoreMotion Push演练//  Created by apple on 13-8-2.//  Copyright (c) 2013年 itcast. All rights reserved.#import <UIKit/UIKit.h>//需要导入第3方框架#import <CoreMotion/CoreMotion.h>@interface AppDelegate : UIResponder <UIApplicationDelegate>@property (strong, nonatomic) UIWindow *window;// 单例,共享的运动管理器,定义在AppDelegate里面,保证所有controller都能用@property (strong, nonatomic, readonly) CMMotionManager *sharedMotionManager;@end

H:/0802/03_dispatch_once生成CMMotionManager单例+小球位置修正+碰撞检测_AppDelegate.m
//  AppDelegate.m//  加速计02.CoreMotion Push演练//  Created by apple on 13-8-2.//  Copyright (c) 2013年 itcast. All rights reserved.//  dispatch_once生成CMMotionManager单例模板代码#import "AppDelegate.h"@interface AppDelegate(){    CMMotionManager *_montionManager;}@end@implementation AppDelegate#pragma mark - 成员变量sharedMotionManager的Getter方法,返回创建的运动管理器单例// 单例,共享的运动管理器,定义在AppDelegate里面,保证所有controller都能用- (CMMotionManager *)sharedMotionManager{    // 重点!!!!!!!!直接打dispatch_one定义单例//静态的泛型,自动生成,做标记用    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        _montionManager = [[CMMotionManager alloc]init];    });    return _montionManager;}- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{    return YES;}- (void)applicationWillResignActive:(UIApplication *)application{}- (void)applicationDidEnterBackground:(UIApplication *)application{}- (void)applicationWillEnterForeground:(UIApplication *)application{}- (void)applicationDidBecomeActive:(UIApplication *)application{}- (void)applicationWillTerminate:(UIApplication *)application{}@end

H:/0802/03_dispatch_once生成CMMotionManager单例+小球位置修正+碰撞检测_ViewController.h
////  ViewController.h//  加速计02.CoreMotion Push演练////  Created by apple on 13-8-2.//  Copyright (c) 2013年 itcast. All rights reserved.//#import <UIKit/UIKit.h>@interface ViewController : UIViewController// 模拟小球视图@property (weak, nonatomic) IBOutlet UIView *ballView;@end

H:/0802/03_dispatch_once生成CMMotionManager单例+小球位置修正+碰撞检测_ViewController.m
//  ViewController.m//  加速计02.CoreMotion Push演练//  Created by apple on 13-8-2.//  Copyright (c) 2013年 itcast. All rights reserved./*已经在AppDelegate.h文件中导入了第3方框架<CoreMotion/CoreMotion.h>使用到AppDelegate.m文件中dispatch_once代码生成的单例 _montionManager*/#import "ViewController.h"#import "AppDelegate.h"@interface ViewController (){    // 运动管理器    CMMotionManager *motionManger;    // 小球速度    CGPoint _ballVelocity;}@end@implementation ViewController- (void)viewDidLoad{    [super viewDidLoad];    //    1. 获取AppDelegate中定义的运动管理器实例    AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];    motionManger = [appDelegate sharedMotionManager];    [self startAccelerometer];}// 自定义,启动加速计方法,从ViewDidLoad方法中抽取- (void)startAccelerometer{    //    2. 判断传感器是否可用    if ([motionManger isAccelerometerAvailable]) {        //    3. 设定传感器数据更新频率        //    传感器目前最大采集频率是 100 Hz        [motionManger setAccelerometerUpdateInterval:1 / 30];        //    4. 启动传感器更新,Push方式更新数据        [motionManger startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue]withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {            // 注意:这里如果直接Log,是不会有反应的,需要使用一下Data,才会有反应            // 更新小球速度            // 根据运行情况,加速度数值实在太大,我们需要修正一下            _ballVelocity.x += accelerometerData.acceleration.x / 10;            _ballVelocity.y -= accelerometerData.acceleration.y / 10;            //加速度 打印一下            CGPoint a = CGPointMake(accelerometerData.acceleration.x / 10,-accelerometerData.acceleration.y / 10);            NSLog(@"加速度---%@", NSStringFromCGPoint(a));                        // 更新小球位置            // 需要做一个碰撞检测            //            [_ballView setCenter:CGPointMake(_ballView.center.x + _ballVelocity.x,//_ballView.center.y + _ballVelocity.y)];//调用 自定义方法,更新小球位置            [self updateBallLocation];        }];    } else {        NSLog(@"没有传感器");    }}// 自定义方法,更新小球的位置- (void)updateBallLocation{    // 需求驱动开发    // 1. 碰撞检测,要限制住小球的运动范围    // 首先取出小球的当前位置    CGPoint center = [_ballView center];    // 需要记录一个小球的半径,以便于后续的碰撞检测计算    CGFloat r = _ballView.frame.size.width / 2;NSLog(@"小球的中心点---%@", NSStringFromCGPoint(center));    NSLog(@"速度---%@", NSStringFromCGPoint(_ballVelocity));    // 注意重点问题,小球会贴在屏幕边上// 原因是碰到屏幕的瞬间,可能已经超出屏幕一点点了// 而此时没有重力,而加速度又特别小的时候,即速度*0.8也很小,// 不足以抵消小球嵌入屏幕外边的距离时,这时,小球新的坐标,仍然在屏幕外边,// 最终导致小球嵌在槽里面,出不来了// 此时,需要手动做一个小球位置的修复!    if (center.x < r) {        // 翻转x方向速度        _ballVelocity.x = 0.8 * abs(_ballVelocity.x);        // 修复小球位置        center.x = r;    } else if (center.x > self.view.bounds.size.width - r) {        _ballVelocity.x = -0.8 * abs(_ballVelocity.x);        // 修复小球位置        center.x = self.view.bounds.size.width - r;    }    // 1.2 考虑垂直方向的小球位置    if (center.y < r) {        _ballVelocity.y = 0.8 * abs(_ballVelocity.y);// 修复小球位置        center.y = r;    } else if (center.y > self.view.bounds.size.height - r) {        _ballVelocity.y = -0.8 * abs(_ballVelocity.y);// 修复小球位置        center.y = self.view.bounds.size.height - r;    }//    //    NSLog(@"小球的中心点---%@", NSStringFromCGPoint(center));//    NSLog(@"速度---%@", NSStringFromCGPoint(_ballVelocity));    // 2. 通过变化后的速度,设置小球最新的位置    // 用小球当前的位置+速度变化就可以计算出新的位置了    [_ballView setCenter:CGPointMake(center.x + _ballVelocity.x, center.y + _ballVelocity.y)];    CGFloat x = center.x + _ballVelocity.x;    CGFloat y = center.y + _ballVelocity.y;    NSLog(@"更新的小球的中心点---%@", NSStringFromCGPoint(CGPointMake(x, y)));}#pragma mark - 点击屏幕,让小球停止// 1. 触摸事件 Began事件,需要终端加速计的数据采集工作- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    // 判断加速计是否在采集数据    // 如果是在采集,我们需要把加速计停止    if ([motionManger isAccelerometerActive]) {        [motionManger stopAccelerometerUpdates];    } else {// 调用自定义的启动加速计方法        [self startAccelerometer];    }}@end

0 0
原创粉丝点击