[转载] 在Tiled Map中使用碰撞检测

2014年11月17日 01:46:51 阅读数:6721更多

个人分类: cocos2dx

网上这篇教程的转载非常泛滥,本来以为没什么参考价值。但是当我实际用上 tiledmap 做点东西时,发现TiledMap软件本身,以及TMXTiledMap类的使用确实存在一些疑惑。所以,对于想真正使用 tiledmap 软件做地图的童鞋来说,这篇文章还是值得仔细看一遍的。文章里用的是 cocos2d 引擎,还是 objc 代码, 但是在cocos2dx 3.0 里依然适用.在此转载,以作备忘。

转载声明         本文转载于 冥冥之中 的163博客,地址:http://blog.163.com/fengyi1103@126/blog/static/138356274201081741324532/
         感谢 毛叔 网友 翻译。

        在这篇教程里,我们会讲解如何使用cocos2d和Tiled Map Editor创建一个基于tiled map的游戏.作为例子,我们会制作一个小游戏.游戏的主要内容是一个忍者在沙漠里寻找可口的西瓜吃.
        这篇教程主要学习的内容有:

  1. 如何创建Tiled Map。
  2. 如何将地图载入到游戏内。
  3. 如何让地图跟随玩家滚动;如何使用对象层。
  4. 如何在地图里创建可碰撞(不可穿越)区域。
  5. 如何使用tile属性。
  6. 如何使用可碰撞物体和动态修改地图。
  7. 如何确定你的主角没有产生穿越

如果你是个iphone开发新手,作为基础知识的准备,我建议你先阅读一下How To Make A Simple iPhone Game with Cocos2D Tutorial Series.

创建游戏骨架
      下面我们要创建游戏骨架.并且准备好需要的资源文件,打开XCode,File\New Project,选择cocos2d Application创建一个新工程。
      接下来,下载这个zip文件,这里面包含了游戏需要的资源:

  • 主角精灵
  • 一些游戏音效(使用cxfr工具制作)
  • 游戏背景音(使用Garage Band制作,详细信息)
  • 用于构造tiled map的元件
  • 一些特殊的元件,后面会详细解释

将下载到的资源解包拖入xcode的resources组,记得选中”Copy items into destination group’s folder(if needed)”。
       这样,一切准备就绪.

创建游戏地图
       Cocos2d支持使用开源软件Tiled Map Editor(貌似被伟大的墙挡住了,天朝的用户可以直接访问它在sourceforge的项目主页,杯具!)创建的TMX格式地图.如果你访问上面的链接,你会发现有两个版本可用.
一个使用Qt应用程序框架编写,另一个使用Java编写.这是因为最初Tiled MapEditor使用Java编写,后来移植到Qt框架上.使用哪个版本都可以.在这篇教程里,我们以使用Qt版本的为例,因为它将作为今后的开发主线.
有些人喜欢使用java版本,是因为还有些老版本上的功能尚未移植到Qt框架上.

运行Tiled Map Editor,新建一个地图.填写如下对话框:

在orientation选项内,可以选择Orthogonal(平面直角)或Isometric(45度视角,传说中的2.5D),这里选择Orthogonal.
       接下来需要设置地图大小.这里的数值是指有多少格tiled元件,并不是像素.选择50×50即可.
       最后,确定tile元件的大小.根据美工提供的元件大小设置.这个教成立,我们使用32×32的大小.接下来,将tile元件添加到地图内绘制地图.在Map菜单许做呢New Tileset,填写下面的对话框:
       
       点击Browser从电脑里找到tmw_desert_spacing.png文件(下载的资源包内)
      保持长宽数据为32×32.
      对于margin和spacing,我没有找到文档说明,但是我认为它们的意义是:

  • Margin 表示当前tiled在开始搜索实际像素时应该忽略多少个像素 (译者注:我理解应该是两个tiled元件之间的间距)
  • Spacing 表示读取下一个tiled数据后应该向前推进多少个像素(译者注:我理解应该是两个tiled元件之间的空隙,不过,这好像与Margin重复了…)

