参考:https://github.com/kirualex/SprityBird

该项目基于spritekit,代码的结构很清楚,感觉用来学习spritekit非常不错。

1、项目只有一个viewController,包含:

@property (weak,nonatomic) IBOutlet SKView * gameView;
@property (weak,nonatomic) IBOutlet UIView * getReadyView; @property (weak,nonatomic) IBOutlet UIView * gameOverView;
@property (weak,nonatomic) IBOutlet UIImageView * medalImageView;
@property (weak,nonatomic) IBOutlet UILabel * currentScore;
@property (weak,nonatomic) IBOutlet UILabel * bestScoreLabel;

初始时gameOverView均不可见。

2、在viewController的viewDidLoad中加载场景:

[self.gameView presentScene:scene];

3、这里做的比较好的是,利用协议完成viewController和Scene的交互,viewController处理游戏中反馈的事件,实现对上述游戏完成、游戏开始等顶层view的操作。

@protocol SceneDelegate <NSObject>
- (void) eventStart;
- (void) eventPlay;
- (void) eventWasted;
@end

4、在Scene的初始化中对场景中的障碍和鸟进行绘制:

- (void) startGame
{
// Reinit
wasted = NO; [self removeAllChildren]; [self createBackground];
[self createFloor];
[self createScore];
[self createObstacles];
[self createBird]; // Floor needs to be in front of tubes
floor.zPosition = bird.zPosition + ; if([self.delegate respondsToSelector:@selector(eventStart)]){
[self.delegate eventStart];
}
}

5、在项目里,只定义了两类node,一个是用来表述移动背景如地板、障碍、背景图等,另外一个就是绘制小鸟;

这里初始化的node对象包括鸟、障碍都会被保存在全局数据组里,在后续刷新。以障碍物的移动为例:

- (void) updateObstacles:(NSTimeInterval)currentTime
{
if(!bird.physicsBody){
return;
} for(int i=;i<nbObstacles;i++){ // Get pipes bby pairs
SKSpriteNode * topPipe = (SKSpriteNode *) topPipes[i];
SKSpriteNode * bottomPipe = (SKSpriteNode *) bottomPipes[i]; // Check if pair has exited screen, and place them upfront again
if (X(topPipe) < -WIDTH(topPipe)){
SKSpriteNode * mostRightPipe = (SKSpriteNode *) topPipes[(i+(nbObstacles-))%nbObstacles];
[self place:bottomPipe and:topPipe atX:X(mostRightPipe)+WIDTH(topPipe)+OBSTACLE_INTERVAL_SPACE];
} // Move according to the scrolling speed
topPipe.position = CGPointMake(X(topPipe) - FLOOR_SCROLLING_SPEED, Y(topPipe));
bottomPipe.position = CGPointMake(X(bottomPipe) - FLOOR_SCROLLING_SPEED, Y(bottomPipe));
}
}

6、在scene中主要继承处理两个方法:

//该函数被Scene重绘每一帧调用
- (void)update:(NSTimeInterval)currentTime - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

7、通过sprite的物理引擎实现碰撞操作:

bottomPipe.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0,0, WIDTH(bottomPipe) , HEIGHT(bottomPipe))]

topPipe.physicsBody.categoryBitMask = blockBitMask;
topPipe.physicsBody.contactTestBitMask = birdBitMask;
- (void)didBeginContact:(SKPhysicsContact *)contact
{
if(wasted){ return; } wasted = true;
[Score registerScore:self.score]; if([self.delegate respondsToSelector:@selector(eventWasted)]){
[self.delegate eventWasted];
}
}

