iPhone游戏开发 使用Cocos2d框架开发教程
iPhone游戏开发 使用Cocos2d框架开发教程是本文要介绍的内容,移动设备正改变我们工作和与他人互动的关系。新一轮革命正在我们身上发生,人们开始通过移动设备消费更多的数据内容。iPhone应用商店成为手机应用成功和流行的缩影,其中游戏是最热门的类别。在本篇文章中,我将展示如何用Cocos2d框架来制作iPhone游戏。
iphone游戏
Cocos2d框架
Cocos2d是用于构建iPhone游戏的开源框架,是基于iPhone核心SDK之上架构而成,提供可加速iPhone游戏开发的易用API。
下载和安装Cocos2d框架和模板
要使用Cocos2d框架的强大功能,第一步是下载和安装与框架相关的框架和模板。(游戏邦注:原文提供了框架和模板的下载地址。)
了解框架的基础
在开始制作首个iPhone游戏前,建议先熟悉下Cocos2d框架的基础,包括以下四项内容:
场景。场景这个节点很特殊,它是所有节点的基础。场景的目的在于呈现出游戏的可操作部分和展现游戏场景(游戏邦注:如游戏结束、主页面和高分排行榜等)。
层次。层次呈现出的是玩游戏的具体区域。Cocos2d中的层次与Photoshop的层次作用类似。这意味着某个场景可以由多个层次构成。一个层次承载背景画面,另一个层次便是游戏动作发生之初。
界面。界面指得是那些赋予游戏灵魂的事物。比如,如果你制作太空游戏,你的飞船和敌人就是界面。用于深化用户游戏体验的每个角色都可以当成是界面。
制作首个Cocos2d项目
打开Xcode,创建新项目。如图1所示,从项目模板菜单中选择Cocos2d项目。
图1:Cocos2d template for Xcode
点击“选择”进入下个场景。输入MyFirstCocos2dProject作为项目名称,然后点击“保存”。随后,系统便会通过默认模板来创建Cocos2d项目。这篇文章中所述的是Cocos2d框架的0.99版本,默认搜索的是SDK 4.0。如果你安装过最新版的SDK,你会收到如图2中所示的“基础SDK丢失”信息。
图2:Cocos2d project template base SDK missing
你所要做的是告诉Cocos2d框架我们正在使用的是更新版本的SDK。要达成此目标,点击“项目”标签下的“编辑项目设置”,然后如图3所示指定SDK版本。
图3:Selecting the installed SDK for iOS device
正如你从以上截屏中看到的那样,iOS SDK 4.0丢失,但我们可以选择iOS SDK 4.1。选择正确的SDK后,使用“指令B”构建整个项目。项目中不能有错误。实现上述目标后,你可以用“指令R”来运行应用。图4显示应用正在运行中iPhone模拟器的样式。
图4:The default Cocos2d project template output
Cocos2d模板有基础执行程序,使得屏幕上显示出“Hello World”的语句。每秒帧数(FPS)测量值显示在屏幕左下方(游戏邦注:图4中是60.0)。默认模板是为了验证开发者已正确安装框架以及与框架相关的所有组件。下个部分我们将继续深入挖掘Cocos2d框架。
开始使用Cocos2d框架
默认Cocos2d模板设定为横向模式显示,MyFirstCocos2dProjectAppDelegate.m文件中使用以下代码就可以轻易做出改变:
[director setDeviceOrientation:kCCDeviceOrientationPortrait];
现在,如果你运行应用就会发现,显示是纵向而不是横向。接下来,我们要改变游戏的背景。我们已经在项目的“资源”文件夹中加入文件Background3.png。资源文件夹存放所有应用中使用的资源(游戏邦注:如图片、声音文件等)。以下面的代码将背景图片设置在静态模式场景中:
+(id) scene { // ‘scene’ is an autorelease object. CCScene *scene = [CCScene node]; // ‘layer’ is an autorelease object. HelloWorld *layer = [HelloWorld node]; CCSprite *background = [CCSprite spriteWithFile:@"Background3.png"]; [layer addChild:background]; // add layer as a child to scene [scene addChild: layer]; // return the scene return scene; }
CCSprite类型包含spriteWithFile方法,输入文件名作为参数。使用addChild方式将背景界面加入到层次中,得到图5中显示的效果。
图5:Background sprite not positioned correctly
不幸的是,背景界面的位置不正确。我们需要为界面设置锚点,如图6所示。
图6:Background sprite positioned correctly
背景图片适合尺寸为320 x 480的屏幕。如果你计划让设备的转动发挥作用,那么你需要有张适合480 x 320横向模式的背景图片。在下一节中,我们将为应用添加界面。
添加界面
添加背景只是应用设计的开始,我们需要为游戏添加可操作的界面。我们将使用一张笑脸图片作为我们的活动界面。使用下列代码可为应用添加界面:
// on “init” you need to initialize your instance -(id) init { // always call “super” init // Apple recommends to re-assign “self” with the “super” return value if( (self=[super init] )) { // adding the sprite CCSprite *smiley = [CCSprite spriteWithFile:@"smiley.png"]; smiley.position = ccp(100,100); [self addChild:smiley]; } return self; }
使用最初的方法,我们创建CCSprite实例呈现笑脸角色。首先将笑脸放置在适当位置(100,100),随后添加到层中。如果你运行应用,你会发现笑脸看不见。原因在于笑脸位于背景层之后。为看到笑脸,我们将背景界面的Z轴值调为-1,将背景界面放置在笑脸界面之后,代码如下:[layer addChild:background z:-1];
图7显示调整后的结果。
图7:Smiley face sprite added to the game scene
在上述例子中,我们将笑脸放置在屏幕上时使用的是硬代码值。以下使用硬代码值在屏幕上放置元素是因为应用将以iPhone协调系统为基础。
如果你在iPad上运行应用,你会发现背景和界面的位置都有错误。为了让应用在iPhone和iPad设备上的显示效果相同,我们必须使用CGSize类别来深化当前设备的宽度值和高度值。以下代码显示如何使用CGSize:
// on “init” you need to initialize your instance -(id) init { // always call “super” init // Apple recommends to re-assign “self” with the “super” return value if( (self=[super init] )) { CGSize windowSize = [[CCDirector sharedDirector] winSize]; // adding the sprite CCSprite *smiley = [CCSprite spriteWithFile:@"smiley.png"]; smiley.position = ccp(windowSize.width/2,windowSize.height/2); [self addChild:smiley]; } return self; }
在上述代码中,我们使用CCDirector来恢复winSize实例。winSize是指当前运行的iOS设备的尺寸。这确保应用正确地在设备上运行。
现在,我们的笑脸还没有任何移动。在下节中,我们将介绍让笑脸在屏幕中移动的方法。
动作和顺序
Cocos2d使用动作为CCNode对象中的界面或其他对象添加效果。Cocos2d框架有许多内置动作,这些动作包括CCFadeTo、CCMoveTo和CCScaleBy等。以下代码使用CCMoveTo动作将笑脸移动到屏幕上的特定位置:
// on “init” you need to initialize your instance -(id) init { // always call “super” init // Apple recommends to re-assign “self” with the “super” return value if( (self=[super init] )) { CGSize windowSize = [[CCDirector sharedDirector] winSize]; // adding the sprite CCSprite *smiley = [CCSprite spriteWithFile:@"smiley.png"]; smiley.position = ccp(windowSize.width/2,windowSize.height/2); [self addChild:smiley]; // actions [smiley runAction:[CCMoveTo actionWithDuration:0.9 position:ccp(300,300)]]; } return self; }
在这个代码中,我们使用runAction方法来在笑脸界面上执行CCMoveTo动作。CCMoveTo动作方法使用actionWithDuration和位置参数。actionWithDuration是完成动作所需要的时间。位置参数指的是界面的移动地点。如果你运行应用,你会发现笑脸从原位置移动到新位置上。
在你需要界面执行诸多动作的同时,便产生了情节。对于这些情节,你可以使用CCSpawn类型,确保这些动作同时为界面所执行。以下代码便是CCSpawn在动作中的应用:
id moveAction = [CCMoveTo actionWithDuration:0.9 position:ccp(200,200)]; id fadeOutAction = [CCFadeOut actionWithDuration:0.9]; id callback = [CCCallFunc actionWithTarget:self selector:@selector(finishedAnimation)]; [smiley runAction:[CCSequence actions:moveAction,fadeOutAction,callback,nil]]; -(void) finishedAnimation { NSLog(@”animation has been finished!”); }
在这个代码中,你可以创建两个独立的动作,CCMoveTo和CCFadeOut。这两个动作都会以参数的形式递交给CCSpawn方法,使得笑脸CCSprite能够同时移动和淡出屏幕。
当使用CCActions时,找到动画的完结点很有用。在这段情节中,我们可以使用CCSequence类别。CCSequence让开发者可以陆续进行不同动作,然后最终会有回收功能显示动画已完成。以下代码便是CCSequence:
-(void) finishedAnimation { int x = arc4random() % 320; int y = arc4random() % 480; id moveAction = [CCMoveTo actionWithDuration:0.9 position:ccp(x,y)]; id callback = [CCCallFunc actionWithTarget:self selector:@selector(finishedAnimation)]; [smiley runAction:[CCSequence actions:moveAction,callback,nil]]; }
这个代码使用CCCallFunc类别创建出回收功能。一旦CCMoveTo和CCFadeOut两个动作均完成之后,回收功能就会被触发。以排除漏洞模式运行应用,你会发现在动画完成后,显示完成的日志信息动画会显示在屏幕上。
我们可以使用回收功能来不断重复动画,将界面移动到屏幕上的任意位置。这可以通过finishedAnimation功能实现,以下便是代码:
-(void) finishedAnimation { int x = arc4random() % 320; int y = arc4random() % 480; id moveAction = [CCMoveTo actionWithDuration:0.9 position:ccp(x,y)]; id callback = [CCCallFunc actionWithTarget:self selector:@selector(finishedAnimation)]; [smiley runAction:[CCSequence actions:moveAction,callback,nil]]; }
注意:上述代码可轻易独立成某个类别的方法,这会减少出现复制粘贴之类的错误。但为了让此文更为简洁,我已经复制了代码。
arc4random功能可用于随机生成从0到n-1的数字。我们根据iPhone屏幕尺寸(游戏邦注:即320 x 480像素)来限定这个随机数字。获得的坐标随后将传输至CCMoveTo功能的位置参数。finishedAnimation也可以用作回收方法,使得动画在结束后不断重复。运行应用,你会发现笑脸不断从某个随机位置移动到另一个随机位置。
触屏的使用
我们的笑脸在屏幕上自由移动,目前没有方法让它停下来。在本节中,我们将让用户可以通过接触事件来控制笑脸。处理接触事件的方法很多,为使设计简单我们使用CCTouchesBegin事件,这个事件在用户接触屏幕时触发。在使用CCTouchesBegin事件之前,使用原始方法确保isTouchEnabled特性设定为“是”:
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:[touch view]]; location = [[CCDirector sharedDirector] convertToGL:location]; }
以上使用的ccTouchesBegan方法可获得用户接触屏幕的坐标。在ccTouchesBegan事件中,我们需要得知用户是否接触笑脸。我们通过使用好用的老式毕达哥拉斯原理来实现这个目标。以下代码显示我们如何察觉笑脸是否已被接触:
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:[touch view]]; location = [[CCDirector sharedDirector] convertToGL:location]; float distance = pow(smiley.position.x – location.x, 2) + pow(smiley.position.y – location.y, 2); distance = sqrt(distance); if(distance <= 50) { [smiley runAction:[CCScaleBy actionWithDuration:0.9 scale:2.0]]; [self performSelector:@selector(removeSmileyFromLayer) withObject:nil afterDelay:1.2]; } }
在上述代码中,我们可以设置笑脸和触点间的最短距离。如果距离小于50像素,程序确实笑脸已被用户触及。随后我们运行CCScaleBy动作,为笑脸增大,随后使用传统removeSmileyFromLayer方法将其从层中移除。
添加CCParticles
现在,当用户触及笑脸时,它会增大随后消失。我们可以使用Cocos2d的Particles框架使之表现得更为出色。Particles框架让你可以通过数百个CCNode对象动画做出令人瞩目的效果。所有对象协调配合,创造出特殊的效果。
我们将使用ParticleExplode效果,这会在用户点击笑脸后创造出爆炸性的效果。以下代码显示如何为游戏添加特殊效果。我们在爆炸中使用相同的笑脸,这意味着一旦笑脸遭到点击,便会产生出更小的笑脸。
if(distance <= 50) { CCParticleExplosion *explosion = [[CCParticleExplosion alloc] init]; explosion.texture = [[CCTextureCache sharedTextureCache] addImage:@”smiley.png”]; [explosion setDuration:2]; [explosion setAutoRemoveOnFinish:YES]; explosion.position = self.smiley.position; [self addChild:explosion]; [self removeChild:self.smiley cleanup:YES]; self.smiley = nil; }
在上述代码中,我们已将CCParticleExplosion效果初始化,这是Cocos2d框架中许多可用的CCParticles效果之一。粒子效果间隔时间设定为2秒,粒子对象设定为自动移除。
效果显示在图8中。
图8:CCParticleExplosion effect in action