iOS学习之flappyBird游戏的实现
导言
在本人还是学生的时候,flappyBird这款游戏非常火爆,最后等到Android版的出来之后,也是很痴迷的玩了一把。可是,本人游戏天赋一直平平,几度玩得想摔手机。本文主要介绍如何开发iOS平台的flappyBird,游戏中使用了原本软件的图片资源,仅作学习交流使用。本人实现的flappyBird游戏包含游戏等级设定,排行榜,音效等功能。
技术点
flappyBird是单机游戏,主要涉及界面逻辑、图片资源、游戏动画、得分排行。
为了实现这几个功能,需要使用以下几个技术框架:
1)AVFoundation
2)归档
3)模态视图
4)NSTimer
5)视图控件,包括UIImageView、UILabel、UITableView等
实现过程
1、创建工程
1)打开Xcode,点击新建工程,选择Single View Application模板

2)填写工程信息

2、移除Main.storyboard文件

上图是flappyBird的文件目录,因为Xcode6使用模板创建工程时会自动生成Main.storyboard文件,而工程中本人使用代码布局,所以可以移除Main.storyboard文件。具体操作方法可以参看本人另一篇文章:
3、游戏界面布局
1)主菜单界面,游戏难度设定界面、排行榜界面,效果图如下
    
    
2)游戏界面,效果图如下

