描述:用CoreMontion加速计控制小球的运动,通过屏幕触摸,暂停和恢复。
步骤
1. 添加MontionManager和CADisplayLink
- (void)viewDidLoad{ [super viewDidLoad]; // 添加小球 UIImage *image = [UIImage imageNamed:@"black"]; _ball = [[UIImageView alloc] initWithImage:image]; _ball.center = self.view.center; [self.view addSubview:_ball]; _ballVelocity = CGPointZero; _queue = [[NSOperationQueue alloc] init]; // 运动管理器方法 // 1) 实例化运动管理器MyMontionManager *montionManager = [MyMontionManager sharedMyMontionManager]; // 2) 判断加速计是否可用 if (montionManager.isAccelerometerAvailable) { // 3) 设置采样数据的时间间隔 montionManager.accelerometerUpdateInterval = 1 / 60.0; // 4)开始采样数据 [self startAccelerometerUpdates]; } else { NSLog(@"摔坏了"); } // 实例化游戏时钟 防止小球虚化显示 montionManager负责采集,CADisplayLink 负责显示_gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateLocation)]; // 将时钟添加到主运行循环中[_gameTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];}
2. 设置MontionManager单例,方便使用
static MyMontionManager *_instance;@implementation MyMontionManager+ (id)allocWithZone:(struct _NSZone *)zone{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance;}+ (instancetype)sharedMyMontionManager{ if (_instance == nil) { _instance = [[MyMontionManager alloc] init]; } return _instance;}@end
3. 采样方法
- (void)startAccelerometerUpdates{ // 操作队列是负责处理采样的数据[[MyMontionManager sharedMyMontionManager] startAccelerometerUpdatesToQueue:_queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { // 处理采样数据,修改小球速度 _ballVelocity.x += accelerometerData.acceleration.x; _ballVelocity.y -= accelerometerData.acceleration.y; NSLog(@"%@", [NSThread currentThread]); }];}
4. 更改小球位置、
- (void)updateLocation{ NSLog(@"==== %@", [NSThread currentThread]); // 设置小球的位置 CGPoint center = _ball.center; CGSize size = self.view.bounds.size; // 解决小球出界问题,碰撞检测 // 水平方向:左边,右边 if (CGRectGetMinX(_ball.frame) <= 0 || CGRectGetMaxX(_ball.frame) >= size.width) { // 修改小球的速度方向 _ballVelocity.x *= -1; // 修复位置 < 0 if (CGRectGetMinX(_ball.frame) <= 0) { center.x = _ball.bounds.size.width / 2.0; } else { center.x = size.width - _ball.bounds.size.width / 2.0; } } // 垂直方向 if (CGRectGetMinY(_ball.frame) <= 0 || CGRectGetMaxY(_ball.frame) >= size.height) { // 修改小球的速度方向 _ballVelocity.y *= -1; // 修复位置 < 0 if (CGRectGetMinY(_ball.frame) <= 0) { center.y = _ball.bounds.size.height / 2.0; } else { center.y = size.height - _ball.bounds.size.height / 2.0; } } center.x += _ballVelocity.x; center.y += _ballVelocity.y; _ball.center = center; //在mainloop中,所以不需要队列}
5 触摸停止/启动
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // 正在采样数据,说明游戏进行中,暂停if ([MyMontionManager sharedMyMontionManager].isAccelerometerActive) { // 定制采样数据 [[MyMontionManager sharedMyMontionManager] stopAccelerometerUpdates]; // 停止时钟 // invalidate停止时钟 // 1> 将时钟从主运行循环中撤销 // 2> 将时钟销毁// [_gameTimer invalidate]; // 直接从主运行循环中将游戏时钟删除,而不会销毁时钟,等到需要时再次添加即可。 [_gameTimer removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } else { // 开始采样加速计数据 [self startAccelerometerUpdates]; [_gameTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } }