本游戏的设计步骤:
一、布局界面(把图片资源拉进Main.storyboard)
二、让小球动起来(给他一个初速度)
三、碰撞检测
1、屏幕碰撞
2、砖块碰撞
3、挡板碰撞
四、挡板移动
// ViewController.h
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *blockImageArray; @property (weak, nonatomic) IBOutlet UIImageView *paddleImage; @property (weak, nonatomic) IBOutlet UIImageView *ballImage; @end
// ViewController.m
#import "ViewController.h"
@interface ViewController () { //用这个布尔值标示游戏是否正在进行中 BOOL isPlaying ; //加一个游戏时钟 CADisplayLink *_gameTimer; //小球移动的速度 CGPoint _speed; //手指移动位置的差值 CGFloat chaX; } //1.检测屏幕碰撞 -(BOOL)checkWithScreen; //2.砖块碰撞检测 -(BOOL)checkWithBlock; //3.挡板碰撞 -(void)checkWithPandle; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark 1 之前进行了页面的布局 //开始游戏 -(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //游戏是否在进行中,如果游戏还没有开始就让游戏开始 if(!isPlaying){ isPlaying = YES; //初始化一个游戏时钟,让step方法1/60秒执行一次 _gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step)]; //将游戏放在runloop中 /* * *runLoop做两件事情 1.监听输入源,一般自动放到runLoop中 2.监听定时器,一般需手动放到runLoop中 */ //[_gameTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [_gameTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; //给小球一个初始的速度 _speed = CGPointMake(0, -5); } else { chaX = 0; } } #pragma mark 2 让小球动起来 //让小球按照1/60的频率动起来 -(void)step{ // 如果返回值是yes就代表游戏失败 if ([self checkWithScreen]) { [self gameOver:@"再来一次"]; } if ( [self checkWithBlock]) { [self gameOver:@"你真棒"]; } [self checkWithPandle]; //小球每次的移动都是以上一次的位置作为参考 _ballImage.center = CGPointMake(_ballImage.center.x+_speed.x, _ballImage.center.y+_speed.y); } #pragma mark 3 碰撞检测 //1.检测屏幕碰撞 -(BOOL)checkWithScreen { BOOL isFail = NO; //CGRectGetMInY 获取到小球的最小Y值 //1.顶部碰撞 if (CGRectGetMinY(_ballImage.frame) <= 0) { //获取到绝对值 _speed.y = fabsf(_speed.y); } //2.底部碰撞 if (CGRectGetMaxY(_ballImage.frame) >= (CGRectGetHeight(self.view.frame))) { isFail = YES; } //3左侧碰撞 if (CGRectGetMinX(_ballImage.frame) <= 0) { _speed.x = fabsf(_speed.x); } //4.右侧碰撞 if (CGRectGetMaxX(_ballImage.frame) >= CGRectGetWidth(self.view.frame)) { _speed.x = -1*fabsf(_speed.x); } return isFail; } //2.检测板子是否碰撞 -(BOOL)checkWithBlock { BOOL gameWin = YES; //通过for循环找到小球跟哪个色块碰撞了 for (UIImageView *block in _blockImageArray) { //CGRectIntersectsRect判断;两个视图是否碰撞 if (CGRectIntersectsRect(block.frame , _ballImage.frame) && !block.hidden) { block.hidden = YES; _speed.y = fabsf(_speed.y); } } //判断所有的砖块是否都被隐藏了 for (UIImageView *block in _blockImageArray ) { if (block.hidden == NO) { gameWin = NO; break; } } return gameWin; } //3.挡板碰撞检测 -(void)checkWithPandle { if(CGRectIntersectsRect(_ballImage.frame,_paddleImage.frame)) { _speed.y = -1*fabsf(_speed.y); //让小球的X方向的速度跟手指瞬时移动的速度相加 _speed.x += chaX; NSLog(@"speed.x= %f",_speed.x); } } -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { if (isPlaying) { //后去我点击的手指,touches是个集合,视图有多点触摸 UITouch *touch = [touches anyObject]; //获取到当前手指x的值 CGFloat nowX = [touch locationInView:self.view].x; //获取到上一次手指x的值 CGFloat lastX = [touch previousLocationInView:self.view].x; chaX = nowX -lastX; //让挡板移动 _paddleImage.center = CGPointMake(_paddleImage.center.x+chaX,_paddleImage.center.y); } } #pragma mark 从底部掉下去,游戏结束 -(void)gameOver:(NSString *)string { isPlaying = NO; NSLog(@"%@",string); //销毁定时器 [_gameTimer invalidate]; for (UIImageView *block in _blockImageArray) { block.hidden = YES; block.alpha = 0; } [UIView animateWithDuration:2.0 animations:^{ for (UIImageView *block in _blockImageArray){ block.hidden = NO; block.alpha = 1; } }completion:^(BOOL finshed){ _ballImage.center = CGPointMake(160, 377); _paddleImage.center = CGPointMake(160, 397); }]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end