如果你仔细观察tmw_desert_spacing.png,你会发现每个tiled元件之间都有1像素的黑边.这样的图片需要将margin和spacing设置为1
        

点击OK,tiled元件将被显示在Tilesets窗口内.现在你可以开始绘制地图了.点击工具条上的Stamp(印章)图标,选择一个tiled元件,在地图内需要的位置点击放置地图元件.
         

按上面的方法绘制一张地图. 至少在地图上绘制几个建筑,因为后面我们要用到它们.
         

一些快速技巧最好记住:

  • 你可以一次添加多个tiled元件到地图里.(画一个方块选中多个tiled元件).
  • 可以使用油漆筒按钮填充地图背景.
  • 可以在view菜单里放大缩小地图.

画好地图后,双击Layers窗口里的层(一般是取名为Layer1),改名为Background.在File菜单内选择Save,将地图保存到xcode项目内,取名tiledmap.tmx

           将Tiled Map添加到Cocos2d Scene中,将刚才创建的tmx文件拖入项目resources内.打开HelloWorldLayer.h文件,添加一些代码:

#import ”cocos2d.h”

//HelloWorld Layer
@interface HelloWorld : CCLayer
{
    CCTMXTiledMap *_tileMap;
    CCTMXLayer *_background;

}
@property (nonatomic, retain) CCTMXTiledMap *tileMap;
@property (nonatomic, retain) CCTMXLayer *background;
//returns a Scene that contains the HelloWorld as the only child
+(id) scene;

@end

在HelloWorldLayer.m添加代码:

//Import the interfaces
#import ”HelloWorldScene.h”

//HelloWorld implementation
@implementation HelloWorld

//Right after the implementation section
@synthesize tileMap =_tileMap;
@synthesize background =_background;

//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];
       
    }
    returnself;
}

+(id) scene
{
    //‘scene’ is an autorelease object.
CCScene *scene =[CCScene node];
   
    //‘layer’ is an autorelease object.
HelloWorld *layer =[HelloWorld node];
   
    //add layer as a child to scene
[scene addChild: layer];
   
    //return the scene
returnscene;
}

//on “dealloc” you need to release all your retained objects
-(void) dealloc
{
    self.tileMap =nil;
    self.background =nil;
    [super dealloc];
}
@end

这里我们调用CCTMXTiledMap从map文件创建了一个地图.

关于CCTMXTiledMap的一些简要介绍

  • 它是CCNode的子类.所以我们可以设置position, scale等.
  • 这个node包含着地图的层,并且包含一些函数使你可以通过名字找到它们.
  • 为了提高性能,每一层使用的都是CCSpriteSheet的子 类. 这也意味着每个tiled元件在每一层都只有一个实例.

接下来我们要做的是利用地图和层的引用把他们添加到HelloWorld层,编译运行代码,你将能够看到地图的左下角.
          

看起来不错!不过作为一个游戏,我们还需要做三件事:

  1. 一个游戏主角;
  2. 一个放置主角的起始点;
  3. 移动视图,让我们的视角一直跟随主角.

这些才是开发这个游戏关键工作,我们一个个解决.

对象层和设置Tiled Map的位置.
       Tiled Map Editor支持两种层: tile layers(铺展层,前面我们使用过)和object layers(对象层).
       Object layers 允许你以一点为中心在地图上圈定一个区域.这个区域内可以触发一些事件.比如:你可以制作一个区域来产生怪物,或者制作一个区域进去就会死亡.在我们的例子里,我们制作一个区域作为主角的产生点.

打开TiledMapEditor,在Layer菜单选择Add Object Layer.新layer取名objects.注意,在object layer里不会绘制tiled元件,它会绘制一些灰色的圆角形状.你可以展开或者移动这些形状.
       我们是想选择一个tile元件作为主角的进入点.所以,在地图里点击一个tiled元件,产生的形状的大小无所谓,我们会使用x,y坐标来指定.
        

