首页 > 代码库 > IOS 开发入门—打砖块小游戏
IOS 开发入门—打砖块小游戏
iPhone三代(iPhone3GS)
- 2009年发布
- 外观上基本跟iPhone3G没区别,速度更快,3GS后面的S就是“Speed”的意思
- 3.5英寸,480x320像素分辨率
- 后置摄像头300万像素
iPhone4
- 2010年发布,艳惊四座
- 全新外观+玻璃材质,9.3毫米厚度,A4单核处理器,支持多任务
- 3.5英寸Retina显示屏(视网膜屏幕),960x640像素分辨率
- 后置摄像头500万像素
- 前置摄像头30万像素
iPhone4S
- 2011年发布
- 外观上与iPhone4区别不大
- A5双核处理器,性能上有较大的提升
- 3.5英寸,960x640像素分辨率
- 后置摄像头800万像素
- 前置摄像头30万像素
iPhone5
- 2012年发布
- 全新外观,机身更轻薄,7.6毫米厚度,屏幕更大
- A6双核处理器,速度更快
- 4.0英寸,1136x640像素分辨率
- 后置摄像头800万像素
- 前置摄像头120万像素
2013年9月发布iphone5s
- 800万像素
- IPS屏幕;1136*640;4.0英寸
- 64位双核苹果A7处理器,外观优雅简洁,机身轻薄,用户体验极佳,操作简单,让用户感受到从未有过的爽,软件种类丰富、高质量 。
- 性能极佳,支持众多大型3D游戏
iPad做游戏是必用的!否则不一定用到
iPad1
- 2010年发布的平板电脑
- A4单核处理器,9.7英寸,1024x768像素分辨率
iPad2
- 2011年发布
- A5双核处理器,9.7英寸,1024x768像素分辨率
- 前置摄像头:30万像素,后置摄像头:70万像素
The new iPad
- 2012年发布
- A5X双核处理器,9.7英寸Retina显示屏,2048x1536像素分辨率
- 前置摄像头:30万像素,后置摄像头:500万像素
iPad4
- 2012年发布
- A6X双核处理器,9.7英寸Retina显示屏,2048x1536像素分辨率
- 前置摄像头:120万像素,后置摄像头:500万像素
9.7寸,分辨率2048×1536
- iPod Touch是一台没有电话服务功能的iPhone
- 可以使用wifi接入无线网络,拥有和iPhone一样的上网体验
- 可以通过苹果皮实现打电话和短信功能
Apple TV(不在大陆销售)
- 苹果公司推出的一款高清电视机顶盒产品
- 可以通过Apple TV在线收看电视节目
- 可以通过Airplay功能,将iPad、iPhone、iPod和PC中的照片、视频和音乐通过传输到电视上进行播放
//// 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 //引入动画框架 QuartzCore11 #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 @end29 30 @implementation ViewController31 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 *)sender44 {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 *) event56 {57 //先判断本游戏是否已经开始了,如果游戏还没有开始:58 if (!_isPlaying) {59 //考虑一个点的触摸,获取触摸的对象60 // UITouch *touch = [touches anyObject];//暂时用不到61 62 // 触摸之后,给小球一个初始速度,0,-5,63 //-5就是 y 向下的过程,每一次时钟触发的时候,y 都减去564 _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)checkWithBlocks102 {103 BOOL gameWin = NO;104 105 //所有的在砖块集合里的砖块的碰撞检测106 for (UIImageView *block in _blocksImage) {107 //苹果提供了一个 bool 类型的矩形碰撞检测函数108 //如果两个矩形重叠了(也就是碰撞了),函数反悔 YES,否则返回 NO109 //同时只检测,那些没有被隐藏的砖块,已经隐藏的就不需要碰撞检测了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)checkWithPaddle138 {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 *)sender148 {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 *) event172 {173 //先判断本游戏是否已经开始了,如果游戏还没有开始:174 if (!_isPlaying) {175 //考虑一个点的触摸,获取触摸的对象176 // UITouch *touch = [touches anyObject];//暂时用不到177 178 // 触摸之后,给小球一个初始速度,0,-5,179 //-5就是 y 向下的过程,每一次时钟触发的时候,y 都减去5180 _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)checkWithBlocks106 {107 BOOL gameWin = NO;108 109 //所有的在砖块集合里的砖块的碰撞检测110 for (UIImageView *block in _blocksImage) {111 //苹果提供了一个 bool 类型的矩形碰撞检测函数112 //如果两个矩形重叠了(也就是碰撞了),函数反悔 YES,否则返回 NO113 //同时只检测,那些没有被隐藏的砖块,已经隐藏的就不需要碰撞检测了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)checkWithPaddle142 {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 *)sender154 {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 *) event178 {179 //先判断本游戏是否已经开始了,如果游戏还没有开始:180 if (!_isPlaying) {181 //考虑一个点的触摸,获取触摸的对象182 // UITouch *touch = [touches anyObject];//暂时用不到183 184 // 触摸之后,给小球一个初始速度,0,-5,185 //-5就是 y 向下的过程,每一次时钟触发的时候,y 都减去5186 _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 *)event203 {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)checkWithScreen100 {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)checkWithBlocks131 {132 //所有的在砖块集合里的砖块的碰撞检测133 for (UIImageView *block in _blocksImage) {134 //苹果提供了一个 bool 类型的矩形碰撞检测函数135 //如果两个矩形重叠了(也就是碰撞了),函数反悔 YES,否则返回 NO136 //同时只检测,那些没有被隐藏的砖块,已经隐藏的就不需要碰撞检测了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)checkWithPaddle178 {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 *)sender190 {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 *) event214 {215 //先判断本游戏是否已经开始了,如果游戏还没有开始:216 if (!_isPlaying) {217 //考虑一个点的触摸,获取触摸的对象218 // UITouch *touch = [touches anyObject];//暂时用不到219 220 // 触摸之后,给小球一个初始速度,0,-5,221 //-5就是 y 向下的过程,每一次时钟触发的时候,y 都减去5222 _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 else236 {237 //重置水平移动举例238 _deltaX = 0;239 }240 }241 242 //触摸移动的处理243 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event244 {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
离发布还要至少经过:
IOS 开发入门—打砖块小游戏