标签:
iPhone三代(iPhone3GS)
iPhone4
iPhone4S
iPhone5
2013年9月发布iphone5s
iPad做游戏是必用的!否则不一定用到
iPad1
iPad2
The new iPad
iPad4
Apple TV(不在大陆销售)
// // ViewController.h // 打砖块小游戏 // // Created by 大帅 on 14-12-21. // Copyright (c) 2014年 dashuai. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController //按住 ctrl 健进行拖拽,连接outlet //小球 @property (weak, nonatomic) IBOutlet UIImageView *ballImage; //挡板 @property (weak, nonatomic) IBOutlet UIImageView *paddleImage; //砖块的集合 @property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *blocksImage; @end
让小球动起来
要求;在屏幕的任意位置点击一下,小球就会跳起来。如图是4和4s 的坐标图
要注意,iphone 的坐标里 y 向下增长,故小球向上打出去,y 方向是负数。且苹果开发中,考虑的是点的概念,而不是像素的概念!记住,4和4s 是320x480的大小。
m 文件的代码如下:
1 // 2 // ViewController.m 3 // 打砖块小游戏 4 // 5 // Created by 大帅 on 14-12-21. 6 // Copyright (c) 2014年 dashuai. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 //引入动画框架 QuartzCore 11 #import <QuartzCore/QuartzCore.h> 12 13 //私有的变量,在 m 文件里定义一下 14 @interface ViewController () 15 { 16 //游戏开始的标志 17 BOOL _isPlaying; 18 19 //定义游戏的时钟 20 CADisplayLink *_gameTimer; 21 22 //定义小球的速度,_ballV来表示 23 CGPoint _ballV; 24 } 25 //游戏时钟的处理方法,对外不可见,应该定义在点m 文件里 26 - (void)step:(CADisplayLink *)sender; 27 28 @end 29 30 @implementation ViewController 31 32 - (void)viewDidLoad { 33 [super viewDidLoad]; 34 // Do any additional setup after loading the view, typically from a nib. 35 } 36 37 - (void)didReceiveMemoryWarning { 38 [super didReceiveMemoryWarning]; 39 // Dispose of any resources that can be recreated. 40 } 41 42 //游戏时钟的处理方法, 因为对外不可见,故定义在 点m 文件里,而不是头文件里 43 - (void)step:(CADisplayLink *)sender 44 { 45 //让求(小球的图)动起来,本质 是 设置小球的 位置(也就是更新小球的位置的状态) 46 //小球中心点的 x 位置加上小球中心点的 x 方向的速度 47 //小球中心点的 y 位置加上小球中心点的 y 方向的速度 48 [_ballImage setCenter:CGPointMake(_ballImage.center.x + _ballV.x, _ballImage.center.y + _ballV.y)]; 49 //可以打印测试下,游戏时钟的方法是否是每秒钟运行60次 50 NSLog(@"游戏运行了~");//后期去掉 51 } 52 53 //触摸事件的实现 54 //触摸结束(手指抬起之后),游戏开始,小球动起来,这里的方法是支持多点触摸的 55 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *) event 56 { 57 //先判断本游戏是否已经开始了,如果游戏还没有开始: 58 if (!_isPlaying) { 59 //考虑一个点的触摸,获取触摸的对象 60 // UITouch *touch = [touches anyObject];//暂时用不到 61 62 // 触摸之后,给小球一个初始速度,0,-5, 63 //-5就是 y 向下的过程,每一次时钟触发的时候,y 都减去5 64 _ballV = CGPointMake(0, -5); 65 66 //定义游戏时钟 67 //通过函数名来调用头文件里定义的另外的方法 step: 方法,时钟的目标是自己 68 _gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step:)]; 69 70 //把当前时钟添加到游戏里经典的应用循环中,ios默认提供的循环方法 71 [_gameTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 72 73 //勿忘修改游戏状态的标识 74 //表面本游戏已经开始了 75 _isPlaying = YES; 76 } 77 } 78 79 @end
屏幕刷新频率的概念
每秒钟,屏幕上的所有的点被重新绘制的次数。而苹果设备的屏幕刷新频率,大概每秒是将近60次,或多或少。
而在本游戏里,给小球设置的初试速度,也就是初试移动位置是(0, -5),那么每秒钟小球就跑出了300左右的点的距离。表现的就是小球飞了!
程序运行发现:
1 2014-12-30 18:39:04.064 打砖块小游戏[4498:129623] 游戏运行了~ 2 2014-12-30 18:39:04.082 打砖块小游戏[4498:129623] 游戏运行了~ 3 2014-12-30 18:39:04.099 打砖块小游戏[4498:129623] 游戏运行了~ 4 2014-12-30 18:39:04.114 打砖块小游戏[4498:129623] 游戏运行了~ 5 2014-12-30 18:39:04.132 打砖块小游戏[4498:129623] 游戏运行了~ 6 2014-12-30 18:39:04.148 打砖块小游戏[4498:129623] 游戏运行了~ 7 2014-12-30 18:39:04.165 打砖块小游戏[4498:129623] 游戏运行了~ 8 2014-12-30 18:39:04.181 打砖块小游戏[4498:129623] 游戏运行了~ 9 2014-12-30 18:39:04.199 打砖块小游戏[4498:129623] 游戏运行了~ 10 2014-12-30 18:39:04.215 打砖块小游戏[4498:129623] 游戏运行了~ 11 2014-12-30 18:39:04.232 打砖块小游戏[4498:129623] 游戏运行了~ 12 2014-12-30 18:39:04.249 打砖块小游戏[4498:129623] 游戏运行了~ 13 2014-12-30 18:39:04.264 打砖块小游戏[4498:129623] 游戏运行了~ 14 2014-12-30 18:39:04.281 打砖块小游戏[4498:129623] 游戏运行了~ 15 2014-12-30 18:39:04.299 打砖块小游戏[4498:129623] 游戏运行了~ 16 2014-12-30 18:39:04.315 打砖块小游戏[4498:129623] 游戏运行了~ 17 2014-12-30 18:39:04.331 打砖块小游戏[4498:129623] 游戏运行了~ 18 2014-12-30 18:39:04.349 打砖块小游戏[4498:129623] 游戏运行了~ 19 2014-12-30 18:39:04.365 打砖块小游戏[4498:129623] 游戏运行了~ 20 2014-12-30 18:39:04.381 打砖块小游戏[4498:129623] 游戏运行了~ 21 2014-12-30 18:39:04.398 打砖块小游戏[4498:129623] 游戏运行了~ 22 2014-12-30 18:39:04.415 打砖块小游戏[4498:129623] 游戏运行了~ 23 2014-12-30 18:39:04.431 打砖块小游戏[4498:129623] 游戏运行了~ 24 2014-12-30 18:39:04.448 打砖块小游戏[4498:129623] 游戏运行了~ 25 2014-12-30 18:39:04.465 打砖块小游戏[4498:129623] 游戏运行了~ 26 2014-12-30 18:39:04.481 打砖块小游戏[4498:129623] 游戏运行了~ 27 2014-12-30 18:39:04.498 打砖块小游戏[4498:129623] 游戏运行了~ 28 2014-12-30 18:39:04.514 打砖块小游戏[4498:129623] 游戏运行了~ 29 2014-12-30 18:39:04.532 打砖块小游戏[4498:129623] 游戏运行了~ 30 2014-12-30 18:39:04.548 打砖块小游戏[4498:129623] 游戏运行了~ 31 2014-12-30 18:39:04.564 打砖块小游戏[4498:129623] 游戏运行了~ 32 2014-12-30 18:39:04.581 打砖块小游戏[4498:129623] 游戏运行了~ 33 2014-12-30 18:39:04.598 打砖块小游戏[4498:129623] 游戏运行了~ 34 2014-12-30 18:39:04.614 打砖块小游戏[4498:129623] 游戏运行了~ 35 2014-12-30 18:39:04.631 打砖块小游戏[4498:129623] 游戏运行了~ 36 2014-12-30 18:39:04.648 打砖块小游戏[4498:129623] 游戏运行了~ 37 2014-12-30 18:39:04.664 打砖块小游戏[4498:129623] 游戏运行了~ 38 2014-12-30 18:39:04.682 打砖块小游戏[4498:129623] 游戏运行了~ 39 2014-12-30 18:39:04.698 打砖块小游戏[4498:129623] 游戏运行了~ 40 2014-12-30 18:39:04.715 打砖块小游戏[4498:129623] 游戏运行了~ 41 2014-12-30 18:39:04.731 打砖块小游戏[4498:129623] 游戏运行了~ 42 2014-12-30 18:39:04.748 打砖块小游戏[4498:129623] 游戏运行了~ 43 2014-12-30 18:39:04.764 打砖块小游戏[4498:129623] 游戏运行了~ 44 2014-12-30 18:39:04.781 打砖块小游戏[4498:129623] 游戏运行了~ 45 2014-12-30 18:39:04.798 打砖块小游戏[4498:129623] 游戏运行了~ 46 2014-12-30 18:39:04.815 打砖块小游戏[4498:129623] 游戏运行了~ 47 2014-12-30 18:39:04.831 打砖块小游戏[4498:129623] 游戏运行了~ 48 2014-12-30 18:39:04.848 打砖块小游戏[4498:129623] 游戏运行了~ 49 2014-12-30 18:39:04.865 打砖块小游戏[4498:129623] 游戏运行了~ 50 2014-12-30 18:39:04.881 打砖块小游戏[4498:129623] 游戏运行了~ 51 2014-12-30 18:39:04.898 打砖块小游戏[4498:129623] 游戏运行了~ 52 2014-12-30 18:39:04.914 打砖块小游戏[4498:129623] 游戏运行了~ 53 2014-12-30 18:39:04.932 打砖块小游戏[4498:129623] 游戏运行了~ 54 2014-12-30 18:39:04.948 打砖块小游戏[4498:129623] 游戏运行了~ 55 2014-12-30 18:39:04.964 打砖块小游戏[4498:129623] 游戏运行了~ 56 2014-12-30 18:39:04.981 打砖块小游戏[4498:129623] 游戏运行了~ 57 2014-12-30 18:39:04.999 打砖块小游戏[4498:129623] 游戏运行了~
大概是57次/每秒钟,差不多就是前面分析的那样,在本游戏里,是可以被接受的!不是太快,也不是太慢,刚刚好。屏幕点击之后,小球就飞出去了。
碰撞检测
1、要知道这个物理公式:位移 = 时间 * 速度
2、时钟处理的流程图
3、在做小球的碰撞检测的时候,要知道这个图的含义
代码如下
1 // 2 // ViewController.m 3 // 打砖块小游戏 4 // 5 // Created by 大帅 on 14-12-21. 6 // Copyright (c) 2014年 dashuai. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 //引入动画框架 QuartzCore 11 #import <QuartzCore/QuartzCore.h> 12 13 //私有的变量,在 m 文件里定义一下 14 @interface ViewController () 15 { 16 //游戏开始的标志 17 BOOL _isPlaying; 18 19 //定义游戏的时钟 20 CADisplayLink *_gameTimer; 21 22 //定义小球的速度,_ballV来表示 23 CGPoint _ballV; 24 } 25 //游戏时钟的处理方法,对外不可见,应该定义在点m 文件里 26 - (void)step:(CADisplayLink *)sender; 27 28 //检测和屏幕边缘的碰撞 29 - (BOOL)checkWithScreen; 30 31 //检测和砖块的碰撞 32 - (BOOL)checkWithBlocks; 33 34 //检测和挡板的碰撞 35 - (void)checkWithPaddle; 36 37 //重置游戏的状态 38 //游戏胜利,失败的状态 39 - (void)resetGamesStateWithMessage:(NSString *)message; 40 41 @end 42 43 @implementation ViewController 44 45 - (void)viewDidLoad { 46 [super viewDidLoad]; 47 // Do any additional setup after loading the view, typically from a nib. 48 } 49 50 - (void)didReceiveMemoryWarning { 51 [super didReceiveMemoryWarning]; 52 // Dispose of any resources that can be recreated. 53 } 54 55 //游戏的重置方法的实现 56 - (void)resetGamesStateWithMessage:(NSString *)message 57 { 58 NSLog(@"%@", message); 59 _isPlaying = NO; 60 //屏幕的中间位置 x是160 61 //把小球设置到中间 62 [_ballImage setCenter:CGPointMake(160, 430)]; 63 //把挡板设置到中间位置也 64 [_paddleImage setCenter:CGPointMake(160, 450)]; 65 //把时钟清除也就是关掉,千万不要忘记,否则后果很严重!不亚于内存泄露的错误! 66 [_gameTimer invalidate]; 67 } 68 69 //小球和屏幕的碰撞检测方法实现 70 - (BOOL)checkWithScreen 71 { 72 //除了下方的屏幕边缘,其他的都是反弹回来,而下方是掉出去,游戏失败 73 BOOL gameOver = NO; 74 75 //左边碰撞检测的处理,比较简单,因为屏幕的原点就是在左边的线上 76 if ([_ballImage frame].origin.x <= 0) { 77 //反弹回去,就是把它取正数,x 方向的速度变为正数,使用绝对值函数 78 _ballV.x = abs(_ballV.x); 79 } 80 81 //右边碰撞检测处理,小球边框的距离原点的 x 加上小球本身的宽度,如果大于了视图本身边框的宽度的尺寸,那就是碰撞 82 if ([_ballImage frame].origin.x + [_ballImage frame].size.width >= self.view.frame.size.width) { 83 //反弹,就是保证小球 x 方向的速度必须为负的 84 _ballV.x = -1 * abs(_ballV.x); 85 } 86 87 //顶部屏幕的碰撞检测处理 88 if ([_ballImage frame].origin.y <= 0) { 89 _ballV.y = abs(_ballV.y); 90 } 91 92 //底部碰撞检测处理 93 if ([_ballImage frame].origin.y + [_ballImage frame].size.height >= self.view.frame.size.height) { 94 gameOver = YES; 95 } 96 97 return gameOver; 98 } 99 100 //小球和方块的碰撞检测方法的实现 101 - (BOOL)checkWithBlocks 102 { 103 BOOL gameWin = NO; 104 105 //所有的在砖块集合里的砖块的碰撞检测 106 for (UIImageView *block in _blocksImage) { 107 //苹果提供了一个 bool 类型的矩形碰撞检测函数 108 //如果两个矩形重叠了(也就是碰撞了),函数反悔 YES,否则返回 NO 109 //同时只检测,那些没有被隐藏的砖块,已经隐藏的就不需要碰撞检测了 110 if (CGRectIntersectsRect([block frame], [_ballImage frame]) && ![block isHidden]) { 111 //碰撞就消除砖块,其实是隐藏砖块的图像 112 [block setHidden:YES]; 113 //碰撞完成之后,要让小球向下运动 114 _ballV.y = abs(_ballV.y); 115 //保证循环的效率,提前退出循环 116 break; 117 } 118 } 119 120 //判断游戏是否胜利的逻辑 121 int count = 0; 122 123 for (UIImageView *block in _blocksImage) { 124 if ([block isHidden]) { 125 count++; 126 } 127 } 128 129 if (count == [_blocksImage count]) { 130 gameWin = YES; 131 } 132 133 return gameWin; 134 } 135 136 //小球和挡板的碰撞检测方法 137 - (void)checkWithPaddle 138 { 139 //如果小球和挡板碰撞 140 if (CGRectIntersectsRect([_ballImage frame], [_paddleImage frame])) { 141 //强制把小球 y 方向的速度设为负数,让它反弹回去 142 _ballV.y = -1 * abs(_ballV.y); 143 } 144 } 145 146 //游戏时钟的处理方法, 因为对外不可见,故定义在 点m 文件里,而不是头文件里 147 - (void)step:(CADisplayLink *)sender 148 { 149 //让求(小球的图)动起来,本质 是 设置小球的 位置(也就是更新小球的位置的状态) 150 //小球中心点的 x 位置加上小球中心点的 x 方向的速度 151 //小球中心点的 y 位置加上小球中心点的 y 方向的速度 152 [_ballImage setCenter:CGPointMake(_ballImage.center.x + _ballV.x, _ballImage.center.y + _ballV.y)]; 153 //可以打印测试下,游戏时钟的方法是否是每秒钟运行60次 154 //NSLog(@"游戏运行了~"); 155 156 //在游戏时钟处理方法里,调用碰撞检测方法 157 if ([self checkWithScreen]) { 158 [self resetGamesStateWithMessage:@"游戏结束!"]; 159 } 160 161 if ([self checkWithBlocks]) { 162 [self resetGamesStateWithMessage:@"游戏胜利!"]; 163 } 164 165 [self checkWithPaddle]; 166 167 } 168 169 //触摸事件的实现 170 //触摸结束(手指抬起之后),游戏开始,小球动起来,这里的方法是支持多点触摸的 171 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *) event 172 { 173 //先判断本游戏是否已经开始了,如果游戏还没有开始: 174 if (!_isPlaying) { 175 //考虑一个点的触摸,获取触摸的对象 176 // UITouch *touch = [touches anyObject];//暂时用不到 177 178 // 触摸之后,给小球一个初始速度,0,-5, 179 //-5就是 y 向下的过程,每一次时钟触发的时候,y 都减去5 180 _ballV = CGPointMake(0, -5); 181 182 //定义游戏时钟 183 //通过函数名来调用头文件里定义的另外的方法 step: 方法,时钟的目标是自己 184 _gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step:)]; 185 186 //把当前时钟添加到游戏里经典的应用循环中,ios默认提供的循环方法 187 [_gameTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 188 189 //勿忘修改游戏状态的标识 190 //表面本游戏已经开始了 191 _isPlaying = YES; 192 } 193 } 194 195 @end
挡板移动的处理
如下代码:
1 // 2 // ViewController.m 3 // 打砖块小游戏 4 // 5 // Created by 大帅 on 14-12-21. 6 // Copyright (c) 2014年 dashuai. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 //引入动画框架 QuartzCore 11 #import <QuartzCore/QuartzCore.h> 12 13 //私有的变量,在 m 文件里定义一下 14 @interface ViewController () 15 { 16 //游戏开始的标志 17 BOOL _isPlaying; 18 19 //定义游戏的时钟 20 CADisplayLink *_gameTimer; 21 22 //定义小球的速度,_ballV来表示 23 CGPoint _ballV; 24 25 //水平位移 26 CGFloat _deltaX; 27 } 28 29 //游戏时钟的处理方法,对外不可见,应该定义在点m 文件里 30 - (void)step:(CADisplayLink *)sender; 31 32 //检测和屏幕边缘的碰撞 33 - (BOOL)checkWithScreen; 34 35 //检测和砖块的碰撞 36 - (BOOL)checkWithBlocks; 37 38 //检测和挡板的碰撞 39 - (void)checkWithPaddle; 40 41 //重置游戏的状态 42 //游戏胜利,失败的状态 43 - (void)resetGamesStateWithMessage:(NSString *)message; 44 45 @end 46 47 @implementation ViewController 48 49 - (void)viewDidLoad { 50 [super viewDidLoad]; 51 // Do any additional setup after loading the view, typically from a nib. 52 } 53 54 - (void)didReceiveMemoryWarning { 55 [super didReceiveMemoryWarning]; 56 // Dispose of any resources that can be recreated. 57 } 58 59 //游戏的重置方法的实现 60 - (void)resetGamesStateWithMessage:(NSString *)message 61 { 62 NSLog(@"%@", message); 63 _isPlaying = NO; 64 //屏幕的中间位置 x是160 65 //把小球设置到中间 66 [_ballImage setCenter:CGPointMake(160, 430)]; 67 //把挡板设置到中间位置也 68 [_paddleImage setCenter:CGPointMake(160, 450)]; 69 //把时钟清除也就是关掉,千万不要忘记,否则后果很严重!不亚于内存泄露的错误! 70 [_gameTimer invalidate]; 71 } 72 73 //小球和屏幕的碰撞检测方法实现 74 - (BOOL)checkWithScreen 75 { 76 //除了下方的屏幕边缘,其他的都是反弹回来,而下方是掉出去,游戏失败 77 BOOL gameOver = NO; 78 79 //左边碰撞检测的处理,比较简单,因为屏幕的原点就是在左边的线上 80 if ([_ballImage frame].origin.x <= 0) { 81 //反弹回去,就是把它取正数,x 方向的速度变为正数,使用绝对值函数 82 _ballV.x = abs(_ballV.x); 83 } 84 85 //右边碰撞检测处理,小球边框的距离原点的 x 加上小球本身的宽度,如果大于了视图本身边框的宽度的尺寸,那就是碰撞 86 if ([_ballImage frame].origin.x + [_ballImage frame].size.width >= self.view.frame.size.width) { 87 //反弹,就是保证小球 x 方向的速度必须为负的 88 _ballV.x = -1 * abs(_ballV.x); 89 } 90 91 //顶部屏幕的碰撞检测处理 92 if ([_ballImage frame].origin.y <= 0) { 93 _ballV.y = abs(_ballV.y); 94 } 95 96 //底部碰撞检测处理 97 if ([_ballImage frame].origin.y + [_ballImage frame].size.height >= self.view.frame.size.height) { 98 gameOver = YES; 99 } 100 101 return gameOver; 102 } 103 104 //小球和方块的碰撞检测方法的实现 105 - (BOOL)checkWithBlocks 106 { 107 BOOL gameWin = NO; 108 109 //所有的在砖块集合里的砖块的碰撞检测 110 for (UIImageView *block in _blocksImage) { 111 //苹果提供了一个 bool 类型的矩形碰撞检测函数 112 //如果两个矩形重叠了(也就是碰撞了),函数反悔 YES,否则返回 NO 113 //同时只检测,那些没有被隐藏的砖块,已经隐藏的就不需要碰撞检测了 114 if (CGRectIntersectsRect([block frame], [_ballImage frame]) && ![block isHidden]) { 115 //碰撞就消除砖块,其实是隐藏砖块的图像 116 [block setHidden:YES]; 117 //碰撞完成之后,要让小球向下运动 118 _ballV.y = abs(_ballV.y); 119 //保证循环的效率,提前退出循环 120 break; 121 } 122 } 123 124 //判断游戏是否胜利的逻辑 125 int count = 0; 126 127 for (UIImageView *block in _blocksImage) { 128 if ([block isHidden]) { 129 count++; 130 } 131 } 132 133 if (count == [_blocksImage count]) { 134 gameWin = YES; 135 } 136 137 return gameWin; 138 } 139 140 //小球和挡板的碰撞检测方法 141 - (void)checkWithPaddle 142 { 143 //如果小球和挡板碰撞 144 if (CGRectIntersectsRect([_ballImage frame], [_paddleImage frame])) { 145 //强制把小球 y 方向的速度设为负数,让它反弹回去 146 _ballV.y = -1 * abs(_ballV.y); 147 //给小球的 x 方向,加上水平的位移,让它能随着挡板的移动而水平的移动起来 148 _ballV.x += _deltaX; 149 } 150 } 151 152 //游戏时钟的处理方法, 因为对外不可见,故定义在 点m 文件里,而不是头文件里 153 - (void)step:(CADisplayLink *)sender 154 { 155 //让求(小球的图)动起来,本质 是 设置小球的 位置(也就是更新小球的位置的状态) 156 //小球中心点的 x 位置加上小球中心点的 x 方向的速度 157 //小球中心点的 y 位置加上小球中心点的 y 方向的速度 158 [_ballImage setCenter:CGPointMake(_ballImage.center.x + _ballV.x, _ballImage.center.y + _ballV.y)]; 159 //可以打印测试下,游戏时钟的方法是否是每秒钟运行60次 160 //NSLog(@"游戏运行了~"); 161 162 //在游戏时钟处理方法里,调用碰撞检测方法 163 if ([self checkWithScreen]) { 164 [self resetGamesStateWithMessage:@"游戏结束!"]; 165 } 166 167 if ([self checkWithBlocks]) { 168 [self resetGamesStateWithMessage:@"游戏胜利!"]; 169 } 170 171 [self checkWithPaddle]; 172 173 } 174 175 //触摸事件的实现 176 //触摸结束(手指抬起之后),游戏开始,小球动起来,这里的方法是支持多点触摸的 177 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *) event 178 { 179 //先判断本游戏是否已经开始了,如果游戏还没有开始: 180 if (!_isPlaying) { 181 //考虑一个点的触摸,获取触摸的对象 182 // UITouch *touch = [touches anyObject];//暂时用不到 183 184 // 触摸之后,给小球一个初始速度,0,-5, 185 //-5就是 y 向下的过程,每一次时钟触发的时候,y 都减去5 186 _ballV = CGPointMake(0, -5); 187 188 //定义游戏时钟 189 //通过函数名来调用头文件里定义的另外的方法 step: 方法,时钟的目标是自己 190 _gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step:)]; 191 192 //把当前时钟添加到游戏里经典的应用循环中,ios默认提供的循环方法 193 [_gameTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 194 195 //勿忘修改游戏状态的标识 196 //表面本游戏已经开始了 197 _isPlaying = YES; 198 } 199 } 200 201 //触摸移动的处理 202 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 203 { 204 if (_isPlaying) { 205 //获取手指移动的距离 206 UITouch *touch = [touches anyObject]; 207 208 //计算手指在 x 方向的移动举例 209 //方向分解 210 //本次触摸的位置 - 上次触摸的位置(x 方向的),就是水平方向的移动距离 211 //在声明里,定义一个成员变量,方便使用 212 //CGFloat deltaX = [touch locationInView:self.view].x - [touch previousLocationInView:self.view].x; 213 _deltaX = [touch locationInView:self.view].x - [touch previousLocationInView:self.view].x; 214 //挡板 x 方向的移动,y 方向不用管,不需要移动。 215 [_paddleImage setCenter:CGPointMake([_paddleImage center].x + _deltaX, [_paddleImage center].y)]; 216 } 217 } 218 219 @end
运行:
会出现,随着游戏的继续,小球速度越来越快!不合理!问题出在如下代码:在检测小球和挡板碰撞的方法里
//给小球的 x 方向,加上水平的位移,让它能随着挡板的移动而水平的移动起来 _ballV.x += _deltaX;
不符合物理常识,按照原则,应该修改为符合物理常识的碰撞和移动。
最后修正
每次手指离开屏幕之后,都把水平的距离变化设置为0,且代码其他一些善后操作要做一些修正。
比较粗糙的完整运行的代码,离着发布还有一定距离。
1 // 2 // ViewController.m 3 // 打砖块小游戏 4 // 5 // Created by 大帅 on 14-12-21. 6 // Copyright (c) 2014年 dashuai. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 //引入动画框架 QuartzCore 11 #import <QuartzCore/QuartzCore.h> 12 13 //私有的变量,在 m 文件里定义一下 14 @interface ViewController () 15 { 16 //游戏开始的标志 17 BOOL _isPlaying; 18 19 //定义游戏的时钟 20 CADisplayLink *_gameTimer; 21 22 //定义小球的速度,_ballV来表示 23 CGPoint _ballV; 24 25 //水平位移 26 CGFloat _deltaX; 27 } 28 29 //游戏时钟的处理方法,对外不可见,应该定义在点m 文件里 30 - (void)step:(CADisplayLink *)sender; 31 32 //检测和屏幕边缘的碰撞 33 - (BOOL)checkWithScreen; 34 35 //检测和砖块的碰撞 36 - (BOOL)checkWithBlocks; 37 38 //检测和挡板的碰撞 39 - (void)checkWithPaddle; 40 41 //重置游戏的状态 42 //游戏胜利,失败的状态 43 - (void)resetGamesStateWithMessage:(NSString *)message; 44 45 @end 46 47 @implementation ViewController 48 49 - (void)viewDidLoad { 50 [super viewDidLoad]; 51 // Do any additional setup after loading the view, typically from a nib. 52 } 53 54 - (void)didReceiveMemoryWarning { 55 [super didReceiveMemoryWarning]; 56 // Dispose of any resources that can be recreated. 57 } 58 59 //游戏的重置方法的实现 60 - (void)resetGamesStateWithMessage:(NSString *)message 61 { 62 NSLog(@"%@", message); 63 64 //先把时钟清除也就是关掉,千万不要忘记,否则后果很严重!不亚于内存泄露的错误! 65 //之后,step 方法不会被调用,同时游戏是开始状态的 66 [_gameTimer invalidate]; 67 68 //然后所有的砖块的图片全部恢复,设置为可见 69 for (UIImageView *block in _blocksImage) { 70 [block setHidden:NO]; 71 //把透明度设置为0,此时,肉眼又看不见了 72 [block setAlpha:0]; 73 //把砖块缩小到一个看不见的点 74 [block setFrame:CGRectMake(block.center.x, block.center.y, 0, 0)]; 75 } 76 77 //用两秒钟做一个动画 78 [UIView animateWithDuration:2.0 animations:^{ 79 for (UIImageView *block in _blocksImage) { 80 //然后这里的动画效果,再把砖块的透明度设置为1,可见了。 81 [block setAlpha:1]; 82 //接下来把砖块放大的效果实现 83 [block setFrame:CGRectMake(block.center.x - 32, block.center.y - 10, 64, 20)]; 84 } 85 }completion:^(BOOL finished){ 86 _isPlaying = NO; 87 //屏幕的中间位置 x是160 88 //把小球设置到中间 89 [_ballImage setCenter:CGPointMake(160, 430)]; 90 91 //把挡板设置到中间位置也 92 [_paddleImage setCenter:CGPointMake(160, 450)]; 93 }]; 94 95 96 } 97 98 //小球和屏幕的碰撞检测方法实现 99 - (BOOL)checkWithScreen 100 { 101 //除了下方的屏幕边缘,其他的都是反弹回来,而下方是掉出去,游戏失败 102 BOOL gameOver = NO; 103 104 //左边碰撞检测的处理,比较简单,因为屏幕的原点就是在左边的线上 105 if ([_ballImage frame].origin.x <= 0) { 106 //反弹回去,就是把它取正数,x 方向的速度变为正数,使用绝对值函数 107 _ballV.x = abs(_ballV.x); 108 } 109 110 //右边碰撞检测处理,小球边框的距离原点的 x 加上小球本身的宽度,如果大于了视图本身边框的宽度的尺寸,那就是碰撞 111 if ([_ballImage frame].origin.x + [_ballImage frame].size.width >= self.view.frame.size.width) { 112 //反弹,就是保证小球 x 方向的速度必须为负的 113 _ballV.x = -1 * abs(_ballV.x); 114 } 115 116 //顶部屏幕的碰撞检测处理 117 if ([_ballImage frame].origin.y <= 0) { 118 _ballV.y = abs(_ballV.y); 119 } 120 121 //底部碰撞检测处理 122 if ([_ballImage frame].origin.y + [_ballImage frame].size.height >= self.view.frame.size.height) { 123 gameOver = YES; 124 } 125 126 return gameOver; 127 } 128 129 //小球和方块的碰撞检测方法的实现 130 - (BOOL)checkWithBlocks 131 { 132 //所有的在砖块集合里的砖块的碰撞检测 133 for (UIImageView *block in _blocksImage) { 134 //苹果提供了一个 bool 类型的矩形碰撞检测函数 135 //如果两个矩形重叠了(也就是碰撞了),函数反悔 YES,否则返回 NO 136 //同时只检测,那些没有被隐藏的砖块,已经隐藏的就不需要碰撞检测了 137 if (CGRectIntersectsRect([block frame], [_ballImage frame]) && ![block isHidden]) { 138 //碰撞就消除砖块,其实是隐藏砖块的图像 139 [block setHidden:YES]; 140 //碰撞完成之后,要让小球向下运动 141 _ballV.y = abs(_ballV.y); 142 //保证循环的效率,提前退出循环 143 break; 144 } 145 } 146 147 //判断游戏是否胜利的逻辑 148 BOOL gameWin = YES; 149 150 for (UIImageView *block in _blocksImage) { 151 //如果砖块有没被隐藏的,就认为游戏失败了,否则胜利 152 if (![block isHidden]) { 153 gameWin = NO; 154 //节省性能,发现一个就行了 155 break; 156 } 157 } 158 159 return gameWin; 160 161 //如下比较耗费性能 162 163 // int count = 0; 164 // 165 // for (UIImageView *block in _blocksImage) { 166 // if ([block isHidden]) { 167 // count++; 168 // } 169 // } 170 // 171 // if (count == [_blocksImage count]) { 172 // gameWin = YES; 173 // } 174 } 175 176 //小球和挡板的碰撞检测方法 177 - (void)checkWithPaddle 178 { 179 //如果小球和挡板碰撞 180 if (CGRectIntersectsRect([_ballImage frame], [_paddleImage frame])) { 181 //强制把小球 y 方向的速度设为负数,让它反弹回去 182 _ballV.y = -1 * abs(_ballV.y); 183 //给小球的 x 方向,加上水平的位移,让它能随着挡板的移动而水平的移动起来 184 _ballV.x += _deltaX; 185 } 186 } 187 188 //游戏时钟的处理方法, 因为对外不可见,故定义在 点m 文件里,而不是头文件里 189 - (void)step:(CADisplayLink *)sender 190 { 191 //让求(小球的图)动起来,本质 是 设置小球的 位置(也就是更新小球的位置的状态) 192 //小球中心点的 x 位置加上小球中心点的 x 方向的速度 193 //小球中心点的 y 位置加上小球中心点的 y 方向的速度 194 [_ballImage setCenter:CGPointMake(_ballImage.center.x + _ballV.x, _ballImage.center.y + _ballV.y)]; 195 //可以打印测试下,游戏时钟的方法是否是每秒钟运行60次 196 //NSLog(@"游戏运行了~"); 197 198 //在游戏时钟处理方法里,调用碰撞检测方法 199 if ([self checkWithScreen]) { 200 [self resetGamesStateWithMessage:@"游戏结束!"]; 201 } 202 203 if ([self checkWithBlocks]) { 204 [self resetGamesStateWithMessage:@"游戏胜利!"]; 205 } 206 207 [self checkWithPaddle]; 208 209 } 210 211 //触摸事件的实现 212 //触摸结束(手指抬起之后),游戏开始,小球动起来,这里的方法是支持多点触摸的 213 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *) event 214 { 215 //先判断本游戏是否已经开始了,如果游戏还没有开始: 216 if (!_isPlaying) { 217 //考虑一个点的触摸,获取触摸的对象 218 // UITouch *touch = [touches anyObject];//暂时用不到 219 220 // 触摸之后,给小球一个初始速度,0,-5, 221 //-5就是 y 向下的过程,每一次时钟触发的时候,y 都减去5 222 _ballV = CGPointMake(0, -5); 223 224 //定义游戏时钟 225 //通过函数名来调用头文件里定义的另外的方法 step: 方法,时钟的目标是自己 226 _gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step:)]; 227 228 //把当前时钟添加到游戏里经典的应用循环中,ios默认提供的循环方法 229 [_gameTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 230 231 //勿忘修改游戏状态的标识 232 //表面本游戏已经开始了 233 _isPlaying = YES; 234 } 235 else 236 { 237 //重置水平移动举例 238 _deltaX = 0; 239 } 240 } 241 242 //触摸移动的处理 243 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 244 { 245 if (_isPlaying) { 246 //获取手指移动的距离 247 UITouch *touch = [touches anyObject]; 248 249 //计算手指在 x 方向的移动举例 250 //方向分解 251 //本次触摸的位置 - 上次触摸的位置(x 方向的),就是水平方向的移动距离 252 //在声明里,定义一个成员变量,方便使用 253 //CGFloat deltaX = [touch locationInView:self.view].x - [touch previousLocationInView:self.view].x; 254 _deltaX = [touch locationInView:self.view].x - [touch previousLocationInView:self.view].x; 255 //挡板 x 方向的移动,y 方向不用管,不需要移动。 256 [_paddleImage setCenter:CGPointMake([_paddleImage center].x + _deltaX, [_paddleImage center].y)]; 257 } 258 } 259 260 @end
离发布还要至少经过:
标签:
原文地址:http://www.cnblogs.com/kubixuesheng/p/4179122.html