接下来,右键选择刚才添加的灰色形状,点击Properties.设置名字为 “SpawnPoint”

       也许你可以设置这个对象的Type为Cocos2D的类名.并且它会创建一个对象(比如CCSprite),但是我没有找到源代码里如何完成这些工作.不管它,我们保留type区域为空,它将创建一个NSMutableDictionary用来访问对象的各种参数,比如x,y坐标.保存地图回到xcode.

修改HelloWorldScene.h

//Inside the HelloWorld class declaration
CCSprite *_player;
 
//After the class declaration
@property (nonatomic, retain) CCSprite *player;

修改HelloWorldScene.m

//Right after the implementation section
@synthesize player =_player;
 
//In dealloc
self.player =nil;
 
//Inside the init method, after setting self.background
CCTMXObjectGroup *objects =[_tileMap objectGroupNamed:@”Objects”];
NSAssert(objects !=nil, @”‘Objects’ object group not found”);
NSMutableDictionary *spawnPoint =[objects objectNamed:@”SpawnPoint”];        
NSAssert(spawnPoint !=nil, @”SpawnPoint object not found”);
intx =[[spawnPoint valueForKey:@”x”] intValue];
inty =[[spawnPoint valueForKey:@”y”] intValue];
 
self.player =[CCSprite spriteWithFile:@”Player.png”];
_player.position =ccp(x, y);
[self addChild:_player];
 
[self setViewpointCenter:_player.position];

我们先花一点时间解释一下object layer和object groups.
                首先,      我们通过CCTMXTiledMap对象的objectGroupNamed方法取回object layers.这个方法返回的是一个CCTMXObjectGroup对象.
                接下来,  调用CCTMXObjectGroup对象的objectNamed方法得到包含一组重要信息的NSMutableDictionary.包括x,y坐标,宽度,高度等.
                在这里,  我们主要需要的是x,y坐标.我们取得坐标并用它们来设置主角精灵的位置.
                最后,      我们要把主角作为视觉中心来显示.现在,添加下面的代码:

-(void)setViewpointCenter:(CGPoint) position
{
    CGSize winSize =[[CCDirector sharedDirector] winSize];
 
    intx =MAX(position.x, winSize.width /2);
    inty =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;
 
}

同样做一下简要的解释.想象这个函数是把视线设置到取景中心.我们可以在地图里设置任何x,y坐标,但是有些坐标不能正确的处理显示.比如,我们不能让显示区域超出地图的边界.否则就会出现空白区.下面的图片更能说明这个问题:
        
        屏幕的宽高计算后,要与显示区域的宽高做相应的适配.我们需要检测屏幕到达地图边缘的情况.
       在cocos2d里本来有一些操控camera(可以理解为可视取景区)的方法,但是使用它可能搞得更复杂.还不如靠直接移动layer里的元素来解决更简单有效.
       继续看下面这张图:
      

把整张地图想象为一个大的世界,我们的可见区是其中的一部分.主角实际的坐标并不是世界实际的中心.但是在我们的视觉内,要把主角放在中心点,所以,我们只需要根据主角的坐标便宜,调整世界中心的相对位置就可以了.
       实现的方法是把实际中心与屏幕中心做一个差值,然后把HelloWorld Layer设置到相应的位置.好,现在编译运行,我们会看到小忍者出现在屏幕上.
       

使主角移动
       前面进行的都不错,但是到目前为止,我们的小忍者还不会动.
       接下来,我们让小忍者根据用户在屏幕上点击的位置方向来移动(点击屏幕上半部分向上移,依此类推),修改HelloWorldScene.m的代码:

//Inside init method
self.isTouchEnabled =YES;
 
