首页 > > > IOS开发入门介绍.pdf

IOS开发入门介绍.pdf

IOS开发入门介绍.pdf

上传者: ddfqqy 2014-04-08 评分1 评论0 下载73 收藏12 阅读量331 暂无简介 简介 举报

简介:本文档为《IOS开发入门介绍pdf》,可适用于手机软件领域,主题内容包含第一章iPhone开发环境设置Iftheaxisdullanditsedgeunsharpened,morestrengthisneeded铁器钝了符等。

第一章 iPhone开发环境设置 If the ax is dull and its edge unsharpened, more strength is needed. 铁器钝了,若不将刃磨快,就必多费气力。 ——《旧约•传道书》 前言 本书的目的是让初学者能够系统的学习iPhone开发的基础知识,让你在学习iPhone软件开 发的过程中少走弯路,掌握技术精要,使你能够快速的步入iPhone开发的殿堂,同时也为有 经验的开发者提供实用的编程技巧,思路和参考实例,这些宝贵的实例是在进行iPhone开发 时需要的第一手素材,是你在实际开发iPhone软件时遇到问题时最珍贵的资源,有效使用这 些资源能让你快速解决问题, 实现软件需要的功能, 节约你大量的宝贵时间。 面对一种新技术,我们是先学习Objective-C,还是先熟悉 iPhone SDK用户界面编程? 还是跟着一些样本代码直接临摹练习? 初学者刚刚接触 iPhone软件开发的时候,往往会有这样的疑惑,如何入手,从哪里开始?本书从实践出 发, 由浅入深,逐步讲解iPhone软件开发的必要知识要点,读者在阅读的同时, 也可以编 译相关例子代码,加深理解,也可以将这些例子代码应用到实际的软件开发当中,所以笔 者在选材和介绍时尽量做到既不太复杂,又能够满足项目开发的实际需要。 1.0 安装雪豹操作系统 要进行iPhone开发,拥有Mac操作系统是最起码的条件,然而对许多 人而言,安装苹果雪豹系统看起来是件很麻烦的事情,所以为了帮助初学者快速建立开发 环境,笔者就以自己的开发环境为例来讲解如何快速建立iPhone开发环境。 笔者使用的苹果操作系统是Mac OS X 10.6.3版本,见下图, 笔者的机器CPU和内存参数如下: Intel(R) Core(TM)2 Duo CPU E7200 @ 2.53GHz 3.11 GB内存 笔者的机器主板配置: 华硕( ASUS)P5GC-MX/GBL 1.6 使用Wine安装Source Insight Source Insight 是笔者使用过的最优秀的代码阅读和编辑工具, 软件包含代码编 辑器和代码浏览器,内置对C/C++,C#和Java程序的分析功能,以及其他语言。你可以 添加各种语言语法分析文件CLF(Custom Language File), 如ARM,PPC,PIC汇编,verilog 语言,Perl,PHP,Python,Ruby,以及Lua,TCL,SQL等各种语言, 使用Source Insight来阅读 和分析大型软件源代码,可以帮助你快速了解软件模块之间的关系, 类之间的继承, 函数 之间的调用关系等源代码内在关系, 是代码分析和编程的优秀工具软件, 许多成功的大型 商业软件都是使用Source Insight 编辑开发出来的, 打开Applications => Utilities => 打 开Terminal, 执行如下命令: $ mv Si3Setup.exe ~/.wine/drive_c/ $ cd ~/.wine/drive_c/ $ wine Si3Setup.exe 即可启动Source Insight的安装, 接着和Windows安装过程一样,输入序列号直到安装结束, 安装完成以后就可以使用Source Insight强大的代码阅读能力来分析大型软件原代码了, 以 下是Source Insight 在Mac OS X上运行时的工程截图: 第二章 Objective-C编程基础 A wise man who built his house on the rock, a foolish man who built his house on sand. 一个聪明人,把房子盖在磐石上。无知的人,把房子盖在沙土上。 ——《新约•马太福音》 2.15 Objective-C接口编程 2.15.1 接口编程之@protocol Protocols @protocol是Objective-C中普遍存在的接口定义方式, 即在一个类中通过@protocol定 义接口, 在另外的类中实现该接口, 这种接口定义方式也称为"delegation"模式, @protocol声明了可以被其它任何类实现的方法, 协议仅仅是定义一个接口,由其它的类 去负责实现。 "delegation"模式的使用分为三个步骤, 分别是接口声明,接口回调和接口实现,我们来看个 具体的例子, 第一步: 接口声明,该接口只有一个方法processSuccessful()声明: // ClassWithProtocol.h #import <Foundation/Foundation.h> @protocol ProcessDataDelegate <NSObject> @required - (void) processSuccessful: (BOOL)success; @end 定义一个包装类ClassWithProtocol包含该接口: @interface ClassWithProtocol : NSObject { id <ProcessDataDelegate> delegate; } 接口变量delegate作为类ClassWithProtocol的属性: @property (retain) id delegate; 同时定义一个任务, 在任务完成时回调接口: -(void)startSomeProcess; @end 第二步: 接口回调,客户在ClassWithProtocol类时会设置delegate属性,所以这里就可以 使用该delegate回调客户,代码示范: // ClassWithProtocol.m #import "ClassWithProtocol.h" @implementation ClassWithProtocol @synthesize delegate; - (void)processComplete { //回调接口,processSuccessful()由使用者负责具体实现 [[self delegate] processSuccessful:YES]; } //通过定时器,模拟在任务完成时调用接口回调函数 -(void)startSomeProcess { [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(processComplete) userInfo:nil repeats:YES]; } @end 第三步: 接口实现,编写一个测试类TestAppDelegate实现ProcessDataDelegate接口,代 码如下: // test_appAppDelegate.h #import <UIKit/UIKit.h> #import "ClassWithProtocol.h" @class testAppObject; @interface TestAppDelegate : NSObject <UIApplicationDelegate, ProcessDataDelegate> { UIWindow *window; ClassWithProtocol *protocolTest; } @property (nonatomic, retain) UIWindow *window; @end 实现接口方法,我们在这里只是简单的输出一条打印语句: - (void) processSuccessful:(BOOL)success { NSLog(@"Process completed"); } 在这里TestAppDelegate类实现接口以后, 在ClassWithProtocol类的processComplete() 中回调接口方法时就会执行这里的打印语句, 完整代码请参考本书附带的 protocolExample.zip实例。 重要提示:使用@protocol模式时,需要注意的是,如果你的对象是另一个对象的 delegate,那么在你的对象release之前要将另一个对象的delegate属性设置成nil,否则另一 个对象在不知道delegate已经不可用的情况下仍然可能发送消息给其delegate,就可能产生 典型的“魔鬼引用”,示范代码: ClassWithProtocol *another; TestAppDelegate *test; another.delegate = test; //do some work … another.delegate = nil; [test release]; 本节的完整Xcode工程代码, 请参考本书附带的Protocol.zip实例。 练习: 编程实现"delegation"模式, 定义接口模拟简单的加法运算。 第三章:iPhone SDK开发基础 The heart of the discerning acquires knowledge; the ears of the wise seek it out. 聪明人的心得知识,智慧人的耳求知识。 ——《旧约•箴言》 3.7 UIView层次管理 在iOS开发中通过设置UIView的叠放层次, 以及其backgroundColor属性等,就可以组合 各种UIView来创建各种用户界面, UIView在这里就好像图片处理程序中的层(Layer)对象 一样,你可以将一个层显示在最前面,也可以将前面的层推送到背后, 或者交换不同层的内 容, 将一个UIView显示在最前面只需要调用其父视图的bringSubviewToFront()方法, 将一个UIView层推送到背后只需要调用其父视图的sendSubviewToBack()方法即可, 如下图显示的程序界面: 点击"Show Next Picture"按钮, 则程序动态显示不同的图片, 实现代码如下: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. UIView *mainview = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; mainview.backgroundColor = [UIColor clearColor]; imageViews = [[NSMutableArray alloc] initWithCapacity:5]; for(int i = 1; i< 6; i++){ NSString *name = [NSString stringWithFormat:@"apple-ipad- background-%d.jpg",i]; UIImage *image = [UIImage imageNamed:name]; UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; imageView.frame = [[UIScreen mainScreen] bounds]; [imageViews addObject:imageView]; [mainview addSubview:imageView]; [imageView release]; } [window addSubview: mainview]; [mainview release]; button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [button setTitle:@"Show Next Picture" forState:UIControlStateNormal]; [button addTarget:self action:@selector(showNext:) forControlEvents:UIControlEventTouchUpInside]; button.frame = CGRectMake(160-75, 480-44, 150, 40); button.autoresizingMask = UIViewAutoresizingFlexibleTopMargin; [window addSubview: button]; [window makeKeyAndVisible]; return YES; } 程序首先从文件里面读出文件组成UIImageView数组,并将生成的UIImageView对象加入 一个图片容器mainview, mainview是一个背景透明的UIView,这样当容器里面显示不同 的UIImageView的时候, 用户可以透过容器看见图片,按钮的消息响应函数: - (void)showNext:(id)sender{ UIImageView *view = nil; for(view in imageViews){ if([view isInFront]){ [view sentToBack]; break; } } } showNext()函数遍历UIImageView数组,找出当前显示在最前面的图片, 找到以后通过 sentToBack()函数将其推送到背后,这样其下面的图片就显示出来, sentToBack()函数通 过UIView的扩展类实现,其定义如下: 第四章:iPhone SDK高级编程 When the hay is removed and new growth appears. 干草割去,嫩草生发。 ――《旧约•箴言》 4.10 自定义用户界面控件制作 4.10.1 ComboBox控件和UIPikerView设计 iOS没有和桌面软件类似的ComboBox界面控件,本节结合UITextField,UIPickerView,以 及UIToolbar来实现一个定制的ComboBox控件,控件外观如下图所示,该控件在用户点击 文本框旁边的下拉箭头时弹出UIPikerView,在用户滚动UIPikerView时,用户选择的项目 将自动填入文本框,用户选择好选项以后,点击蓝色"Done"按钮,即可关闭UIPikerView,下 面就介绍如何实现该控件。 首先通过子类化UITextField的来实现下拉箭头,同时实现UIPickerView的接口协议, UIPickerViewDataSource和UIPickerViewDelegate,这样子类化的UITextField就可以 响应UIPickerView发送的消息,子类的接口定义: @interface UIComboBox : UITextField<UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate> { } 重载父类的didMoveToSuperview()消息, 加载箭头图片组成UIImageView,然后将 UIImageView设置在文本框的最右边,这样就实现了带下拉箭头的文本框: 第五章:iPhone企业应用实例分析 By other's faults, wise men correct their own. 他山之石,可以攻玉。 ――《旧约•箴言》 5.2 系统介绍 这是一个通过手机进行企业工作流和文档管理的项目,要求基于Web技术,多层架构, 业务层使用Web Service提供服务,客户端需要支持iPhone,Android,Blackberry和 Windows Mobile平台,系统框架如下图: 5.3 系统需求和主要用例 项目名称: WebDoc Mobile 系统需求: 第六章: iPad软件开发基础 More strength is needed but skill will bring success. 得智慧指教,便有益处。 ――《旧约•传道书》 6.7 Google地图编程 iOS虽然提供了MapKit.framework这个framework来支持地图程序的开发, 但是在实际 的项目开发中, 开发地图程序往往具有一定的挑战性, 本节通过一个“路线测量"程序作为 iOS地图软件开发中典型的实例来介绍有关iOS开发的必要编程知识, 让读者在iOS地图项 目中可以应用这些知识来解决实际项目中的开发问题, “路线测量"启动以后,界面显示出一 个Google地图, 用户通过点击地图下方的"Add Annotation"按钮, 即可在地图上面添加 标注, 标注需要一个一个按需要测量的路线顺序添加, 在添加标注的时候, 主要是注意在路 线拐点的地方添加, 当需要测量的路线都标注好以后, 就可以点击"Create Routes"按钮生 成路线相对应的曲线, 程序按照用户添加的标注路径来生成蓝色曲线, 如下图所示: 在生成蓝色的路线以后, 点击"Calculate Distance"就可以让程序计算出路线有多长的距 离, 如上图显示的是2700米. 程序主要通过MapWebView类实现和Google Javascript API的交互,如获取和设置地图 中心点位置,放大和缩小地图, 移动地图等都是通过这个类和Google API进行通信, MapWebView类的定义: // MapWebView.h #import <UIKit/UIKit.h> 第七章: iPad商业软件实例分析 All streams flow into the sea, yet the sea is never full. 江河都往海里流,海却不满。 ――《旧约•传道书》 在大图界面, 用户点图片下方的小图片时, 则可以查看不同的效果图, 点击最右边的小图则 可以播放相应的视频, 视频截图: 用户点击 Info 小图标时, 系统显示当前项目对应的产品信息。 第八章:iOS游戏开发基础 Wisdom is better than weapons of war. 智慧胜过打仗的兵器。 ——《旧约•传道书》 8.5 粒子系统 粒子系统(Particle System)在iOS游戏开发中占有特殊的重要作用, 当要模拟爆炸、烟 雾、火焰、闪电等特效时都需要使用粒子系统, 粒子系统的算法是比较复杂的课题,需要控 制粒子的运动、重力、摩阻、旋转、渐隐、缩放等,接下来笔者介绍两个具体的粒子系统 实例。 8.5.1 轨道卫星 这里介绍一个如何制作卫星飞行时尾部喷火的效果, 如下图所示: 程序使用Chipmunk模拟恒星和卫星飞行, 程序启动以后模拟卫星发射, 在太空飞行, 然后 找到距离卫星最近的恒星以后, 绕恒星飞行, 以上图片就是卫星绕恒星飞行的画面, 程序 没有使用Chipmunk自带的重力模拟而是使用自定义的重力效应函数来模拟恒星的重力。 cocos2d包含了PointParticleSystem和QuadParticleSystem两个类, 使我们可以方便 地使用或者实现粒子系统, 程序直接使用cocos2d库的PointParticleSystem类来实现火 焰效果。 程序通过定义一个PointParticleSystem的子类SatParticle来设置粒子系统的速度,角 度等初始化参数: // SatParticle.h #import "PointParticleSystem.h" #import "QuadParticleSystem.h" @interface SatParticle : PointParticleSystem { } @end 第九章: iOS商业游戏实例分析 Can papyrus grow tall where there is no marsh? Can reeds thrive without water? 蒲草没有泥,岂能发长。芦荻没有水,岂能生发。 ――《旧约•约伯记》 9.1 概述 通过前一章的学习, 读者已经对iOS游戏开发有了初步的了解,本章将介绍几个具有代表性 质的iOS商业游戏实例, 通过对商业游戏实例的学习, 让读者了解真实的游戏项目的系统架 构, 引擎设计, 了解声音, 视频, 图片处理等相关的编程技术要点, 以便借鉴和综合应用这些 知识到实际的游戏项目开发中, 本章提供的游戏都具有极高的商业价值,每个游戏都包含完 整的源代码, 读者完全可以在这些游戏的基础上创建不同类型的iOS新游戏。 9.2 闪回(Flash Back) Flash Back是一款融合RPG和FPS的优秀科幻游戏, 最早由法国游戏开发商 Delphine公司于1992年发行,从那时起,该游戏就风靡了欧美,其它厂商也纷纷将其移植到 了各种流行的游戏平台,游戏以其异常流畅的动画和连贯的动作而赢得用户的喜爱,你扮演 的角色是康拉德.比.哈特先生(Conrad B. Hart), 哈特先生试图恢复他失去的记忆而拯救 游戏设置的反叛乌托邦世界, 在游戏中你将遇到曲折的情节, 阴谋,外星人, 一切你在一个 科幻游戏中所期待看到的事情, 游戏和神秘岛(Myst)类似, Flash Back可以是一个相当短 的游戏,如果你确实非常清楚去哪儿 需要使用什么物件,如何干掉敌人。 游戏使用经典的REminiscence游戏引擎实现, 该引擎也可以在PSP, PalmOS, WinCE等 平台运行, 引擎和Objective-C的接口主要在iPhoneStub.h和iPhoneStub.mm两个文件 中实现, 另外游戏实现了一个游戏手柄和其它一些新的iOS用户界面如系统设置等。 系统启动后在EmulationViewController类的loadView()初始化方法中创建全局的 Game对象, 并在runEmulator()中启动游戏主循环, 而Game对象则在C++代码端的 game.h文件中定义。 // EmulationViewController.m - (void)loadView { systemStub = static_cast<iPhoneStub*> (SystemStub_create()); engine = new Game(systemStub, dataPath, documentsPath, ver); inputController = [[InputControllerView alloc] initWithFrame:CGRectZero]; self.inputController.TheJoyStick = &systemStub->TheJoyStick; [view addSubview:self.inputController]; } 通过本节实例, 我们看到一种移植老游戏到iOS平台的途径,就是基于iOS模拟器来实现 Object-C和C,C++代码的接口, 在Object-C层面开发新的用户输入协议和界面, 而程序 功能仍然由老游戏的C,C++代码提供, 网络上存在许多这样成熟的模拟器可以帮助我们重 复利用老游戏代码, 减少开发和测试工作量, 这也是进行商业iOS游戏开发的一种主要开发 方法。 本节相关的完整原代码文件请参考本书附带的FlashBack.zip工程。 9.3 法术的释放(Ghost Castle) Ghost Castle是一款精美的RPG游戏, 这款游戏没有使用cocos2d游戏开 发库, 而是直接使用OpenGL ES库实现自定义的游戏引擎。游戏的故事是你扮演一个年 轻的骑士,爵士Lamorak先生,喜欢冒险同时也追逐名利,想证明在当地乡村的森林附 近被长期废弃的城堡中不存在有鬼这样的事情。当Lamorak先生到达铺满青苔的城堡时, 他开始感到不安, 仿佛有千双眼睛注视着他, 当他从骏马上跳下后,他的马, 最信赖的的伙 伴, 立刻转身,迅即快奔回城,留下我们勇敢的爵士Lamorak先生独自一人。伴随着凄厉 的冷风对他推搡,爵士Lamorak被吹入城堡巨大的木制門里,生锈的铰链伴随着吱吱响 的声音让人感觉恐怖, 慢慢地,爵士Lamorak面前一片黑暗, 他什么也看不见,但可以 听到风的呻吟和城堡中滴水的声音, 突然,一个冷风横扫而过,他身后的大門突然紧闭, 爵士Lamorak感到一阵恐慌, 他转身跑到門口拼命想把大門打开,但它怎么也打不开了, 他被困在了黑暗中。站在黑暗中,想知道到底为什么他决定来拜访这个地方,爵士 Lamorak透过黑暗听到一个邪恶的声音:“只有那些知道如何撤销法术的人可以离开这个 地方,否则你将和我们在这里...永远!” 爵士紧张得发抖,爵士先生现在站在一个黑暗的 城堡,绝对不知道如何释放法术,在那里可以找到,或者邪恶的声音属于谁。但是有一件 事情,可以肯定...他并不孤单。 游戏界面: 9.3.1 Ghost Castle中的Tile Map管理 Tile Map是Ghost Castle游戏的核心技术, 虽然该技术已经存在了将近20年历史,但仍然 有在游戏开发中使用它的理由, 使用Tile Map可以非常简单地将小块图片绘制成大地图, 如下图所示就是游戏在tiled地图编辑器中的情形: Tile Map通过二维数组将小块图片组织起来绘制屏幕区域, 每个Tile都包含一些重要信息, 比如: • 该Tile绘制的图片ID • 该Tile是否为屏障 • 该Tile是否可以给精灵造成伤害 在tiled地图编辑器中将地图编辑好以后, 通常会保存为XML格式的.tmx文件, 在你的游戏 中需要解析这个XML文件来重建你的地图, .tmx文件包含几个重要的元素: Map元素 <map version="1.0" orientation="orthogonal" width="200" height="200" tilewidth="40" tileheight="40"> 该元素为.tmx文件的顶层元素, 包含地图的宽度,高度, Tile的高度宽度等设置,你也可以设 置任意多的其它相关属性, 比如设置玩家的开始位置,通过Map -> Map Properties即可 添加: <property name="PlayerStartx" value="10"/> <property name="PlayerStarty" value="10"/> </properties> Tileset元素 Map元素可以包含一个或者多个tileset元素,但是通常的做法是包含一个即可, 以下是一个 tileset元素在.tmx文件中的示例: 9.3.2 cocos2d中的Tile Map管理 cocos2d提供了很好的Tile Map管理类, 使用cocos2d提供的包装类,你只需要使用很少 的代码即可实现Tile Map管理,以下是一个原始的包含草坪和雪树的Tile Map图片: 程序实现地图界面,同时将一棵雪树作为精灵(Sprite)移动到前面: cocos2d的Tile Map管理示范实例相关的完整原代码文件请参考本书附带的 isotilemap.zip工程。 Tile Map在2D游戏开发中仍然有着重要意义,使用功能强劲的地图编辑器如Tiled可以帮 助你减少大量的地图设计时间,使用属性和object groups可以创建数据驱动的游戏,通过 修改地图即可快速实现游戏的修改,这样使你的游戏具有强大而灵活的可定制性。 通过本节实例, 我们看到不采用cocos2d库而采用其它的引擎同样可以开发出各种商业 iOS游戏, 如果你不想使用cocos2d库, 也可以使用这里提供的游戏引擎来实现你的游戏, 而且定制引擎如添加额外的功能的工作量相对于cocos2d库来说还要少很多。 游戏的完整Xcode工程原代码文件请参考本书附带的GhostCastle.zip工程。 9.4 甜蜜的梦(Sweet Dreams) "为什么在你做梦的时候,玩具会从一个地方移动到另一个地方"? Sweet Dreams是一款玩起来非常轻松的休闲游戏, 游戏使用cocos2d开发库进行开发, 游戏充 分利用iPhone创新的用户界面控制方式, 通过倾斜手机移动角色, 控制速度和方向, 点击 屏幕进行跳跃, 摇动手机摆动绳索,梦幻般的音乐听起来让人心情愉快, 解决难题后即可获 得有奖金,以下是游戏的界面: 游戏使用"Model-View-Control"模式构建系统框架, 并使用Box2D作为物理引擎, 引擎则 作为模式中的"Model"部分将游戏中的精灵(Sprite)进行对象建模, 引擎包括间距连接 (Distance Joint)和旋转连接(Revolute Joint)将物体连结在一起接受物理作用, 每个精 灵都对应Box2D的一个刚体(b2Body)对象, 这样在精灵类对应的视图(View)和控制器 (Control)中就可以非常方便地使用Box2D提供的功能。 游戏物理建模类图: BaseModelObject的类定义: // BaseModelObject.h #import "IModelObject.h" @interface BaseModelObject : NSObject<IModelObject> { b2Body* physicalBody; float z; float width; float height; float linearDamping; float angularDamping; float density; float friction; float restitution; bool hasMass; bool isInWater; bool fixedRotation; } -(id) initInWorld:(b2World*) mWorld withRect:(CGRect) mLocation; @end BaseModelObject类包含物理模型基类的宽度,高度,密度,阻尼,摩擦,还原等属性, 游戏中 的云朵, 花, 精灵, 房屋等都属于该模型对象, 通过这样的物理建模, 游戏就可以非常方便地 使用Box2D提供的功能来进行精灵的位置更新和"碰撞检测"。 加速度传感器(Accelerometer) iOS提供了一个UIAccelerometer类来获取加速度数据,这个类属于Singleton类型,全局 唯一, 该类从传感器硬件读取数据, 如上图所示, 总共可以检测六个方向上的加速度, X,Y,Z 的取值都在-0.5~0.5之间, 你只要设置UIAccelerometer对象的delegete为你的对象(比 如UIApplication),你的对象就可以在回调接口中收到加速度数据更新通知: UIAccelerometer *accelerometer; self.accelerometer = [UIAccelerometer sharedAccelerometer]; self.accelerometer.updateInterval = .1; self.accelerometer.delegate = self; - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { labelX.text = [NSString stringWithFormat:@"X:%f", acceleration.x]; labelY.text = [NSString stringWithFormat:@"Y:%f", acceleration.y]; labelZ.text = [NSString stringWithFormat:@"Z:%f", acceleration.z]; self.progressX.progress = ABS(acceleration.x); self.progressY.progress = ABS(acceleration.y); self.progressZ.progress = ABS(acceleration.z); } 游戏在BaseGameLayer类中通过一个NSMutableArray类型的变量inputHandlers来管 理Accelerometer控制, 并在其didAccelerate()函数中遍历这个数组来将加速度数据通 知数组中的各个CharacterController对象, 这样各个精灵都能产生加速度作用: // BaseGameLayer.mm -(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{ for(id<IInputHandler> inputHandler in inputHandlers){ [inputHandler accelerometer:accelerometer didAccelerate:acceleration]; } } 在游戏的场景类中将CharacterController对象加入该数组: //Cow01Scene.mm -(void) spawnChar{ [self unschedule:@selector(spawnChar)]; CharacterController* character = [[[CowController alloc] initCharacter:self :CGRectMake(0, -110, 15, 42)] autorelease]; [self addChild:character z:CHARACTER_ATLAS_Z]; [self addInputHandler:character]; [spawnExit closeExit]; } 在CharacterController类的didAccelerate()方法中具体处理加速度数据: // CharacterController.mm - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration } 这里通过勾股定理计算平方根来得到倾斜度, 通过将acceleration.y和阈值进行比较获得 用户移动的方向, 即计算精灵应该向左还是向右移动, 或者应该保持位置不变, 这里移动阈 值的定义为加速度最大值的四分之一: #define MOVEMENT_ACCELERATION_THRESHOLD 0.125f 通过本节实例, 我们看到如何采用Box2D物理引擎进行对象建模, 如何结合Box2D物理引 擎和cocos2d库进行真实的商业iOS游戏开发, 使用Box2D和cocos2d库, 将极大地提高 游戏开发的效率, cocos2d库和Box2D的成熟性可以帮助你编写少量的代码即可实现游 戏的各种功能, 并且具有强大的灵活性和可扩展性。 本节相关的完整原代码文件请参考本书附带的SweetDreams.zip工程。 9.5 毁灭之战(RavagedByWar) Ravaged by War一款TD防御类游戏, 人类的生存受到威胁, 你需要建立一 系列的防御塔阻止敌人的进攻, 敌人有不同的类型, 有爬虫类,有飞行类以及各种古怪的类 型, 游戏有不同的等级和地图可供选择, 游戏界面呈现重金属风格, 这是一个非常令人上瘾 的游戏,因为敌人非常的狡猾, 会想方设法突破你的防线, 你必须快速而有策略地构建你 的防线, 设计圈套, 然后围歼敌人, 让敌人认为薄弱的防线其实是陷阱, 你在火车上, 汽车 上, 或者午休时间都可能玩它。 游戏主界面 战争场面 9.6.1 A*算法 A*算法经常用来计算上述游戏地图中的最短路径问题, 该算法也是使用最为广泛的一种算 法, 算法在搜索过程中设置OPEN和CLOSED两张表, OPEN表保存所有已生成而未考察 的节点, CLOSED表中记录已访问过的节点, 并采用启发式评估(Heuristic Estimate)公 式将许多明显为坏的路径进行排除, 进而快速技术出一条满意的路径, 公式如下: F(n) = G(n) + H(n) G(n): 从起点到目前节点的距离 H(n): 预测目前节点到目标节点的距离(此为A*算法的主要评价公式) F(n): 目前节点的评价分数 A*算法描述: 第一步: 将起始节点A放入OPEN表中。 第二步: 循环执行本步骤: a) 查找OPEN表中代价最小的节点作为"当前节点"(通过评价函数计算); b) 将"当前节点"添加进CLOSED表, 同时从OPEN表中删除; ... A*算法的伪程序如下: ... 毁灭之战中使用A*算法来计算突破玩家防线的最短路径, 算法主要在AStar.m文件的 shortestPathFromA()函数中实现: // AStar.m + (NSArray *)shortestPathFromA:(CGPoint)a ToB:(CGPoint)b OnGrid: (Grid *)grid WithCreepAttribute:(NSInteger)creepAttribute { AStarNode *startNode = [AStarNode AStarNodeWithPositionOnGrid:a AndGoal:b]; NSMutableArray *closed = [[[NSMutableArray alloc] init] autorelease]; NSMutableArray *open = [[[NSMutableArray alloc] init] autorelease]; ... return nil; } 在Creep.m文件中根据精灵(Creep)当前的位置调用shortestPathFromA()函数来更新 其的路径, 这样就实现了游戏主要的AI: // Creep.m - (NSArray *)updatePath { GridCell *gc = [[GameState sharedGameState].map.mapGrid gridCellForPositionOnGrid:self.gridPosition]; if (![gc isAccessibleWithCreepAttribute:self.attributes]) { self.gridPosition = self.lastGridPosition; } [self.path removeAllObjects]; self.path = [AStar shortestPathFromA:self.gridPosition ToB:self.exit OnGrid:[GameState sharedGameState].map.mapGrid WithCreepAttribute:self.attributes]; self.currentPathIndex = 0; [self performSelector:@selector(moveToNextPoint) withObject:nil afterDelay:.1]; [self stopAllActions]; return self.path; } 通过本节实例, 我们看到如何在游戏中实现AI, 如何使用A*算法实现最短路径计算, 游戏中 的AI通常是结合使用最佳路径算法和状态机实现游戏精灵的"智能反应", A*算法是游戏最 短路径计算中最基本的一个算法, 许多大型游戏采用了三层A*算法来实现游戏精灵的路径 选择, 采用好的AI算法将使你的iOS商业游戏具有更强的娱乐性, 同时也更具有竞争性。 本节相关的完整原代码文件请参考本书附带的RavagedByWar.zip工程。 9.6 吹吹鱼(PuffPuff) 吹吹鱼是一款非常好玩的竞技类游戏, 游戏让你游历蓝色的海底世界,你需要 掌握游戏技巧, 精确进行浮力控制,躲避鲨鱼和珊瑚礁, 游戏中你扮演一只鱼为了生存, 必须 避免和有害物体相撞,如珊瑚礁, 海底泄漏的石油,还有鲨鱼, 如果相撞你就会减少能量, 在 游戏屏幕的顶部有能量显示标志,如果你的能量水平达到危险的黑色,就意味着死亡的到来, 在快速运动中,如果遇到粉红色的海胆, 如果你吃掉它就能够增加能量。 游戏界面 游戏使用cocos2d作为系统框架, 并使用Chipmunk作为物理引擎, 在GameLayer类的 init()方法中初始化Chipmunk引擎,设置碰撞回调函数: //GameScene.mm -(id) init{ cpInitChipmunk(); cpBody *staticBody = cpBodyNew(INFINITY, INFINITY); space = cpSpaceNew(); cpSpaceResizeStaticHash(space, 100.0f, 10); cpSpaceResizeActiveHash(space, 50, 300); space->gravity = ccp(0, 0); space->damping =0.02; space->iterations =2; space->elasticIterations = 0; ... } … 通过本节实例, 我们看到如何采用Chipmunk物理引擎实现游戏精灵在高速运动中的"碰撞 检测", 因为Chipmunk引擎回调函数的灵活性,更主要是其有比Box2D更快的速度, 所有游 戏没有使用Box2D而是使用Chipmunk作为游戏的物理引擎, 另外游戏使用cocos2d库 作为游戏系统框架,充分利用库提供的功能可以使系统代码具有更好的模块化组织,更少 的代码也使游戏具有更好的扩展性和维护性, 结合使用Chipmunk物理引擎和cocos2d库 可以快速实现你的商业iOS游戏开发, 极大地提高游戏开发的效率, 使你的创意能在短时间 实现, 并使你的游戏产品能够以极短的时间上市销售,为你创造利润。 本节相关的完整Xcode工程原代码文件请参考本书附带的PuffPuff.zip工程。 9.7 本章总结 本章通过具体的iOS商业游戏实例分析, 介绍不同类型的iOS商业游戏的核心技术, 每个游 戏都具有iOS商业游戏的典型性和代表性, 读者通过这些实例分析iOS商业游戏的内部构 造,系统架构, 关键技术, 特别是通过对游戏原代码的分析, 掌握相关的游戏思路,设计,移植 和相关编程知识,以便将这些知识应用到具体的iOS商业游戏项目开发当中。

编辑推荐

  • 名称/格式
  • 评分
  • 下载次数
  • 资料大小
  • 上传时间

用户评论

0/200
    暂无评论
上传我的资料

相关资料

资料评价:

/ 34
所需积分:0 立即下载
返回
顶部
举报
资料
关闭

温馨提示

感谢您对爱问共享资料的支持,精彩活动将尽快为您呈现,敬请期待!