Flappy Bird 源码走读的更多相关文章

  1. Apache Spark源码走读之23 -- Spark MLLib中拟牛顿法L-BFGS的源码实现

    欢迎转载,转载请注明出处,徽沪一郎. 概要 本文就拟牛顿法L-BFGS的由来做一个简要的回顾,然后就其在spark mllib中的实现进行源码走读. 拟牛顿法 数学原理 代码实现 L-BFGS算法中使 ...

  2. Apache Spark源码走读之16 -- spark repl实现详解

    欢迎转载,转载请注明出处,徽沪一郎. 概要 之所以对spark shell的内部实现产生兴趣全部缘于好奇代码的编译加载过程,scala是需要编译才能执行的语言,但提供的scala repl可以实现代码 ...

  3. Apache Spark源码走读之13 -- hiveql on spark实现详解

    欢迎转载,转载请注明出处,徽沪一郎 概要 在新近发布的spark 1.0中新加了sql的模块,更为引人注意的是对hive中的hiveql也提供了良好的支持,作为一个源码分析控,了解一下spark是如何 ...

  4. Apache Spark源码走读之7 -- Standalone部署方式分析

    欢迎转载,转载请注明出处,徽沪一郎. 楔子 在Spark源码走读系列之2中曾经提到Spark能以Standalone的方式来运行cluster,但没有对Application的提交与具体运行流程做详细 ...

  5. twitter storm 源码走读之5 -- worker进程内部消息传递处理和数据结构分析

    欢迎转载,转载请注明出处,徽沪一郎. 本文从外部消息在worker进程内部的转化,传递及处理过程入手,一步步分析在worker-data中的数据项存在的原因和意义.试图从代码实现的角度来回答,如果是从 ...

  6. storm-kafka源码走读之KafkaSpout

    from: http://blog.csdn.net/wzhg0508/article/details/40903919 (五)storm-kafka源码走读之KafkaSpout 原创 2014年1 ...

  7. spring-data-redis-cache 使用及源码走读

    预期读者 准备使用 spring 的 data-redis-cache 的同学 了解 @CacheConfig,@Cacheable,@CachePut,@CacheEvict,@Caching 的使 ...

  8. ConcurrentHashMap源码走读

    目录 ConcurrentHashMap源码走读 简介 放入数据 容器元素总数更新 容器扩容 协助扩容 遍历 ConcurrentHashMap源码走读 简介 在从JDK8开始,为了提高并发度,Con ...

  9. underscorejs 源码走读笔记

    Underscore 简介 Underscore 是一个JavaScript实用库,提供了类似Prototype.js的一些功能,但是没有继承任何JavaScript内置对象.它弥补了部分jQuery ...

随机推荐

  1. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  2. C++实现线程安全的单例模式

    在某些应用环境下面,一个类只允许有一个实例,这就是著名的单例模式.单例模式分为懒汉模式,跟饿汉模式两种. 首先给出饿汉模式的实现 template <class T> class sing ...

  3. Redis/HBase/Tair比较

    KV系统对比表 对比维度 Redis Redis Cluster Medis Hbase Tair 访问模式    支持Value大小 理论上不超过1GB(建议不超过1MB) 理论上可配置(默认配置1 ...

  4. Chrome V8引擎系列随笔 (1):Math.Random()函数概览

    先让大家来看一幅图,这幅图是V8引擎4.7版本和4.9版本Math.Random()函数的值的分布图,我可以这么理解 .从下图中,也许你会认为这是个二维码?其实这幅图告诉我们一个道理,第二张图的点的分 ...

  5. PHP好用但又容易忽略的小知识

    1.PHP函数之判断函数是否存在 当我们创建了自定义函数,并且了解了可变函数的用法,为了确保程序调用的函数是存在的,经常会先使用function_exists判断一下函数是否存在.同样的method_ ...

  6. ios 获取或修改网页上的内容

    UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌     入页面中,通过这个方法我们可 ...

  7. Android之SharedPreferences数据存储

    一.SharedPreferences保存数据介绍 如果有想要保存的相对较小键值集合,应使用SharedPreferences API.SharedPreferences对象指向包含键值对的文件并提供 ...

  8. maven打包插件:appassembler

    1.打包成bat 打包命令:mvn clean package appassembler:assemble <plugin> <groupId>org.codehaus.moj ...

  9. 如何通过Git GUI将自己本地的项目上传至Github

    最近在学习node.js和react,顺便复习了下AngluarJS相关的东西,写了些小demo想放在GitHub上,之前仅限于只申请了GitHub账号从没用过,今天花半天时间查资料认真学习Githu ...

  10. 跟着老男孩教育学Python开发【第五篇】:模块

    递归的案例:阶乘 1*2*3*4*5*6*7- def func(num):     if num == 1:         return 1     return num * func(num - ...