-(void) registerWithTouchDispatcher
{
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
            priority:0swallowsTouches:YES];
}
 
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
    returnYES;
}
 
-(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 >=0&&
        playerPos.x >=0)
    {
            [self setPlayerPosition:playerPos];
    }
 
    [self setViewpointCenter:_player.position];
 
}

首先,我们在init方法里设置屏幕接受触摸事件.接下来,覆盖registerWithTouchDispatcher方法来注册我们自己的触摸事件句柄.
这样,ccTouchBegan/ccTouchEnded方法会在触摸发生时回调(单点触摸),并且屏蔽掉ccTouchesBegan/ccTouchesEnded方法的回调(多点触摸)

你可能奇怪,为什么不能使用ccTouchesBegan/ccTouchesEnded方法呢?是的,我们的确可以使用,但是不建议这么做,有两点原因:

  • 你不需要再处理NSSets,事件分发器会帮你处理它们,你会在每次触摸得到独立的回调.
  • 你可以在ccTouchBegan事件返回YES来告知delegate这事你想要的事件,这样你可以在move/ended/cancelled等后续的事件里方便的处理.这比起使用多点触摸要省去很多的工作.

通常,我们会将触摸的位置转换为view坐标系,然后再转换为GL坐标系.这个例子里的小变化,只是调用了一下 [self convertToNodeSpace:touchLocation].

这是因为触摸点给我们的是显示区的坐标,而我们其实已经移动过地图的位置.所以,调用这个方法来得到便宜后的坐标.

接下来,我们要搞清楚触摸点与主角位置的相对关系.然后根据向量的正负关系,决定主角的移动方向.我们相应的调节主角的位置,然后设置屏幕中心到主角上.

注意: 我们需要做一个安全检查,不要让我们的主角移出了地图. 
         
          好了,现在可以编译运行了,尝试触摸屏幕来移动一下小忍者吧.
         

这里是根据这篇教程完成的代码:猛击这里下载

接下来,我们将学习如何在地图里创建可碰撞(不可穿越)区域,如何使用tile属性,如何使用可碰撞物体和动态修改地图,如何确定你的主角没有产生穿越。

Tiled Maps和碰撞

你可能注意到了,上一篇里完成的游戏,小忍者可以穿过各种障碍。它是忍者,不是上帝!所以,我们要想办法让地图里的障碍物产生碰撞(不可穿越)。
有很多办法可以解决这个问题(包括使用对象层objects layers),但是我准备告诉你种新技术,我认为这种技术更有效,同时也是作为学习课程的好素材。使用meta layer和层属性。废话少说,我们开始吧。

用Tiled Map Editor打开之前创建的地图,点击Layer菜单的Add TileLayer取名Meta。我们会在这一层上放置一些假的Tile指示特殊的tile元件。点击Map菜单的NewTileset,选择meta_tile.png图片。将Margin和Spacing设置为1。
你会在Tilesets窗口看到meta_tiles的标签。
       

这些tiles元件其实没什么特别的,只是带有透明特性的红色和绿色方块。我们拟定红色表示“可碰撞”的(绿色的后面会用到)。选中Meta层,选择印章(stamp)工具,选择红色tile元件。把它绘制到忍者不能穿越的地方。绘制好之后,看起来应该是这样的:
       

接下来,我们要给这些Tile元件设置一些标记属性,这样在代码里我们可以确定哪些tile元件是不可穿越的。在Tilesets窗口里右键点击红色tile元件。添加一个新的属性Collidable”,设置值为true。
     
      保存地图,回到xcode。修改HelloWorldScene.h文件。

//Inside the HelloWorld class declaration
CCTMXLayer *_meta;
 
//After the class declaration
@property (nonatomic, retain) CCTMXLayer *meta;
[\cc]
修改HelloWorldScene.m文件
[cc lang=”objc”]
//Right after the implementation section
@synthesize meta =_meta;
 
//In dealloc
self.meta =nil;
 
