描述:用CoreMontion加速计控制小球的运动,通过屏幕触摸,暂停和恢复。
步骤
1. 添加MontionManager和CADisplayLink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 |
- ( 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单例,方便使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 |
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. 采样方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
- ( 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. 更改小球位置、
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 |
- ( 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 触摸停止/启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 |
- ( 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 ]; } } |
原文:http://www.cnblogs.com/dqxu/p/3595762.html