Dieses Dokuwiki verwendet ein von Anymorphic Webdesign erstelltes Thema.

Tiled Maps

There are 2 ways of creating tiled maps in cocos2d.

  • by using the TMX Tile Map format (newer, more flexible, recommended)
  • by using the PGU Tile Map format (older, deprecated)

TMX Tile Map format

cocos2d supports maps created with Tiled.

Tiled has 2 versions:

  • A java application that runs on Mac OS X, Windows and Linux, which is the stable version
  • A QT (native) application that supports almost all the features of the java version. As of this writing, the latest QT version is 0.4.0 and supports everything but hexagonal maps

This page explains how to create a map using Tiled:

cocos2d supports the following TMX maps:

  • Orientation:
    • Orthogonal maps
    • Isometric maps
    • Hexagonal maps (edges on left-right. edges at top-bottom are not supported… it seems that Tiled doesn't support them either)
  • Tiles:
    • Embedded tiles are NOT supported (i.e., tilesets with embedded images).
    • Only embedded tilesets are supported (i.e., the tileset is embedded, but not its images).
    • supports at most 1 tileset per layer.
  • Layers:
    • You can have as many layers are you want
    • Each layer will be represented internally by a CCTMXLayer (which is a subclass of CCSpriteSheet)
    • Each tile will be represented by an CCSprite (its parent will be the CCTMXLayer)
  • Object Groups:
    • Tiled objectGroups are supported as well

How to create embedded tilesets with external images

cocos2d doesn't support embedded images in tilesets (but requires tilesets themselves to be embedded in the map file). Instead you should create a sprite sheet image (AKA: Texture Atlas) by yourself.

Setting the Tiled preferences

Tell tiled to NOT save the tileset with embedded images:

$ cd bin/tiled-0.7.2/
$ java -jar tiled

Once in tiled, you should do:

  • Edit → Preferences → Saving
  • Layer Options:
    • Use binary encoding: ON (“text” encoding is not supported by cocos2d)
    • Compress layer data: ON (non-compressed data is also supported)
  • Tileset Options:
    • Embed images (PNG): OFF (Embedding images is not supported)

Tiled Preferences

Note that when creating a new map, Map Size refers to the number of tiles vertically and horizontally, and not the pixel dimensions of your map. Note that there are limits to the size map the iPhone will support (user comment: we have seen 100 x 100 at 44px by 44px as working, but 400 x 200 not work - the tiles are all drawn black)

Making sure a tileset is embedded

The tilesets for your map must be embedded into the map file. In Tiled this is controlled in the “Tileset Manager” (accessed via: Tilesets → Tileset Manager ). You should see ”(Embedded)” in the column to the right of the tileset name in the list of tilesets. If you instead see a path string, you need to select that row in the list and then select the Embed icon to the right which will convert it to an embedded tileset.

If you are using a different tool or want to confirm for yourself you can open the *.tmx file in a text or XML editor and check the <tileset> node. If it contains a source property with a file name you are looking at an external tileset which will not work with cocos2d-iphone.

Creating sprite sheets

There are some image packers that might be useful:

  • mkatlas.pl a command line texture atlas creator (shipped with cocos2d) (free)
  • Packer a visual texture atlas creator (free)
  • Image Magic A command line utility (free)
  • zwoptex a visual texture atlas creator (free & commercial)
  • TexturePacker Graphical Userinterface + Command line (free & commercial)

These tools let you create sprite sheets from individual images.

Limitations of the sprite sheet:

  • Max size: 2048×2048 on iPhone 3GS and 1024×1024 on older iPhones
  • The tiles should all have the same size

Options:

  • margin: the space in pixels in the margins
  • spacing: the space in pixels between the tiles

It is recommended that you use a margin of 2, and spacing of 2

The spritesheet artifact fixer

If you experience lines flickering between the borders of your tiles when you move your map, this tool will fix that. Please note, these lines don't appear in the simulator, only on devices.

The spritesheet-artifact-fixer is a little tool that comes with cocos2d that lets you fix your spritesheet.

What it really does, is to copy the borders of your tiles, into the spacing/margin pixels. In theory the spacing/margin pixels should NOT be rendered, but in practice sometimes they are rendered, specially if you use anti-alias textures and a 3D projection.

How to use this tool:

$ cd cocos2d/tools
$ python spritesheet-artifact-fixer.py -f spritesheet.png -x 32 -y 32 -m 2 -s 2

An alternative is using TexturePacker with the –extrude feature:

$ TexturePacker *.png --extrude 1 --plist test.plist --sheet test.png

Coordinates and GIDS

Coordinates

The coordinate system used in Tiled in a 64×32 map is:

  • (0,0): top-left corner
  • (63,31): bottom-right corner

GID

A tile's GID is the tile's Global IDentifier. It is an unsigned int that goes from 1 until the quantity of tiles.

If you have 5 different tiles then:

  • Tile 0 will have GID 1
  • Tile 1 will have GID 2
  • Tile 2 will have GID 3
  • and so on.

The GID 0 is used to represent to empty tile.

How to create a TMX node

CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"hexa-test.tmx"];
[self addChild:map];