需要说明的是,Game Over这个界面,首先需要隐藏或者等到游戏结束才创建。本人是选择在游戏判定结束时才创建并显示。
4、游戏运行
这款游戏的两个关键点:
1)使用定时器驱动游戏界面运行,即游戏界面中的柱子高低变化与柱子的消失与产生。
2)游戏结束的判定,这里涉及两个问题,一是碰撞检测,二是计分统计。
具体实现部分代码
1、计分统计
-(void)columnLabelClick {
    if (topPipeFrame.origin.x == ( +  - )) {
        columnNumber++;
        columnLabel.text = [NSString stringWithFormat:@"%zi",columnNumber];
    }
}
2、绘制柱子
-(void)pipe {
    //通道高度
    NSInteger tunnelHeight = ;
    //根据游戏难度设定通道高度
    if([[DataTool stringForKey:kRateKey] isEqualToString:@"ordinary"]) {
        tunnelHeight = ;
    }else if([[DataTool stringForKey:kRateKey] isEqualToString:@"general"]) {
        tunnelHeight = ;
    }else if([[DataTool stringForKey:kRateKey] isEqualToString:@"difficult"]) {
        tunnelHeight = ;
    }else if([[DataTool stringForKey:kRateKey] isEqualToString:@"hard"]) {
        tunnelHeight = ;
    } else if([[DataTool stringForKey:kRateKey] isEqualToString:@"crazy"]) {
        tunnelHeight = ;
    }
    //柱子图像
    NSInteger tall = arc4random() %  + ;
    topPipe = [[UIImageView alloc]initWithFrame:CGRectMake(, -, , tall)];
    topPipe.image = [UIImage imageNamed:@"pipe"];
    [self.view addSubview:topPipe];
    bottomPipe = [[UIImageView alloc]initWithFrame:CGRectMake(, tall + tunnelHeight, , )];
    bottomPipe.image = [UIImage imageNamed:@"pipe"];
    [self.view addSubview:bottomPipe];
    //把底部图片视图放在柱子视图上面
    [self.view insertSubview:roadView aboveSubview:bottomPipe];
}
3、使用定时器,驱动游戏界面运行,并进行碰撞检测
//添加定时器
timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(onTimer) userInfo:nil repeats:YES]; //定时器操作
-(void)onTimer {
//底部动画移动
CGRect frame = roadView.frame;
if (frame.origin.x == -) {
frame.origin.x = ;
}
frame.origin.x--;
roadView.frame = frame; //上升
if (isTap == NO) {
CGRect frame = birdsView.frame;
frame.origin.y -= ;
number += ;
birdsView.frame = frame;
if (number >= ) {
isTap = YES;
}
} //下降
if(isTap == YES && birdsView.frame.origin.y < ){
CGRect frame = birdsView.frame;
frame.origin.y++;
number -= ;
birdsView.frame = frame;
number = ;
} //柱子移动
topPipeFrame = topPipe.frame;
CGRect bottomPipeFrame = bottomPipe.frame;
topPipeFrame.origin.x--;
bottomPipeFrame.origin.x--;
topPipe.frame = topPipeFrame;
bottomPipe.frame = bottomPipeFrame;
if (topPipeFrame.origin.x < -) {
[self pipe];
} //碰撞检测(交集)
bool topRet = CGRectIntersectsRect(birdsView.frame, topPipe.frame);
bool bottomRet = CGRectIntersectsRect(birdsView.frame, bottomPipe.frame);
if (topRet == true || bottomRet == true) {
[self.soundTool playSoundByFileName:@"punch"];
[self onStop];
}
if (topPipeFrame.origin.x == ( + - )) {
[self.soundTool playSoundByFileName:@"pipe"];
[self columnLabelClick];
}
}
4、更新分数,更新最佳分数与排行榜分数,并使用归档将数据持久化
-(void)updateScore {
    //更新最佳成绩
    if (columnNumber > [DataTool integerForKey:kBestScoreKey]) {
        [DataTool setInteger:columnNumber forKey:kBestScoreKey];
    }
    //更新本局分数
    [DataTool setInteger:columnNumber forKey:kCurrentScoreKey];
    //更新排行榜
    NSArray *ranks = (NSArray *)[DataTool objectForKey:kRankKey];
    NSMutableArray *newRanksM = [NSMutableArray array];
    NSInteger count = ranks.count;
    BOOL isUpdate = NO;
    for (NSInteger i = ; i < count; i++) {
        NSString *scoreStr = ranks[i];
        NSInteger score = [scoreStr integerValue];
        if (score < columnNumber && isUpdate == NO) {
            scoreStr = [NSString stringWithFormat:@"%zi", columnNumber];
            [newRanksM addObject:scoreStr];
            isUpdate = YES;
            i--;
        } else {
            scoreStr = [NSString stringWithFormat:@"%zi", score];
            [newRanksM addObject:scoreStr];
        }
    }
    if (newRanksM.count > count) {
        [newRanksM removeLastObject];
    }
    [DataTool setObject:newRanksM forKey:kRankKey];
}
5、绘制GameOver提示显示
-(void)pullGameOver {
    //游戏结束操作界面
    gameOver = [[GameOverView alloc] initWithFrame:CGRectMake(, , , )];
    gameOver.delegate = self;
    [self.view addSubview:gameOver];
}
6、游戏停止操作
-(void)onStop {
    //更新分数
    [self updateScore];
    //停止定时器
    [timer setFireDate:[NSDate distantFuture]];
    //弹出游戏结束操作界面
    [self pullGameOver];
}
小结
这款游戏的实现还是很简单的,主要使用UIImageView自带的动画实现方式,即可实现bird的动画效果。使用NSTimer即可实现游戏场景的柱子移动,至于柱子的高度,则可以使用随机数方式在一定范围内实现高低变化。最后可以使用CGRectIntersectsRect来实现边界碰撞检测来判定游戏是否结束。
以上是本人开发iOS版flappyBird的简要过程介绍,其中只包含了关键点的代码实现,具体完整游戏源代码地址:https://github.com/CharsDavy/flappyBird
【扫描关注更多干货】
公众号:xiaoniu

iOS学习之flappyBird游戏的实现的更多相关文章
- 基于Keras的OpenAI-gym强化学习的车杆/FlappyBird游戏
		
强化学习 课程:Q-Learning强化学习(李宏毅).深度强化学习 强化学习是一种允许你创造能从环境中交互学习的AI Agent的机器学习算法,其通过试错来学习.如上图所示,大脑代表AI Agent ...
 - iOS学习路线图
		
