为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

如何使用cocos2d制作一个太空射击游戏

2012-03-05 27页 pdf 482KB 31阅读

用户头像

is_144099

暂无简介

举报
如何使用cocos2d制作一个太空射击游戏 版权属于:子龙山人 首发于:泰然论坛 如何使用 cocos2d 制作一个太空射击游戏 版权属于:子龙山人 首发于:泰然论坛 整理:滔小滔 免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供 学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何 纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作! 原文链接地址: http://www.raywenderlich.com/3611/how-to-ma...
如何使用cocos2d制作一个太空射击游戏
版权属于:子龙山人 首发于:泰然论坛 如何使用 cocos2d 制作一个太空射击游戏 版权属于:子龙山人 首发于:泰然论坛 整理:滔小滔 免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供 学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何 纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作! 原文链接地址: http://www.raywenderlich.com/3611/how-to-make-a-space-shooter-iphone- game 程序截图: 在这个教程里面,你将会学习到如何为 iPhone开发一个太空射击游戏! 你可以使用加速计(重力感应)来控制飞船的移动,并且可以点击屏幕来发 射激光武器。 如果你对于如何制作 iphone游戏完全陌生的话,这个教程可以帮助你!你 将会学习到,如何从头至尾构建一个完整的游戏,不需要任何的经验! 假如你对 cocos2d 编程完全陌生的话,那么你可能需要先学习一下相关的教 程了。 这个教程对于中级开发者来说也非常好,因为它覆盖了一些比较高级的主 ,比如视差滚动(parallax scrolling),预分配 CCNode,加速计移动以及 粒子系统的使用。 版权属于:子龙山人 首发于:泰然论坛 话不多说,直入主题! 安装 cocos2d 为了制作这个游戏,你需要成为 iOS developer program 的一员(这样 的话,你的程序就能够安装到你的 iPhone上面去,不过听说网上有人越狱也可 以安装,知道的朋友麻烦给个链接,谢谢!)同时,需要安装 Xcode 和 cocos2d 框架。 如果你之前已经安装过 cocos2d了,那接下来这部分就不要看了。(如果想 使用新的 cocos2d版本,只需要把之前安装的目录下面的模板文件全部删除,再 按照下面的指令重新安装即可)。如果你重来没有安装过 cocos2d的话,那么只 需要按照下面的指令序列,一步步地安装到你的 mac上面就行了。  首先下载 Cocos2D .确定获得最新版本--作者写这篇文章的时候是 1.0.0-rc2版本,目前是 1.0.0-rc3版本。虽然不是稳定版本,但是,没 关系,其实很稳定啦!:)  双击下载下来的文件,并且解压缩到一个安全的位置。  打开 Terminal (Applications\Utilities\Terminal), 然后使用 cd命令 定位到刚刚解压缩的 cocos2d文件夹下面去。然后运 行./install-templates.sh来安装 xcode 模板,如下面所示: $ cd Downloads $ cd cocos2d-iphone-1.0.0-rc2 $ ./install-templates.sh -f -u 如果一切顺利的话,你应该会看到终端里面一系列的输出语句: “ Installing xxx template”。 然后重新启动 Xcode,祝贺你,您已成功安装 cocos2d了! Hello, Cocos2D! 让我们首先创建一个“Hello World”cocos2d 。 版权属于:子龙山人 首发于:泰然论坛 打开 Xcode,选择 File\New\New Project,然后选 iOS\cocos2d template, 接下来点 Next,并且把工程命名为 SpaceGame,再点 Next并选择一个文件夹作 为你的工程的保存路径,最后点 Create。 编译并运行工程,你将会看到一个“Hello World”出现在屏幕的正中间。 添加相关资源文件 为了做这样一个 iphone游戏,你将需要一些跟太空主题相关的图片资源和 声音资源。 你可以直接下载我老婆制作的太空游戏资源。 因此,请直接下载吧,并且把它解压到你的硬盘的某个目录下面去。 一旦你解压完这些资源以后,把 Backgrounds,Fonts,Particles,Sounds 和 Spritesheets 文件夹拖到 Resouces分组下面去。(基本上,除了 Classes 文件夹以外,其它所有的文件压都拖到 Resource 目录下面去) 确保 “Copy items into destination group’s folder (if needed)”被 复选中,然后点击 Finish。 当你做完这些事之后,你的工程的分组看起来会是下图所示的样子: 版权属于:子龙山人 首发于:泰然论坛 如果你很好奇,你可以随便看看你刚刚向工程里面添加进去了一些什么东 西。下面是完整的内容列表:  Backgrounds: 一些背景图片,你等下会使用它们来制作一个滚动背景。 里面包含星系,太阳,和空间异常(它移动速度比较慢),还有一组空间 尘埃图片(它们会出现在背景前面,而且会移动地稍微快一点)  Fonts: 使用 Glyph Designer制作的位图字体,我们将使用这些字体来 在游戏中显示文字。  Particles: 使用 Particle Designer 制作的一些特殊的粒子效果。 在 这里,我们用来创建星星飞动的效果。  Sounds: 一些与太空相关的背景音乐和音效。使用 Garage Band 和 cxfr 制作的。  Spritesheets: 一张为 pvr.ccz 的大图片,里面包含了游戏中将要用 到的许多小图片,比如陨石,太空船等。这个文件使用 Texture Packer 版权属于:子龙山人 首发于:泰然论坛 制作的---如果你想使用 pvr.ccz文件格式的话,你可能就需要使用这个 工具。当然 pvr.ccz 格式的优点就是文件小,加载速度快。 如果你还没安装上面任何一款工具的话,也不用担心!对于这个教程来说, 你完全不需要他们,你可以使用我已经制作好的这些资源就够了。以后,如果有 条件,你可以再去试试上面提到的工具。 下面就是 Sprites.pvr.ccz文件,它看起来如下图所示: 你可能会奇怪,为什么要把所有的这些图片都弄成这样一张大图呢?因为, 首先,它可以帮助节省内存,同时还可以提高性能。 接下来,让我们开始 coding吧!:) 添加一个太空船 首先,让我们在屏幕上添加一艘太空船吧! 打开 HelloWorldLayer.h文件,然后在@interface里面添加两个实例变量: 版权属于:子龙山人 首发于:泰然论坛 CCSpriteBatchNode *_batchNode; CCSprite *_ship; 第一个变量 (_batchNode)是必须的,因为我们将把所有的图片存储在一张 图片里面,然后使用这个 BatchNode就可以仅使用一次 opengl调用来做所有的 绘图操作。 第二个变量(_ship)代表屏幕上的太空飞船。 接下来,打开 HelloWorldLayer.m,并且把 init改成下面的样子: -(id) init { if( (self=[super init])) { _batchNode = [CCSpriteBatchNode batchNodeWithFile:@"Sprites.pvr.ccz"]; // 1 [self addChild:_batchNode]; // 2 [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: @"Sprites.plist"]; // 3 _ship = [CCSprite spriteWithSpriteFrameName:@"SpaceFlier_sm_1.png"]; // 4 CGSize winSize = [CCDirector sharedDirector].winSize; // 5 _ship.position = ccp(winSize.width * 0.1, winSize.height * 0.5); // 6 [_batchNode addChild:_ship z:1]; // 7 } return self; } 让我们一句一句地解释上面的代码:  使用一张大的图片创建一个 CCSpriteBatchNode 对象来批处理所有的对 象的描绘操作。接收的参数是 Sprites.pvr.ccz。  把 CCSpriteBatchNode 添加到当前层里面去,这样就可以绘制它的所有的 孩子对象。 版权属于:子龙山人 首发于:泰然论坛  加载 Sprites.plist 文件,它里面包含了这张大图里面的所有的小图的位 置坐标信息。这样,你以后可以非常方便地使用 spriteWithSpriteFrameName 来提取一张张小图片来初使化一些精灵。  使用 SpaceFlier_sm_1.png图片来创建一个精灵,注意这张图片是大图 里的一个子图。  使用 CCDirector 来获得屏幕的大小---我们接下来会用到这个大小。  设置飞船的位置在屏幕宽度的 10%,高度的 50处。注意,飞船的中心点 位置默认是飞船的中心。  把 ship当作 batchNode的一个孩子添加进去,这样的话,这些精灵就会 被批处理显示出来。 编译并运行工程,你将会看到你的飞船图片出现在屏幕上面啦! 添加视差滚动 我们已经有一个很酷的飞船在屏幕上了,但是,它看起来就好像坐在那里一 样,毫无生气!我们可以通过往里面添加视差滚动背景来解决这个问题。 但是,等一下,到底什么是视差滚动了? 视差滚动,简单来说,就是“移动背景中的一些图片比其它图片慢一点点”, 打个比方,一个背景中的物体有远有近,近的背景移动地快(比如地面),远的 背景移动地慢(比如天空),这样子就会形成景深不一样的视差效果出来。 版权属于:子龙山人 首发于:泰然论坛 想要在 cocos2d 里面使用视差滚动效果非常简单。你只需要做 3 步就 ok了:  创建一个 CCParallaxNode,然后把它加到层中去。  创建你想要滚动的元素,然后通过调用 CCParallaxNode的 addChild:parallaxRatio:positionOffset 方法把这些元素添加进去。  移动 CCParallaxNode 来滚动背景。这样的话,CCParallaxNode 就会根据 parallaxRatio 的不同,或快或慢地移动它里面添加的元素了。 让我们看看这个过程具体是怎样的。打开 HelloWorldLayer.h,然后在 @interface里面加入下面代码: CCParallaxNode *_backgroundNode; CCSprite *_spacedust1; CCSprite *_spacedust2; CCSprite *_planetsunrise; CCSprite *_galaxy; CCSprite *_spacialanomaly; CCSprite *_spacialanomaly2; 然后,转到 HelloWorldLayer.m 文件,在 init方法的底部加入下面的代码: // 1) Create the CCParallaxNode _backgroundNode = [CCParallaxNode node]; [self addChild:_backgroundNode z:-1]; // 2) Create the sprites we'll add to the CCParallaxNode _spacedust1 = [CCSprite spriteWithFile:@"bg_front_spacedust.png"]; _spacedust2 = [CCSprite spriteWithFile:@"bg_front_spacedust.png"]; _planetsunrise = [CCSprite spriteWithFile:@"bg_planetsunrise.png"]; _galaxy = [CCSprite spriteWithFile:@"bg_galaxy.png"]; _spacialanomaly = [CCSprite spriteWithFile:@"bg_spacialanomaly.png"]; _spacialanomaly2 = [CCSprite spriteWithFile:@"bg_spacialanomaly2.png "]; // 3) Determine relative movement speeds for space dust and backgroun d 版权属于:子龙山人 首发于:泰然论坛 CGPoint dustSpeed = ccp(0.1, 0.1); CGPoint bgSpeed = ccp(0.05, 0.05); // 4) Add children to CCParallaxNode [_backgroundNode addChild:_spacedust1 z:0 parallaxRatio:dustSpeed pos itionOffset:ccp(0,winSize.height/2)]; [_backgroundNode addChild:_spacedust2 z:0 parallaxRatio:dustSpeed pos itionOffset:ccp(_spacedust1.contentSize.width,winSize.height/2)]; [_backgroundNode addChild:_galaxy z:-1 parallaxRatio:bgSpeed position Offset:ccp(0,winSize.height * 0.7)]; [_backgroundNode addChild:_planetsunrise z:-1 parallaxRatio:bgSpeed p ositionOffset:ccp(600,winSize.height * 0)]; [_backgroundNode addChild:_spacialanomaly z:-1 parallaxRatio:bgSpeed positionOffset:ccp(900,winSize.height * 0.3)]; [_backgroundNode addChild:_spacialanomaly2 z:-1 parallaxRatio:bgSpeed positionOffset:ccp(1500,winSize.height * 0.9)]; 编译并运行工程,你将会看到飞船背景了。 然而,这还不是很有趣,因为还没有任何东西在动! 版权属于:子龙山人 首发于:泰然论坛 为了移动太空尘埃和相关背景层,你只需要移动一样东西就可以了,那就是 parallaxNode。对于移动 parallax node的每一个 y值,灰尘就会移动 0.1y值, 同时背景会移动 0.05y 值。 为了移动 parallax 节点,你只需要飞一帧更新一下它的位置就可以了。打 开 HelloWorldLayer.m 文件,加入下列的代码:(添加位置注意看注释) // Add to end of init method [self scheduleUpdate]; // Add new update method - (void)update:(ccTime)dt { CGPoint backgroundScrollVel = ccp(-1000, 0); _backgroundNode.position = ccpAdd(_backgroundNode.position, ccpMult(b ackgroundScrollVel, dt)); } 编译并运行工程,你会看到,使用 parallax 来做视差滚动效果真是太简洁 了! 版权属于:子龙山人 首发于:泰然论坛 然后,运行几秒钟之后,你会发现一个问题:背景滚动完之后没有了!我们 只得到了一个黑色的屏幕!那真是太糟糕了!好,接下来,看看我是怎么解决的 吧! 连续地滚动 我们想要背景保持无限地连续滚动效果。我们的做法就是,当背景移出屏幕 的左边的时候,就马上把它移动到屏幕右边的适当的位置上去。 这里有一个小小的问题,目前 CCParallaxNode 并不支持直接修改它的每个 孩子的 offset。你不能够简单地更新它的孩子的坐标点,因为 CCParallaxNode 每次更新的时候会覆盖那些改变。 不过没关系,我已经制作了一个 CCParallaxNode 的分类,它可以用来解决 这个问题,这个 Category 可以在项目的资源文件下面的 Classes文件夹中找到。 把 CCParallaxNode-Extras.h 和 CCParallaxNode-Extras.m拖到工程中去,同 时确保 “Copy items into destination group’s folder”被复选中,然后点 击 Finish。 然后,在 HelloWorldLayer.m 中做下列改变来实现连续滚动的效果: // Add to top of file #import "CCParallaxNode-Extras.h" // Add at end of your update method NSArray *spaceDusts = [NSArray arrayWithObjects:_spacedust1, _spacedu st2, nil]; for (CCSprite *spaceDust in spaceDusts) { if ([_backgroundNode convertToWorldSpace:spaceDust.position].x < -spa ceDust.contentSize.width) { [_backgroundNode incrementOffset:ccp(2*spaceDust.contentSize.width,0) forChild:spaceDust]; } } NSArray *backgrounds = [NSArray arrayWithObjects:_planetsunrise, _gal axy, _spacialanomaly, _spacialanomaly2, nil]; 版权属于:子龙山人 首发于:泰然论坛 for (CCSprite *background in backgrounds) { if ([_backgroundNode convertToWorldSpace:background.position].x < -ba ckground.contentSize.width) { [_backgroundNode incrementOffset:ccp(2000,0) forChild:background]; } } 编译并运行工程,这时你可以看到有一个无限连续滚动的背景了! 添加星星 没有哪一个太空射击游戏是没有星星在旁边飞的! 同样的,我们也可以创建相应的星星图片,并且把它当作 paralla 节点的一 个孩子添加进去。但是,这里我们不想这么做,因为星星是一个非常好的介绍粒 子系统的例子。 粒子系统能够让你使用同样的精灵创建大量的小对象,并且非常高效。 cocos2d给了你很多配置粒子系统的参数, Particle Designer这个工具可以使 这些参数的配置可视化。 但是,这个教程里面,我们不会涉及如何调整粒子系统的各项参数,我们使 用已经做好的星星的粒子效果。只需要在 init 方法中把它简单地添加进来即可: 版权属于:子龙山人 首发于:泰然论坛 NSArray *starsArray = [NSArray arrayWithObjects:@"Stars1.plist", @"St ars2.plist", @"Stars3.plist", nil]; for(NSString *stars in starsArray) { CCParticleSystemQuad *starsEffect = [CCParticleSystemQuad particleWit hFile:stars]; [self addChild:starsEffect z:1]; } 通过把粒子系统加到层中去,接着它会自动运行起来。编译并运行代码,你 现在可以看到好多星星在屏幕上飞过了!:) 使用加速计来移动飞船 到目前为止,还是很好,但是,如果我们不能控制飞船的移动的话,那就不 是一个完整的游戏! 这里,我们将采用加速计来移动太空飞船。当用户沿着 x轴方向倾斜设备的 时候,飞船就会上下移动。 这个功能实际上非常容易实现。首先,在 HelloWorldLayer.h里面的 @interface里面添加一个成员变量,用来记录飞船沿着 y轴方向每秒移动的点 的个数。(这个点不一定等于一个实际的像素点,如果是 Retina的设备,一个 点=2个像素) 版权属于:子龙山人 首发于:泰然论坛 float _shipPointsPerSecY; 然后,在 HelloWorldLayer.m 中做如下修改: // 1) Add to bottom of init self.isAccelerometerEnabled = YES; // 2) Add new method - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate: (UIAcceleration *)acceleration { #define kFilteringFactor 0.1 #define kRestAccelX -0.6 #define kShipMaxPointsPerSec (winSize.height*0.5) #define kMaxDiffX 0.2 UIAccelerationValue rollingX, rollingY, rollingZ; rollingX = (acceleration.x * kFilteringFactor) + (rollingX * (1.0 - k FilteringFactor)); rollingY = (acceleration.y * kFilteringFactor) + (rollingY * (1.0 - k FilteringFactor)); rollingZ = (acceleration.z * kFilteringFactor) + (rollingZ * (1.0 - k FilteringFactor)); float accelX = acceleration.x - rollingX; float accelY = acceleration.y - rollingY; float accelZ = acceleration.z - rollingZ; CGSize winSize = [CCDirector sharedDirector].winSize; float accelDiff = accelX - kRestAccelX; float accelFraction = accelDiff / kMaxDiffX; float pointsPerSec = kShipMaxPointsPerSec * accelFraction; _shipPointsPerSecY = pointsPerSec; 版权属于:子龙山人 首发于:泰然论坛 } // 4) Add to bottom of update CGSize winSize = [CCDirector sharedDirector].winSize; float maxY = winSize.height - _ship.contentSize.height/2; float minY = _ship.contentSize.height/2; float newY = _ship.position.y + (_shipPointsPerSecY * dt); newY = MIN(MAX(newY, minY), maxY); _ship.position = ccp(_ship.position.x, newY); 让我们一点点剖析一下这段代码:  添加这行代码的作用是让当前的层可以接收到加速计移动事件,当有事件 发生的时候,会回调 accelerometer:didAcccelerate 这个方法。  这个方法的前面一部分是直接从 Apple 的样例代码中 copy过来的,所做 的事情其实是某种意义上的“滤波”。其实你也不用理解它的原理,基本上 就是为了让飞船的移动更加平滑。如果你实在是对此非常感兴趣,可以查看 这里来获得一些信息。不管怎么说,在运行完这个滤波之后,我们可以测试 下看看,到底有哪些改进。通过实现证明,这种方法确实感觉不错!  基于每秒沿 y轴方向移动的点数,来更新飞船的位置。同时要注意边界值 的判断。 编译并运行工程(一定要编译到真机上面,否则模拟器是没有加速计效果的, 你不可能抱着电脑摇吧:))。这时,上下晃动真机,你可以操作你的飞船移动 了! 版权属于:子龙山人 首发于:泰然论坛 添加陨石 这个游戏目前看起来还不错,但是,危险和激情在哪里呢?让我们往场景中 添加一些陨石吧! 我们接下来将要采纳的方法其实是非常普遍的做法,我们在右边屏幕之后创 建一些陨石,然后利用 cocos2d的 action把它移动到屏幕的左边去。 我们可以在每次需要一个陨石的时候,马上创建一个对象,但是,分配内存 的操作是非常慢的!所以你最好不要这样做!因此,我们可以预先分配好一堆陨 石对象,这样当需要一个陨石对象的时候,就从中抓取一个就 ok了。 好,我们看看具体该怎么做吧。打开 HelloWorldLayer.h,然后往类中添加 下列成员变量: CCArray *_asteroids; int _nextAsteroid; double _nextAsteroidSpawn; 接下来在 HelloWorldLayer.m 里面做如下修改: // Add to top of file #define kNumAsteroids 15 版权属于:子龙山人 首发于:泰然论坛 // Add to bottom of init _asteroids = [[CCArray alloc] initWithCapacity:kNumAsteroids]; for(int i = 0; i < kNumAsteroids; ++i) { CCSprite *asteroid = [CCSprite spriteWithSpriteFrameName:@"asteroid.p ng"]; asteroid.visible = NO; [_batchNode addChild:asteroid]; [_asteroids addObject:asteroid]; } // Add new method, above update loop - (float)randomValueBetween:(float)low andValue:(float)high { return (((float) arc4random() / 0xFFFFFFFFu) * (high - low)) + low; } // Add to bottom of update loop double curTime = CACurrentMediaTime(); if (curTime > _nextAsteroidSpawn) { float randSecs = [self randomValueBetween:0.20 andValue:1.0]; _nextAsteroidSpawn = randSecs + curTime; float randY = [self randomValueBetween:0.0 andValue:winSize.height]; float randDuration = [self randomValueBetween:2.0 andValue:10.0]; CCSprite *asteroid = [_asteroids objectAtIndex:_nextAsteroid]; _nextAsteroid++; if (_nextAsteroid >= _asteroids.count) _nextAsteroid = 0; [asteroid stopAllActions]; asteroid.position = ccp(winSize.width+asteroid.contentSize.width/2, r andY); asteroid.visible = YES; [asteroid runAction:[CCSequence actions: 版权属于:子龙山人 首发于:泰然论坛 [CCMoveBy actionWithDuration:randDuration position:ccp(-winSize.width -asteroid.contentSize.width, 0)], [CCCallFuncN actionWithTarget:self selector:@selector(setInvisible:)], nil]]; } // Add new method - (void)setInvisible:(CCNode *)node { node.visible = NO; } 关于上面的代码,有几点需要说明一下:  CCArray 和 NSArray差不多,但是做了速度方面的优化。所以如果可以的 话,尽可能多地使用 CCArray。  注意,我们添加了 15个陨石到 batchNode 中去了。但是,把它们都设置 成了不可见。如果是不可见的,就把它当前是未激活的。  我们使用一个实例变量 (_nextAsteroidSpawn) 来指示下一个陨石出 现的时间点。我们会在 update循环中一直检测这个变量的值。  如果你对 cocos2d的 action还很陌生的话,其实 action就是一种很简单 的,可以让精灵在一段时间做一些事情的对象。比如,你可以让精灵在指 定的一段时间内,让它旋转、缩放、移动等等。这里,我们执行了 2个 action 的序列:一个从右边移动到左边的 action,还有一个是当前一个 action 结束时,调用另一个把陨石设置为不可见的 action。这两个 action 的顺序是固定的。 编译并运行代码,这时候你可以看见一些陨石在屏幕上飞过啦! 版权属于:子龙山人 首发于:泰然论坛 发射激光 我不清楚你是怎么想的,当我看到屏幕上有陨石在飞的时候,我的第一感觉 就是,把它们干掉! 因此,让我们给飞船添加发射激光武器的功能吧!这段代码和我们之前添加 陨石的代码有点类似,因为我们会创建一组可以重用的激光束,同时使用 action 来移动这些激光束。 主要的区别就是,我们将使用 touch事件来发射激光。 首先打开 HelloWorldLayer.h,然后在类中添加下面成员变量: CCArray *_shipLasers; int _nextShipLaser; 然后在 HelloWorldLayer.m 做如下修改: // Add to top of file #define kNumLasers 5 // Add to bottom of init _shipLasers = [[CCArray alloc] initWithCapacity:kNumLasers]; 版权属于:子龙山人 首发于:泰然论坛 for(int i = 0; i < kNumLasers; ++i) { CCSprite *shipLaser = [CCSprite spriteWithSpriteFrameName:@"laserbeam _blue.png"]; shipLaser.visible = NO; [_batchNode addChild:shipLaser]; [_shipLasers addObject:shipLaser]; } self.isTouchEnabled = YES; // Add new method - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { CGSize winSize = [CCDirector sharedDirector].winSize; CCSprite *shipLaser = [_shipLasers objectAtIndex:_nextShipLaser]; _nextShipLaser++; if (_nextShipLaser >= _shipLasers.count) _nextShipLaser = 0; shipLaser.position = ccpAdd(_ship.position, ccp(shipLaser.contentSize. width/2, 0)); shipLaser.visible = YES; [shipLaser stopAllActions]; [shipLaser runAction:[CCSequence actions: [CCMoveBy actionWithDuration:0.5 position:ccp(winSize.width, 0)], [CCCallFuncN actionWithTarget:self selector:@selector(setInvisible:)], nil]]; } 这个例子也向你展示了,在 cocos2d里面接收 touch事件是多么容易啊--- 仅需要把 isTouchEnabled设置为 yes就 ok了。然后你需要实现 ccTouchesBeban (或者 ccTouchesMoved,ccTouchesEnded等等)。 编译并运行代码,现在你可以发射激光武器了。 版权属于:子龙山人 首发于:泰然论坛 基本的碰撞检测 恩,到目前为止,这看起来有点像一个游戏了,但是,还不够完整,因为没 有爆炸! 而且我天性不听话,喜欢搞破坏,所以是时候往游戏里面添加一些破坏啦!:) 打开 HelloWorldLayer.h,然后添加下面的实例变量: int _lives; 然后 update方法的最后面添加下面代码: for (CCSprite *asteroid in _asteroids) { if (!asteroid.visible) continue; for (CCSprite *shipLaser in _shipLasers) { if (!shipLaser.visible) continue; if (CGRectIntersectsRect(shipLaser.boundingBox, asteroid.boundingBox)) { shipLaser.visible = NO; asteroid.visible = NO; 版权属于:子龙山人 首发于:泰然论坛 continue; } } if (CGRectIntersectsRect(_ship.boundingBox, asteroid.boundingBox)) { asteroid.visible = NO; [_ship runAction:[CCBlink actionWithDuration:1.0 blinks:9]]; _lives--; } } 这里使用了最最简单的方式,只是判断两个精灵的边界矩形是否有交集。注 意,边界部分可能有透明,而且边界矩形不能反应精灵实例的轮廓,所以最好的 做法是使用前面介绍的 box2d的方法。不过没关系,这个游戏,我们这样做就可 以了。 对于更好的使用 box2d的方法,请查看《如何只使用 box2d来做碰撞检测》。 编译并运行代码,现在你会看到有东西爆炸啦! 胜利/失败条件检测 我们差不多快做完了---现在只需要往游戏中添加判断游戏胜利或者失败的 条件就可以了。 我是这样考虑的,只要玩家存活了 30秒,就是胜利;如果被陨石打中了 3 次,那么就是失败。 因此,在 HelloWorldLayer.h 中做如下修改: // Add before @interface typedef enum { kEndReasonWin, kEndReasonLose } EndReason; // Add inside @interface 版权属于:子龙山人 首发于:泰然论坛 double _gameOverTime; bool _gameOver; 同时,相应地修改 HelloWorldLayer.m: // Add at end of init _lives = 3; double curTime = CACurrentMediaTime(); _gameOverTime = curTime + 30.0; // Add at end of update loop if (_lives <= 0) { [_ship stopAllActions]; _ship.visible = FALSE; [self endScene:kEndReasonLose]; } else if (curTime >= _gameOverTime) { [self endScene:kEndReasonWin]; } // Add new methods above update - (void)restartTapped:(id)sender { [[CCDirector sharedDirector] replaceScene:[CCTransitionZoomFlipX tran sitionWithDuration:0.5 scene:[HelloWorldLayer scene]]]; } - (void)endScene:(EndReason)endReason { if (_gameOver) return; _gameOver = true; CGSize winSize = [CCDirector sharedDirector].winSize; NSString *message; if (endReason == kEndReasonWin) { message = @"You win!"; } else if (endReason == kEndReasonLose) { 版权属于:子龙山人 首发于:泰然论坛 message = @"You lose!"; } CCLabelBMFont *label; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { label = [CCLabelBMFont labelWithString:message fntFile:@"Arial-hd.fnt "]; } else { label = [CCLabelBMFont labelWithString:message fntFile:@"Arial.fnt"]; } label.scale = 0.1; label.position = ccp(winSize.width/2, winSize.height * 0.6); [self addChild:label]; CCLabelBMFont *restartLabel; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { restartLabel = [CCLabelBMFont labelWithString:@"Restart" fntFile:@"Ar ial-hd.fnt"]; } else { restartLabel = [CCLabelBMFont labelWithString:@"Restart" fntFile:@"Ar ial.fnt"]; } CCMenuItemLabel *restartItem = [CCMenuItemLabel itemWithLabel:restart Label target:self selector:@selector(restartTapped:)]; restartItem.scale = 0.1; restartItem.position = ccp(winSize.width/2, winSize.height * 0.4); CCMenu *menu = [CCMenu menuWithItems:restartItem, nil]; menu.position = CGPointZero; [self addChild:menu]; [restartItem runAction:[CCScaleTo actionWithDuration:0.5 scale:1.0]]; [label runAction:[CCScaleTo actionWithDuration:0.5 scale:1.0]]; 版权属于:子龙山人 首发于:泰然论坛 } 如果你不理解 endScene方法的话,也没关系---那些代码是我过去用来快速 地判断游戏胜利或失败的方式。 真正重要的是,你要理解其它部分的代码---在每一个 update循环中,你只 检测玩家是否胜利或失败,然后相应地调那个方法就可以了。 编译并运行代码,看看你会不会输? 免费的音乐和音效 你懂的,我怎么可能不给你们提供一些很棒的音效和音效呢? 之前,你已经把相关的音乐和音效加到工程里面来了,因此,我们只需要在 HelloWorldLayer.m 中做如下修改即可: // Add to top of file #import "SimpleAudioEngine.h" // Add to bottom of init [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"SpaceGame.caf " loop:YES]; 版权属于:子龙山人 首发于:泰然论坛 [[SimpleAudioEngine sharedEngine] preloadEffect:@"explosion_large.caf "]; [[SimpleAud
/
本文档为【如何使用cocos2d制作一个太空射击游戏】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索