All the tiles by default will be aliased. If you want to create anti-alias tiles, you should do:

// create a TMX map
CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"];
[self addChild:map];
 
// iterate over all the "layers" (atlas sprite managers)
// and set them as 'antialias' 
for( CCTMXLayer* child in [map children] ) {
    [[child texture] setAntiAliasTexParameters];
}

Full example:

How to get/add/delete/modify a tile

To obtain a tile (CCSprite) at a certain coordinate

CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"];		
CCTMXLayer *layer = [map layerNamed:@"Layer 0"];
 
CCSprite *tile = [layer tileAt:ccp(0,63)];
tile.anchorPoint = ccp(0.5f, 0.5f);

To obtain a tile's GID at a certain coordinate

CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"];		
CCTMXLayer *layer = [map layerNamed:@"Layer 0"];
 
unsigned int gid = [layer tileGIDAt:ccp(0,63)];

To set a new tile's GID's at a certain coordinate

CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"];		
CCTMXLayer *layer = [map layerNamed:@"Layer 0"];
 
[layer setTileGID:gid2 at:ccp(3,y)];

To remove a tile at a certain coordinate

CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"];		
CCTMXLayer *layer = [map layerNamed:@"Layer 0"];
 
[layer removeTileAt:ccp(15,15)];

To iterate a Layer

CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"];		
CCTMXLayer *layer = [map layerNamed:@"Layer 0"];
 
CGSize s = [layer layerSize];
for( int x=0; x<s.width;x++) {
	for( int y=0; y< s.height; y++ ) {
		unsigned int tmpgid = [layer tileGIDAt:ccp(x,y)];
		[layer setTileGID:tmpgid+1 at:ccp(x,y)];
	}
}

z order and depth buffer

Information valid on v0.99.1 or newer

Information valid both for Isometric and Orthogonal maps. NOT valid for Hexagonal maps

If your game needs to place the sprites behind/in front of certain tiles according to the sprites' Y position (a common scenario in isometric maps, and in some orthogonal maps too), then you have 2 options:

  • Use OpenGL ES depth buffer
  • Use multiple TMX Layers and z-order

Using Depth Buffer

This option uses the OpenGL ES depth buffer. So, the 1st thing that you must do, is to create a z-buffer and a 2D projection

// Place this code in your AppDelegate, before attaching the director to the window view.
// you can use a 24-bit buffer too with: kDepthBuffer24
[[CCDirector sharedDirector] setDepthBufferFormat:kDepthBuffer16];
 
// You can place this code anywhere you want. You can change the projection in runtime
[[CCDirector sharedDirector] setProjection:CCDirectorProjection2D];

It is also very important to create a map with 2 TMX Layers

  • A background layer. eg: grass
  • A foreground layer. eg: trees

The grass layer will be behind the sprites, so its vertexZ value should be the lowest possible value. eg:-1000. The trees layer should have different vertexZ values for the tiles. Tiles that are at the bottom should have higher vertexZ than the tiles that are at the top.

