码迷,mamicode.com
首页 > 移动开发 > 详细

IOS 开发入门—打砖块小游戏

时间:2015-01-01 22:26:20      阅读:558      评论:0      收藏:0      [点我收藏+]

标签:

忙着期末考试,读书笔记断更了~
 
ios 游戏处女作—demo
 
游戏规则
屏幕上方有四排砖块
点击屏幕开始游戏
游戏开始时,小球向上方运行
小球与砖块撞击可以撞碎砖块并反弹
小球与屏幕顶部、右侧、左侧碰撞会反弹
小球与挡板碰撞会反弹
左右移动手指可以挪动挡板
小球从屏幕下方掉出游戏结束
撞碎所有砖块游戏胜利
 
手机游戏的使用习惯
除非是非常出色的游戏或者游戏模式所迫,否则最好使用竖版的模式,适合用户单手操作手机,比较方便。而 iPad 则最好使用横版。
游戏类的屏幕一般要把手机上面的状态栏隐藏。不同于一般的应用程序,比如淘宝,美团,网上银行等,这些程序就不需要把状态栏隐藏,用户需要看到时间等信息。
 
Xcode6:
 
技术分享
 
并且 Iphone6模拟器默认自带状态栏,还是需要设置一下,把它屏蔽掉;
技术分享
 
 
需要添加动画框架QuartzCore.framework
 
技术分享
 
这里要知道一些苹果手机的配置:

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游戏
iPhone6和6s
太平洋时间2014年9月9日10点(北京时间9月10日凌晨1点)正式发布
6主屏尺寸4.7英寸 主屏分辨率1704x960像素 后置摄像头800万像素 前置摄像头210万像素
6s 主屏5.5英寸 ,分辨率 1920x1080像素
 

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万像素
iPad Mini 1
 
2012年10月23日于美国加州圣荷西发布
7.9英寸、1024 × 768 分辨率显示屏
500 万像素后置 ,120 万像素前置,处理器等硬件规格大致与iPad 2相同;
采用与 iPhone 5相同的Lightning连接线作充电或数据传送。
立体声扬声器。
 
iPad Mini 2
 
2013年10月22日发布
超过310万像素的Retina显示屏,分辨率2048 x 1536像素。
A7芯片,薄至仅7.5毫米,轻达331克。
 
iPad Air
 
2013年10月23日发布
9.7英寸,视网膜显示屏,厚7.5毫米
重量是1磅(约合454克),A7处理器,并搭配了M7协处理器
后置摄像头500万,支持1080p高清视频FaceTime;
电池续航能力达到10小时。
 
iPad mini 3
美国东部时间2014年10月16日下午1点(北京时间10月17日凌晨1点)正式发布。
7.9英寸,分辨率2048x1536
内置苹果64位 A7 双核处理器
系统内存1GB。
 
iPad Air 2
2014年10月
A8X处理器,IOS 8
9.7寸,分辨率2048×1536
 
iPod Touch
  • iPod Touch是一台没有电话服务功能的iPhone
  • 可以使用wifi接入无线网络,拥有和iPhone一样的上网体验
  • 可以通过苹果皮实现打电话和短信功能

Apple TV(不在大陆销售)

  • 苹果公司推出的一款高清电视机顶盒产品
  • 可以通过Apple TV在线收看电视节目
  • 可以通过Airplay功能,将iPad、iPhone、iPod和PC中的照片、视频和音乐通过传输到电视上进行播放
敏捷开发 scrum
以需求为驱动,反复迭代。而不是上来就先写代码。故我们先设计界面的布局,看看好玩不好玩。
 
大致样子:按照4和4s
每行设计为5个砖块,则单个砖块的宽是64,因为总宽为320。然后把图片素材拖进去即可,初步设置为6排。
挡板同样是宽度64,高度20。
小球是宽度20,高度20。
技术分享
有些粗糙,美工的问题,可以折中缓解下,发现这些素材的背景都是灰色,那么我们设置屏幕的背景为灰色即可解决。切记;苹果的产品素材最好是1:1的比例,来保证最佳的性能和效果,尽量让美工去调整素材。
 
最终成品:
技术分享
 
尺寸问题
先调整3.5英寸的(4和4s),再调整4英寸的(5和5s),现在又有了4.7英寸和5.5英寸。一般的原则是从小到大调整。
 
界面设计的总结
在 IOS 游戏开发中,界面设计是重中之重!!非常重要,不能小视。要先设计界面原型,再讨论游戏的过程,期间要对游戏的好玩度抱有信心,必须相信自己的游戏是好玩的,一定要坚定不移,即使这是一种病态的坚持。这样的爱好和热心才会给开发人员带来热情和激情。
最忌讳还没对游戏的好玩度抱有决心和信心的时候,就动手写代码。这样很容易失败。相反,有了成型的界面和对游戏好玩度的信心和激情,这之后的思路才会清晰和长久。
 
继续游戏的开发
技术分享
 
比较经典的应用程序的循环,设置完毕,处理用户事件(包括触摸,点击,说话,摇晃等),处理的同时更新游戏状态(比如,手指滑动挡板,则挡板移动,小球碰撞了砖块,则砖块隐藏),判断游戏是否结束,没有结束就继续循环,否则结束。几乎所有的语言在开发游戏的时候,都会有类似的循环过程。
 
建立IBOutlet & IBOutlet Collection
这需要注意下砖块的 outlet 集合的设置,把每个砖块都拖拽到这个集合里。
技术分享
 
//
//  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

离发布还要至少经过:

素材的完善和优化:
•图像素材的完备:图标、启动图像
•必须要有音频:没有声音的游戏是不可想象的
•多语言(perfect!)
 
程序的优化:
•游戏要设置难度和手动的调整 & 最好是有物理的仿真
•要有关卡的设置
•玩家得分与奖励制度的建立
•游戏暂停功能(必须要)
•游戏状态保存(必须的) 
 

IOS 开发入门—打砖块小游戏

标签:

原文地址:http://www.cnblogs.com/kubixuesheng/p/4179122.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!