//In init, right after loading background
self.meta =[_tileMap layerNamed:@”Meta”];
_meta.visible =NO;
 
//Add new method
-(CGPoint)tileCoordForPosition:(CGPoint)position {
    intx =position.x /_tileMap.tileSize.width;
    inty =((_tileMap.mapSize.height *_tileMap.tileSize.height) -position.y) /_tileMap.tileSize.height;
    returnccp(x, y);
}

简单的对上面的代码做一些解释。我们定义了一个CCTMXLayer对象meta作为类成员。注意,我们将这个层设置为不可见,因为它只是用来处理碰撞的。
       接下来我们编写了一个tileCoordForPosition方法,用来将x,y坐标转换为地图网格坐标。地图左上角为(0,0)右下角为(49,49)。

       上面带有坐标显示的截图来自java版本的编辑器。顺便说一声,我觉得在Qt版本里这个功能可能不再会被移植了。
        不管怎么样,用地图网格坐标要比用x,y坐标方便。得到x坐标比较方便,但是y坐标有点麻烦,因为在cocos2d里,是以左下作为原点的。也就是说,y坐标的向量与地图网格坐标是相反的。
       接下来,我们要修改一下setPlayerPosition方法。

CGPoint tileCoord =[self tileCoordForPosition:position];
inttileGid =[_meta tileGIDAt:tileCoord];
if(tileGid) {
    NSDictionary *properties =[_tileMap propertiesForGID:tileGid];
    if(properties) {
        NSString *collision =[properties valueForKey:@”Collidable”];
        if(collision &&[collision compare:@”True”] ==NSOrderedSame) {
            return;
        }
    }
}
_player.position =position;

这里,我们将主角的坐标系从x,y坐标(左下原点)系转换为tile坐标系(左上原点)。接下来,我们使用meta layer里的tileGIDAt函数获取tile坐标系里的GID。噢?什么是GID? GID应该是“全局唯一标识”(我认为).但是在这个例子里,把它作为tile层的id更贴切。

我们使用GID来查找tile层的属性,返回值是一个包含属性列表的dictionary。我们检查“Collidable”属性是否设置为ture。如果是,则说明不可以穿越。很好,编译运行工程,你再也不能走入你在tile里设置为红色的区域了。
        

动态改变Tiled Maps

现在,你的小忍者可以在地图上漫游了,不过,整个游戏还是略显沉闷。
       假设我们的小忍者非常饿,那么我们设置一些食物,让小忍者可以找到并吃掉它们。

为了实现这个想法,我们要创建一个前端层,承载所有用于触碰(吃掉)的物体。这样,我们可以在忍者吃掉它们的同时,方便的从层上删除它。并且背景层不受任何影响。

打开Tiled Map Editor,Layer菜单的Add Tile Layer。命名新层为Foreground。选中这个层,添加一些可触碰的物件。我比较喜欢用西瓜。
      

接下来,要让西瓜变为可触碰的。这次我们用绿色方块来标记。记得要在meta_tiles里做这件事。
      

同样的,给绿色方块添加属性“Collectable”设置值为 “True”.
     保存地图,回到xcode。修改代码:

//in HelloWorldScene.h:
//Inside the HelloWorld class declaration
CCTMXLayer *_foreground;
 
//After the class declaration
@property (nonatomic, retain) CCTMXLayer *foreground;
//in HelloWorldScene.m
//Right after the implementation section
@synthesize foreground =_foreground;
 
//In dealloc
self.foreground =nil;
 
//In init, right after loading background
self.foreground =[_tileMap layerNamed:@”Foreground”];
 
//Add to setPlayerPosition, right after the if clause with the return in it
NSString *collectable =[properties valueForKey:@”Collectable”];
if(collectable &&[collectable compare:@”True”] ==NSOrderedSame) {
    [_meta removeTileAt:tileCoord];
    [_foreground removeTileAt:tileCoord];
}

