上海龙雨建设工程有限公司网站,建设人才网证书查询,网页版qq在线登录界面,深圳市住房和建设局薛峰简历免责申明#xff08;必读#xff01;#xff09;#xff1a;本博客提供的所有教程的翻译原稿均来自于互联网#xff0c;仅供学习交流之用#xff0c;切勿进行商业传播。同时#xff0c;转载时不要移除本申明。如产生任何纠纷#xff0c;均与本博客所有人、发表该翻译稿… 免责申明必读本博客提供的所有教程的翻译原稿均来自于互联网仅供学习交流之用切勿进行商业传播。同时转载时不要移除本申明。如产生任何纠纷均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作 原文链接地址http://www.raywenderlich.com/1163/how-to-make-a-tile-based-game-with-cocos2d 教程截图 在这个部分的教程中我将会教大家如何使用cocos2d来做一个基于tile地图的游戏当然还有Tiled地图编辑器。我们小时候玩的小霸王小学机里面的游戏大部分都是基于tile地图的游戏如坦克大战、冒险岛、吞食天地等我们将会创建一个忍者在沙漠中找西瓜吃的小游戏。-_- 在第一部分教程中我将教大家如何使用Tile来创建地图怎样把地图加到游戏中怎么让地图跟随玩家滚动以及怎样使用对象层。 在第二部分教程中我将介绍如何在地图中创建可碰撞的区域如何使用tile属性如何制作可拾取的物体和动态修改地图还有确保忍者不要吃撑了 如果你还没有准备好的话你可能需要先从《如何使用cocos2d来制作简单的iphone游戏》系列教程开始学起因为我们这个教程使用了大量的基本概念而这些概念都可以从上面的教程中获取。 好了让我们玩一玩tile地图吧 创建工程骨架 让我们首先创建整个工程的骨架这样可以确保今后我们需要的文件都包含进来了并且能够跑起来。 因此启动XCode点击“File\New Project...”选择cocos2d Application template并且把工程命名为TileGame。 接下来下载游戏资源文件。这个资源文件包里包含了以下内容 玩家sprite。这个图片和《如何使用cocos2d来制作简单的iphone游戏》差不多。我使用cxfr这个工具制作的一些音效。我使用Garage Band制作的一些背景音乐。查看这篇博文获得更多的信息我们将会使用的tile集合--它实际上会和tile地图编辑器一块儿使用但是我想把它放在这里余下的事情会变得更容易。 一些额外的“特殊”的tile我将会在后面加以说明。 一旦你获得了这些资源解压并把它拖到你的工程的“Resources”分组下面。确保复选中“Copy items into destination group’s folder (if needed)”引用类型为“Relative to Project”然后点击增加。 如果一切顺利所有的文件应该都在你的工程里了。是时候制作我们的地图了 使用Tile来制作地图 cocos2d支持使用开源的Tile地图编辑器创建的TMX格式的地图。 作者给出的网址现在打不开了这是我在另一个地方找到的。我把它放到我的网盘里了并且做了一个链接。如果有人下载不了请留言。这个tile地图编辑器是java版的其实还有一个at版的但是java版的功能强大一些。但是大家请注意作者使用的是qt版本的所以界面会有一些不一致但这并不影响程序的使用。 下载完之后直接双击运行。点击File\New然后会出现以下对话框 在 orientation部分你可以选择Orthogonal参考 Legend of Zelda或者Isometric参考 Disgaea。我们这里将选择Orthogonal。 接下来设置地图的大小。记住这个大小是以tile为单位的而不是以像素为单位。我们将创建一个尽量小的地图因此选择×. 最后你指定每个tile的宽度和高度。你这里选择的宽度和高度要根据你的实际的tile图片的尺寸来做。这个教程使用的样例tile的尺寸是×所以在上面的选项中选择×. 接下来我们把制作地图所需要的tile集合导入进来。点击菜单栏上面的“TileSets”菜单“New Tileset...”然后会出现下面的窗口 为了获得图片点击Browse按钮然后定位到你的TestGame文件夹选择 tmw_desert_spacing.png文件然后加到工程中去。它会基于文件名自动填充Name。然后把TileSet name命名为“tmw_desert_spacing.png”.同时设置下面的Tile spacing和Margin都为1. 你可以保留宽度和高度为×因为tile的实际大小也是这么多。至于margin和spacing我还没找到任何好的文档解释如何设置这两个值下面是我的个人看法 Margin就是当前的tile计算自身的像素的时候它需要减去多少个像素宽度和高度都包含在内。类比word、css的marginSpacing 就是相邻两个tile之间的间隔同时考虑宽度和高度类比word、css的spacing 如果你看看 tmw_desert_spacing.png你将会看见每一个tile都有一个像素的空白边界围绕着这意味着我们需要把margin和spacing设置为. 一旦你选择ok你将会看到Tilesets窗口中显示了一些tiles。现在你可以制作地图了点击工具栏上的“Stamp”按钮。点击Tile palette中的tile map然后选择一个tile然后再在地图上的任意位置单击你就会看到你选中的tile出现在点中的地方了。 因此继续制作地图吧---充分发挥你的聪明才智确保增加至少一对建筑物在地图上因为后面我们需要一些东西来做碰撞。 记住一些方便的快捷方式 你可以在Tileset拾取器中拖出一个方框一次选取多个tile。你可以使用工具栏上的paint按钮来基于一个基准tile绘制整个地图。你可以使用“View\Zoom In...”和“View\Zoom out...”来放大和缩小地图。 一旦你完成了地图的绘制工作在Layers选项卡的层上面双击现在可以说是“Layer”然后重命名为“Background”。然后点击“File\Save”并且保存文件到你的工程的资源文件夹中并且命名为“TileMap.tmx”。 后面我们将会使用这个tmx来做一些有趣的事情好了让我们把地图加载到游戏中去吧 把tile地图添加到cocos2d的场景中 首先第一件事情右键点击Resources选择“ Add\Existing Files…”然后添加TileMap.tmx文件。 打开HelloWorldScene.h然后添加一些成员变量并且申明一声属性 // Inside the HelloWorld class declarationCCTMXTiledMap *_tileMap;CCTMXLayer *_background;// After the class declarationproperty (nonatomic, retain) CCTMXTiledMap *tileMap;property (nonatomic, retain) CCTMXLayer *background; 然后在HelloWorldScene.m文件中做如下修改 // Right after the implementation sectionsynthesize tileMap _tileMap;synthesize background _background;// In deallocself.tileMap nil;self.background nil;// Replace the init method with the following-(id) init{if( (self[super init] )) {self.tileMap [CCTMXTiledMap tiledMapWithTMXFile:TileMap.tmx];self.background [_tileMap layerNamed:Background];[self addChild:_tileMap z:-1];}return self;} 这里我们调用CCTMXTiledMap类的一些方法把我们刚刚创建的地图文件加载进去。 一些简明的CCTMXTiledMap的背景知识。它是一个CCNode你可以设置它的位置和比例等。这个地图的孩子是一些层而且提供了一个帮助函数可以让你通过层的名字得到层对象--我们上面就是通过这种方面获得地图背景的。每一个层都是一个CCSpriteSheet的子类这里考虑了性能的原因--但是这也意味着每一个层只能有一个tile集。 因此我们这里做的所有这些就是指向一个tile地图然后保存背景层的引用并且把tile地图加到HelloWorld层中。 好了就这么多编译并运行工程你将会看到地图的左下角出现在模拟器中。 还不错但是这还不是一个游戏我们还需要三个东西a游戏主角b主角初使位置和c能够移动视图这样就好像是第一视角了。 好了接下来让我们来解决这些问题。 tiled对象层和设置tile地图位置 tiled支持两类层--tile层就是我们目前使用的层还有对象层。 对象层允许你在地图上圈出一些区域来指定一些事件的发生。比如你可能想制作一个区域在那里怪物将会跳出来或者是一个区域只要进入就会死掉。这我们这个例子中我们将创建一个区域来显示我们的游戏主角。 因此找到Tiled的菜单点击” Layer\Add Object Group…”命名为“Objects”然后选择Ok。如果你绘制了地图你将会注意到它并没有绘制一个tile而是画了一个很难看的灰色矩形这个矩形我们之后可以扩展使之能够包含多个tiles或者移动它。 我们只想要选择一个tile来让主角显示。因此在你的地图上选择一个tile。这个区域的大小实际上并没有关系因为我们仅仅使用x、y坐标。 然后上面的黄色对象上面点右键 取名为“SpawnPoint然后选择Ok 添加对象方法很简单看到左边的号和-号了吗一个是增加对象一个是删除对象。点中加号以后用鼠标可以拖出一个矩阵区域。 下面给出一些技巧。如何把一个对象准确放置到Background的空白区域只需要调整背景的opacity就可以了 假设你可以做一些奇思妙想。你把对象的类型命名为cocos2d里面的class的名字然后它会为你创建那个类型比如CCSprite但是我在cocos2d自带的源代码里面代不到这样的例子。更新来自GeekAndDad.com的Tyler提供了之前版本的cocos2d里面使用这种“妙想”的方法但是由于背景有白色所以被移除了。 不管怎么说--我们仅仅把这个类型设置为空就行了最后cocosd会为我们创建NSMutableDictionary我们可以从中获得对象的各种属性包含xy坐标。 保存地图然后返回XCode。在HelloWorldScene.h中做如下修改 // Inside the HelloWorld class declarationCCSprite *_player;// After the class declarationproperty (nonatomic, retain) CCSprite *player; 同样修改HelloWorldScene.m代码如下 // Right after the implementation sectionsynthesize player _player;// In deallocself.player nil;// Inside the init method, after setting self.backgroundCCTMXObjectGroup *objects [_tileMap objectGroupNamed:Objects];NSAssert(objects ! nil, Objects object group not found);NSMutableDictionary *spawnPoint [objects objectNamed:SpawnPoint]; NSAssert(spawnPoint ! nil, SpawnPoint object not found);int x [[spawnPoint valueForKey:x] intValue];int y [[spawnPoint valueForKey:y] intValue];self.player [CCSprite spriteWithFile:Player.png];_player.position ccp(x, y);[self addChild:_player]; [self setViewpointCenter:_player.position]; 好了让我们先歇会儿来解释一下对象层和对象组。首先注意你通过CCTMXTiledMap对象的objectGroupNamed方法来获得对象层而不是layerNamed方法。它返回一个特殊的CCTMXObjectGroup对象。 我们然后调用CCTMXObjectGroup类的objectNamed方法来获得一个NSMutableDictionary这个字典包含了关于对象的大量信息包括x和y坐标值宽度和高度。在这个例子中我们只关心x和y坐标因此我们提取出这两个信息并且设置player的位置。 最后我想设置这个视图为玩家所在的位置。因此添加下面一个新方法到文件中 -(void)setViewpointCenter:(CGPoint) position {CGSize winSize [[CCDirector sharedDirector] winSize];int x MAX(position.x, winSize.width /2);int y MAX(position.y, winSize.height /2);x MIN(x, (_tileMap.mapSize.width * _tileMap.tileSize.width) - winSize.width /2);y MIN(y, (_tileMap.mapSize.height * _tileMap.tileSize.height) - winSize.height/2);CGPoint actualPosition ccp(x, y);CGPoint centerOfView ccp(winSize.width/2, winSize.height/2);CGPoint viewPoint ccpSub(centerOfView, actualPosition);self.position viewPoint;} 好了让我解释一下。假设这个函数是设置camera的中心。我们允许用户传入地图上任何x、y坐标值--但是如果你仔细想一下有些东西我们并不想让它显示出来--比如我们不想让屏幕超过地图的边界那些区域仅仅是一个空白区域 比如看看下面这幅图 看一下什么时候camera的中心会小于winSize.width/2或者winSize.height/2部分视图将会在屏幕之外类似的我们需要检查上面的界限区间也和我们这里的情形一样。 因此我们把这个函数看作是设置camera的视角中心点。然而。。。那不完全是我们想要的。在cocos2d里面有一种方式可以直接操作一个CCNode的camera但是那会使事情变得更复杂。我们需要另一种替代方法那就是移动整个层。 看看下面的图 想像一个大的地图我们查看从到winSize.height/width的坐标。我们的视图的中心点是centerOfView而且我们知道我们要把这个中心设置到哪里actualPositon。因此为了使实际的位置和视图中心相吻合我们只需要把地图往左下角移动即可 这个可以通过使实际的位置减去视图的中心位置来实现然后设置HelloWorld层到那个点。 唉太多理论了--让我们看点实际的吧编译并运行项目如果一切顺利你将会看到忍者在场景当中然而视角也移过来了。 使忍者移动 我们已经有一个好的开端了但是我们的忍者只是站在那儿不动这可不像真正的忍者 让我们使忍者动起来吧只需要让忍者移动到用户点击的地方就行了。在HelloWorldScene.m中增加以下代码 // Inside init methodself.isTouchEnabled YES;-(void) registerWithTouchDispatcher{[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];}-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{return YES;}-(void)setPlayerPosition:(CGPoint)position {_player.position position;}-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{CGPoint touchLocation [touch locationInView: [touch view]]; touchLocation [[CCDirector sharedDirector] convertToGL: touchLocation];touchLocation [self convertToNodeSpace:touchLocation];CGPoint playerPos _player.position;CGPoint diff ccpSub(touchLocation, playerPos);if (abs(diff.x) abs(diff.y)) {if (diff.x 0) {playerPos.x _tileMap.tileSize.width;} else {playerPos.x - _tileMap.tileSize.width; } } else {if (diff.y 0) {playerPos.y _tileMap.tileSize.height;} else {playerPos.y - _tileMap.tileSize.height;}}if (playerPos.x (_tileMap.mapSize.width * _tileMap.tileSize.width) playerPos.y (_tileMap.mapSize.height * _tileMap.tileSize.height) playerPos.y 0playerPos.x 0 ) {[self setPlayerPosition:playerPos];}[self setViewpointCenter:_player.position];} 首先在init方法中设置层能够接收touch事件。如果我们覆盖registerWithTouchDispatcher方法来使这个层能够处理目标touch事件。这样会导致ccTouchBegan和ccTouchEnded方法被调用注意是单数形式而不是复数形式的ccTouchesBegan和ccTouchesEnded方法 你可能会问为什么我要讲这个因为我们在 《如何使用cocos2d来制作简单的iphone游戏》里面使用的是ccTouchesBegan和ccTouchesEnded方法。那两个方法可以在这个教程里用两种方法都可以。但是我想向大家介绍一个新方法因为它有两个优点 “你不需要处理NSSet划分UITouch集合并调度的工作全部由cocos2d框架来完成。每一次方法调用你只获得了一个UITouch。““你可以在ccTouchBegan中返回yes这样当前的层就可以接收touch事件回调。而且只有当你返回yes的时候才会响应move/ended/cancelled回调. 这个就使你从一些复杂的多触摸判断中解放出来了。 不管怎么说在我们的ccTouchEnded里面我们转换屏幕touch坐标为局部view坐标然后再转换成GL的坐标。这两个步骤在新的cocos2d版本中只需要一步完成即调用 [self convertToNodeSpace:touchLocation].就可以了。 这是因为touch位置只是告诉我们屏幕视口的坐标比如。但是我们我们滚动了地图这个位置实际可能对应地图的。因此调用这个方法基于我们当前层的位置来决定touch的偏移。 接下来计算出touch点和player的位置之差。我们必须基于touch位置选择一个方向因此首先我们需要计算出是上下移动还是左右移动。然后我们比较正负值决定具体的方向。 相应的我们再调整player的位置并且设置player的位置为视口的中心位置这个在上一节中已经用到了。 更新注意我们不得不添加一个安全检查来确保我们的player不会移到地图之外这一点是GeekDad指出来的谢谢你 编译并运行你现在可以点击鼠标想让尽者移到哪它就移到哪儿 何去何从 这只是这个教程的一部分。此时你应该了解一些创建tile地图的基础了而且知道如何把它导入到游戏当中。 这里有我们目前为止用的完整源代码。 接下期待第二部分教程吧在那里我将教大家如何在地图中添加碰撞检测如果使我们的忍者沿着墙壁快乐的奔跑 著作权声明本文由http://www.cnblogs.com/andyque翻译欢迎转载分享。请尊重作者劳动转载时保留该声明和作者博客链接谢谢转载于:https://www.cnblogs.com/zilongshanren/archive/2011/04/11/2012852.html