一.iOS学习路线图 二.iOS学习路线图--视频篇 阶 段 学完后目标 知识点 配套学习资源(笔记+源码+PPT) 密码 基础阶段 学习周期:24天 学习后目标: ...
 - iOS 学习资源
		
这份学习资料是为 iOS 初学者所准备的, 旨在帮助 iOS 初学者们快速找到适合自己的学习资料, 节省他们搜索资料的时间, 使他们更好的规划好自己的 iOS 学习路线, 更快的入门, 更准确的定位的 ...
 - iOS学习资源个人整理
		
1208更新: http://www.tuyiyi.com 图翼网 https://github.com/Alamofire/Al ...
 - iOS学习笔记-精华整理
		
iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始 ...
 - iOS学习笔记总结整理
		
来源:http://mobile.51cto.com/iphone-386851_all.htm 学习IOS开发这对于一个初学者来说,是一件非常挠头的事情.其实学习IOS开发无外乎平时的积累与总结.下 ...
 - ios学习资料(一)
		
IT社区: http://www.cnblogs.com/ http://www.csdn.net/ http://www.51cto.com/ http://www.cocoachina.com/ ...
 - iOS学习资料整理
		
视频教程(英文) 视频 简介 Developing iOS 7 Apps for iPhone and iPad 斯坦福开放教程之一, 课程主要讲解了一些 iOS 开发工具和 API 以及 iOS S ...
 - iOS 学习
		
iOS 学习资料 (适合初学者) 本文资料来源于GitHub 一.视频教程(英文) Developing iOS 7 Apps for iPhone and iPad斯坦福开放教程之一, 课程主要讲解 ...
 
随机推荐
- MyBatis Generator 学习
			
根据数据库,自动生成 VO.XML或者DAO的工具. 同大多数工具(或者框架)一样,需要加载一个配置文件,然后根据配置文件中的内容连接数据库,访问其中的表内容,最后生成实体类以及MAPPER. 占位用 ...
 - Unity5.X 新版AssetBundle打包控制
			
一.什么是AssetBundle 估计很多人只知道Unity的模型之类的东西可以导出成一种叫做AssetBundle的文件,然后打包后可以在Unity程序运行的时候再加载出来用.那么AssetBund ...
 - 【UVa】Headmaster's Headache(状压dp)
			
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
 - 【BZOJ】1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐(dfs)
			
http://www.lydsy.com/JudgeOnline/problem.php?id=1648 水题.. dfs记录能到达的就行了.. #include <cstdio> #in ...
 - MyEclipse10.6 安装SVN插件方法及插件下载地址
			
今天MyEclipse10.6出了点问题,所以重装了它,同一时候也把svn的插件重装了一次,把网上资源和自己的经历顺便在博客这里记录一下.建议直接看方法一好了,简单方便,不必要折腾太多. 下来 ...
 - Spring_day04--课程安排_回顾SSH框架知识点_SSH框架整合思想
			
Spring_day04 上节内容回顾 今天内容介绍 回顾SSH框架知识点 Hibernate框架 Struts2框架 Spring框架 SSH框架整合思想 整合struts2和spring框架 Sp ...
 - 剑指 offer set 13 把数组排成最小的数
			
总结 1. 给定 3, 32, 321 将他们组合成最小的数, 比如 321323 2. 3 -> 333 32 -> 322 321 -> 321 然后再排序
 - insmod 内核模块参数传递
			
对于如何向模块传递参数,Linux kernel 提供了一个简单的框架.其允许驱动程序声明参数,并且用户在系统启动或模块装载时为参数指定相应值,在驱动程序里,参数的用法如同全局变量. 通过宏modul ...
 - VS2010类模板更改,增加版权等等信息
			
本文转载自XDOTNET 在开发过程中往往需要在每一个页面(类)增加注释等等内容,VS2010中可以修改模板,在原有模板中增加一个类,会引用System等等命名空间,以及一些程序集.下面我们来看看如何 ...
 - python里的生成器
			
author:headsen chen date:2018-03-22 10:59:46 notice:This article created by headsen chen himself and ...