这里有个基本的原则,要同时删除meta layer 和the foreground layer的匹配对象。编译运行,小忍者可以吃到美味的甜西瓜了。
       

创建分数计数器
       小忍者现有吃有喝很开心,但是,我们想知道到底他吃了多少个西瓜。
       通常,我们在layer上看着顺眼的地方加个label来显示数量。但是,我们一直在移动层,这样会给我们带来很多的困扰。
       这是一个演示在一个场景里使用多个层的好例子。我们保留HelloWorld层来进行游戏,同时,增加一个HelloWorldHud层用来显示label(Hub = heads up display)。
       当然,这两个层需要一些方法来互相通讯。Hub层需要知道小忍者吃到了西瓜。有很多很多方法实现两个层之间的通信,但是我们使用尽量简单的方法来实现。我们会让HelloWorld层管理一个HelloworldHub层的引用,在忍者迟到西瓜的时候,可以调用一个方法来通知Hub层。修改代码:

//HelloWorldScene.h
//Before HelloWorld class declaration
@interface HelloWorldHud : CCLayer
{  
    CCLabel *label;
}
 
-(void)numCollectedChanged:(int)numCollected;
@end
 
//Inside HelloWorld class declaration
int_numCollected;
HelloWorldHud *_hud;
 
//After the class declaration
@property (nonatomic, assign) intnumCollected;
@property (nonatomic, retain) HelloWorldHud *hud;
//HelloWorldScene.m
//At top of file
@implementation HelloWorldHud
 
-(id) init
{
    if((self =[super init])) {
        CGSize winSize =[[CCDirector sharedDirector] winSize];
        label =[CCLabel labelWithString:@”0”dimensions:CGSizeMake(50, 20)
            alignment:UITextAlignmentRight fontName:@”Verdana-Bold”
            fontSize:18.0];
        label.color =ccc3(0,0,0);
        intmargin =10;
        label.position =ccp(winSize.width -(label.contentSize.width/2)
            -margin, label.contentSize.height/2+margin);
        [self addChild:label];
    }
    returnself;
}
 
-(void)numCollectedChanged:(int)numCollected {
    [label setString:[NSString stringWithFormat:@”%d”, numCollected]];
}
 
@end
 
//Right after the HelloWorld implementation section
@synthesize numCollected =_numCollected;
@synthesize hud =_hud;
 
//In dealloc
self.hud =nil;
 
//Add to the +(id) scene method, right before the return
HelloWorldHud *hud =[HelloWorldHud node];    
[scene addChild: hud];
 
layer.hud =hud;
 
//Add inside setPlayerPosition, in the case where a tile is collectable
self.numCollected++;
[_hud numCollectedChanged:_numCollected];

没什么稀奇的,第二个层继承CCLayer,并且在右下角添加了一个label。我们将第二个层添加到场景(Scene)里并且把hub层的引用传递给HelloWorld层。然后修改HelloWorld层调用通知计数改变的方法。
编译运行,应该可以在右下角看到吃瓜计数器了。

音效和音乐
       众所周知,没有音效和音乐的游戏,称不上是个完整的游戏。接下来,我们做一些简单的修改,让我们的游戏带有音效和背景音。

//HelloWorldScene.m
//At top of file
#import ”SimpleAudioEngine.h”
 
//At top of init for HelloWorld layer
[[SimpleAudioEngine sharedEngine] preloadEffect:@”pickup.caf”];
[[SimpleAudioEngine sharedEngine] preloadEffect:@”hit.caf”];
[[SimpleAudioEngine sharedEngine] preloadEffect:@”move.caf”];
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@”TileMap.caf”];
 
//In case for collidable tile
[[SimpleAudioEngine sharedEngine] playEffect:@”hit.caf”];
 
//In case of collectable tile
[[SimpleAudioEngine sharedEngine] playEffect:@”pickup.caf”];
 