So, in order to achieve this, you should do:

  1. Open Tiled
  2. Select the background Layer (eg: grass)
  3. Tiled → Layer → Layer Properties
  4. Add: cc_vertexz = -1000
  5. Select the foreground Layer (eg: trees)
  6. Tiled → Layer → Layer Properties
  7. Add: cc_vertexz = automatic

The other important thing to do is to draw your sprites with GL_ALPHA_TEST enabled. Example:

//MySprite is a subclass of CCSprite.
// If you are drawing sprites using CCSpriteSheet, then you should subclass CCSpriteSheet and not CCSprite.
// You can also enable GL_ALPHA_TEST globally, but if you do so, you need to comment the the CCTMXLayer#draw method (see CCTMXLayer.m)
// There are other alternatives. This is just an example.
@implementation MySprite
-(void) draw
{
   glEnable(GL_ALPHA_TEST);
   glAlphaFunc( GL_GREATER, 0 );
   [super draw];
   glDisable(GL_ALPHA_TEST);
}
@end

Q: How does cc_vertexz work ?

A: cc_vertexz accepts either the word automatic or an integer number

  • If the value is a integer (negative or positive), then, that number will be used as the vertexZ value for all the tiles of that layer
  • If the value is automatic then the first row of tiles will have a vertexZ value of -1, the second row will have a vertexZ value of -2, an so on.

The only thing left to do is to modify your sprites' vertexZ value according to its Y position. Example:

-(void) repositionSprite:(ccTime)dt
{
	// tile height is 101x81
	CGPoint p = [sprite position];
	[sprite setVertexZ: -( (p.y+81) /81) ];
}

Please, see TileMapTest.m for a working sample.

Q: When should I use cc_alpha_func ?

A: The cc_alpha_func value will only be used when cc_vertexz=automatic. By default it will have a value of 0. This value will be used to draw the tiles using the GL_GREATER function. This is how CCTMXLayer draws the tiles:

// CCTMXLayer drawing function
-(void) draw
{
	if( useAutomaticVertexZ_ ) {
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, alphaFuncValue_);
	}
 
	[super draw];
 
	if( useAutomaticVertexZ_ )
		glDisable(GL_ALPHA_TEST);
}

Examples:

Isometric vertex Z example. It has 2 layers: “trees” and “grass”. Uses cc_vertex=automatic for the “trees” layer. And cc_vertexz=-1000 for the “grass” layer.
 Orthogonal vertex example. It has 2 layers: “trees” and “grass”. It uses cc_vertexz=automatic and cc_alpha_func=0.5 for the “trees” layer. and cc_vertexz=-1000 for the “grass” layer.

Using multiple TMX Layers and z-order

Each layer in the map is automatically assigned it's own zOrder value, so there is no need to add any layer attributes in your TMX editor. Adding your sprite as a child of the TMXMap allows you to dynamically place it within the layers of the map object.

CCTMXTiledMap map = [CCTMXTiledMap tiledMapWithTMXFile:@"Map.tmx"];
[self addChild:map];
 
CCSprite *character = [CCSprite spriteWithFile:@"Character.png"];
// Add the sprite as a child of the map, and set the z order to
// be the same as the layer you wish the sprite to appear
// immediately above.
[map addChild:character z:[map layerNamed:@"grass"] zOrder]];

See a working example here: TileMapTest.m

Screenshots

Orthogonal map, with 3D projection and anti-aliased tiles. The tiles were “fixed” using the spritesheet-fixer tool. No artifacts appears even with a 3D projection and anti-aliased tiles
Orthogonal map. map's tile size is smaller than the tiles
Isometric map, with 2D projection and aliased tiles
Hexagonal map, with 2D projection and aliased tiles. Edges are at the left-right. Bottom-top edges are not supported (yet)

PGU Tile Map Format

You can use the PGU Tile maps, too.

Since the format is not very flexible (it has limitations with it's sizes) and the editor seems to have some bugs, this format is deprecated. You will be able to continue using it with your old game, but it's usage is not recommended.

Instead, use the recommened TMX Tile Map.

Some articles about this format:

prog_guide/tiled_maps.txt · Last modified: 2011/10/07 15:55 by cacker
Trace: tiled_maps
Dieses Dokuwiki verwendet ein von Anymorphic Webdesign erstelltes Thema.
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0