//Right before setting player position
[[SimpleAudioEngine sharedEngine] playEffect:@”move.caf”];

接下来做点什么呢?
       通过这篇教程,你应该对coco2d有了一些基本的了解。
       这里是按照整篇教程完成的工程文件,猛击这里下载
       如果你感兴趣,我的好朋友Geek和Dad编写了一篇后续教程:Enemies and Combat: How To Make a Tile-Based Game with Cocos2D Part 3! 。这篇教程将告诉你,如何在游戏里添加敌人,武器,胜负场景等。


http://www.taodudu.cc/news/show-2814138.html

相关文章:

  • Tiled有java版本吗_【Cocos2d-X开发学习笔记】开发工具之Tiled地图编辑器的使用
  • Directx11进阶教程之Tiled Based Deffered Shading
  • Tiled结合Unity实现瓦片地图
  • Tiled 编辑地形后 输出简化
  • tiled素材_瓦片地图 Tiled Map
  • 【Cocos2d-x游戏引擎开发笔记(13)】Tiled Map Editor(一)
  • Tiled-免费2D游戏场景Tile编辑器
  • (Tiled官方文档翻译)第三节:Tile Layers的编辑
  • libGDX学习之路02:利用Tiled绘制游戏地图
  • (Tiled官方文档翻译)第四节:对象的编辑和使用
  • iphone 如何运行android,iPhone成功运行Android,厉害~
  • 解锁忘记密码的iPhone X
  • 苹果手机升级13无法开机_苹果手机更新时突然断电,手机无法开机,为什么?...
  • iOS 12 - iOS 15,如何在iPhone上设置“早上好”功能
  • oracle 访问日志ip,怎么从访问日志中把ip提取出来
  • iPhone4丢了 定位找回
  • Mac修改iPhone备份到移动硬盘或其他位置,避免备份空间不足
  • IPHONE手机知识大全(中)
  • 手把手教你iPhone 3G手机软件开发
  • iphone 11显示连接服务器出现错误,iPhone11投屏方法有哪些?iPhone投屏失败的原因及解决方法...
  • html实现iphone桌面,HTML_Html5实现iPhone开机界面示例代码,今天我突发其想,想到可以用H - phpStudy...
  • iphone无线服务器未响应,iphone8无限转圈黑屏强制关机没反应(解决死机黑屏无法开机的3种方式)...
  • 苹果app老是显示无法连接服务器失败原因,iphone无法连接到app store服务器出错怎么办...
  • Raspberry pi 通过iphone手机访问
  • 苹果8黑屏无法强制开机_iPhone黑屏转圈圈,无法开机解决方法
  • 百胜中国二次上市:肯德基与必胜客贡献九成营收,春华资本是股东
  • 肯德基历史
  • 企业招聘普遍年龄35岁以下,那全国人过40岁都干什么去了?
  • 『每日AI』马化腾丨中国互联网已从C2C进化为KFC!
  • 供货肯德基与必胜客,千味央厨上市全靠“抱大腿”?

在Tiled Map中使用碰撞检测相关推荐

  1. [转载] 在Tiled Map中使用碰撞检测

    网上这篇教程的转载非常泛滥,本来以为没什么参考价值.但是当我实际用上 tiledmap 做点东西时,发现TiledMap软件本身,以及TMXTiledMap类的使用确实存在一些疑惑.所以,对于想真正使 ...

  2. Cocos creator 导入 tiled map地图资源,cocos 显示地图错乱偏移

    1)Tiled map 中显示 (举例子随便画了一个) 2)Cocos creator显示的地图(严重错乱偏移) 3)修改过程 ①第一步: ②修改Trim type=none ③保存(正常显示了)

  3. 魔力宝贝高清单机计划(二) 地图转为tiled map

    文章目录 地图格式 tiled map格式学习 转换步骤 代码地址: https://github.com/mversace/CrossGateRemastered 地图格式 地图文件头: #prag ...

  4. 【日常点滴016】python游戏库arcade结合Tiled map editor地图编辑器和Pymunk物理引擎制作游戏过程记录,并最终打包为exe文件

    独此一家,建议收藏 前言 一.创建一个空白窗口 step001.py代码示例 二.创建很多全局能用的常量 step002.py代码示例 三.创建实例变量即代表各种精灵等的变量 step003.py代码 ...

  5. cocos2d-x 游戏 之 Tiled Map Editor(地图编辑)

    转载于:http://blog.csdn.net/zhy_cheng/article/details/8308609 Tiled Map Editor是Cocos2d-x支持的地图编辑器,使用Tile ...

  6. map中批量图层的加载和展示

    private function configopLayermaps():void {var i:int = 0;var len_configData_opLayers:int=configData. ...

  7. 【Cocos2d-x游戏引擎开发笔记(13)】Tiled Map Editor(一)

    原创文章,转载请注明出处:http://blog.csdn.net/zhy_cheng/article/details/8308609 Tiled Map Editor是Cocos2d-x支持的地图编 ...

  8. tiled素材_瓦片地图 Tiled Map

    瓦片地图(Tiled Map) 瓦片地图(Tile Map) 不但生成简单,并且可以灵活的用于Cocos2d-x引擎.不论你的游戏是角色扮演游戏, 平台动作游戏或仿打砖块游戏,这些游戏地图可以使用开源 ...

  9. html5地图编辑器,Tiled地图编辑器 Tiled Map Editor 的使用(一)基础功能+地形功能...

    看了很久关于 Tiled Map Editor 相关资料,但是网上的东西相对太少了,多日整理之后重新写一份吧 一方面是对自己学习的总结 另外也是和想入门的人做个分享. 首先是官网下载地址 http:/ ...

最新文章

  1. pytorch模型的保存与加载
  2. 宏定义#define
  3. 微信屏蔽百度红包活动页面,谁在焦虑?
  4. python api数据接口_python写数据api接口
  5. 微信公众号无限群发消息 v5.7.1 多功能版全开源 + 配置教程
  6. 【最佳实践】【Blend】Triggers、Actions 和 Behaviors
  7. 《数字图像处理与机器视觉——Visual C++与Matlab实现》——0.2 数字图像处理与识别...
  8. Algs4-2.4.5给出以下字母顺序插入大堆的结果
  9. php html转ubb,php实现转换ubb代码的方法
  10. Java时间格式转换输出实现代码示例
  11. 微pe工具箱怎么安装系统?
  12. 计算机操作常用的五大功能是,计算机操作系统的五大功能是什么
  13. RadioButton下划线效果的使用
  14. 求生之路服务器租用配置要求介绍
  15. 基于java的俄罗斯方块游戏系统设计与实现(项目报告+答辩PPT+源代码+数据库+截图+部署视频)
  16. iPhone13ProMax和华为Mate50Pro区别 哪个好
  17. qpython androidhelper gps_Qpython SL4A获取手机电量和GPS
  18. 酷狗音乐车载Android版,酷狗音乐车载版
  19. 云虚拟服务器登录,云虚拟服务器登录
  20. 键盘与ASCII码对应表

热门文章

  1. 基于小波变换的音频压缩
  2. java获取double类型区间随机数
  3. Vue3项目运行时报错,提示Use // eslint-disable-next-line to ignore the next line.
  4. DNSPod十问陈迪菲:从C到B,鹅厂设计师的中场战事
  5. JSD-2204-Session-Token-JWT-Day12
  6. 前端开发练习——包含了计时功能的动画时钟
  7. 基于BIM轻量化的智能建造OA管理系统
  8. 中国线上驾驶游戏市场深度研究分析报告
  9. 计算机书籍推荐 活着,信息朗读者 |《活着》——19级计算机实验班蔺子健
  10. mysql 部署master slave_MySQL Master Slave 数据同步,集群。