타일 기반 게임의 장점
* 메모리를 절약할 수 있다.
* 게임 세계의 효과적인 공간 분할에 따른 이점이 있다. 타일에 속성을 부여함으로써 충돌검사나 랜더링을 쉽게 할 수 있다. 캐릭터와 배경과의 상호작용을 처리하기가 쉽다.
* 그래픽 디자이너가 아닌 누구라도, 디자이너가 만들어둔 타일셋으로 맵 디자인을 할 수 있다.
타일 기반 게임의 단점
* 그래픽이 다소 지루하고 경직되어 보인다. 반복되는 타일 이미지가 많이 나타나며 유연성이 부족하다.
* 타일 이미지 제작, 관리가 힘들고 불편하다.
* 통짜맵에 비해 랜더링 알고리즘이 복잡하고 느리다.
<출처 : http://meat.tistory.com/9 >
TileMap 관련 내용
http://mamedev.org/devwiki/index.php/Tilemaps#The_problem
TileMap cocos2d-iphone 레퍼런스
http://www.cocos2d-iphone.org/wiki/doku.php/ko:prog_guide:tiled_maps
타일맵 관련 정말깔끔한 최종 정리
출처:
http://cafe.daum.net/iLogic/915W/39?docid=1KHkj915W3920110612155237
타일 맵
Cocos 2D 에서는 타일 맵을 생성하는 방법이 2 가지다.
- TMX 타일 맵 형식 사용 (새로 나와서 다루기 쉬움, 추천)
- PGU 타일 맵 형식 사용 (예전 것, 비추)
TMX 타일 맵 형식
Cocos 2D 는 타일로 생성된 맵을 제공한다.
Tiled
의 2 가지 버전:
- Mac OS X, 윈도우, 리눅스에서 실행되는 자바 어플은 안정화된 버전이다.
- 자바 버전의 모든 특징을 제공하는 QT 어플. 이 강좌를 작성하는 시점의 최근 버전은 0.4.0 이며 육각형 맵만 제외하고 모든 기능을 제공한다.
다음 링크된 페이지에서는 Tiled
를 사용하여 맵을 만드는 방법을 설명한다.
Cocos 2D 는 다음과 같은 TMX 맵을 제공한다.
- 위치:
- 지각 맵
- 등각 맵
- 육각 맵
- 타일:
- 연결된 타일은 제공되지 않는다. (즉, 연결된 이미지를 갖는 tileset).
embedded
tileset 만 제공된다. (즉, tileset 은 연결되었지만 이미지는 아닌 것).- 레이어 별로 최대 1 개의 tileset 만 제공된다.
- 레이어:
- 레이어는 원하는 만큼 만들 수 있다.
- 각 레이어는 내부적으로
CCSpriteSheet
의 자식 클래스인CCTMXLayer
으로 표현된다. - 각 타일은
CCTMXLayer
의 자식 클래스인CCSprite
으로 표현된다.
- 객체 그룹:
- 타일의 객체 그룹이 제공된다.
외부 이미지에서 연결된 tileset 생성하는 방법
Cocos 2D 는 tileset 에 연결된 이미지를 제공하지 않는다. 그러나, tileset 자체는 맵 파밀에서 연결된 그림이 되어야 한다. 대신, 자체적으로 sprite sheet
이미지(AKA: Texture Atlas)를 생성해야 한다.
Tiled 정보 설정
연결된 이미지를 갖는 tileset 으로 저장되지 않도록 tiled
에 설정한다.
$ cd bin/tiled-0.7.2/ $ java -jar tiled
tiled 에서 해야할 작업:
- Edit → Preferences → Saving
- Layer 옵션:
- Use binary encoding: ON (“텍스트” 엔코딩은 Cocos 2D 에서 제공되지 않는다)
- Compress layer data: ON (압축되지 않은 데이터도 또한 제공된다)
- Tileset 옵션:
- Embed images (PNG): OFF (연결 이미지는 제공되지 않는다)
새로운 맵을 생성할 때 맵의 크기는 맵의 픽셀 단위의 크기가 아닌 가로 세로의 tile 의 개수를 넣어야 한다. iPhone 에서 제공할 수 있는 맵의 크기는 제한된다. 작동할 때 44 픽셀 x 44 픽셀은 100 x 100 으로 보여진다. 400 x 200 의 타일은 모두 검정색으로 그려진다.
tileset 연결된 것 확인하기
맵용 tileset 은 맵 파일 내에 포함되어야 한다. tiled 에서는 Tileset → Tileset Manager 로 접근할 수 있는 "Tileset Manager"로 조절된다. tileset 목록에서 tileset 이름의 오른쪽 행에 Embedded 를 볼 수 있다. 대신에 경로가 보인다면, 목록에서 열을 선택하고 embedded tileset 으로 변환하는 오른쪽의 Embed 아이콘을 선택해야 한다.
다른 도구를 사용하거나 확인해보려면 텍스트나 XML 편집기에서 *.tmx 파일을 열고 <tileset>
노드를 확인해볼 수 있다. 파일 명을 갖는 source
속성을 포함하면 Cocos 2D iPhone 에서 동작하지 않는 외부 tileset 을 보고 있는 것이다.
sprite sheet 생성
유용한 이미지를 묶어주는 도구들이 있다.
- zwoptex 비주얼 텍스처 아트라스 생성기 (flash)
- mkatlas.pl 도스 실행형 텍스처 아트라스 생성기 (perl)
- Packer 비주얼 텍스처 아트라스 생성기 (java)
- TexturePacker 강력한 명령행 도구, XCode-통합용
이 도구들은 개별 이미지로부터 sprite sheets
를 생성하도록 도와준다.
sprite sheet 의 제한:
- 최대 크기: iPhone 3GS 에서는 2048×2048 이고 이전 iPhone 에서는 1024×1024
- 타일은 모두 같은 크기여야 한다.
옵션:
- 여백: 픽셀 단위의 공백
- 간격: 타일 간의 공백
여백과 간격은 2 를 사용하는 것이 추천된다.
spritesheet artifact fixer
맵을 이동할 때 타일의 경계 사이의 선이 깜빡이는 경험이 있다면, 이 도구는 고쳐야 한다. 이들 선은 시뮬레이터에서는 나타나지 않고 장치에서 실행할 때만 나타난다.
spritesheet-artifact-fixer
는 spritesheet 를 고치는 Cocos 2D 에 있는 작은 도구이다.
실제로 해야할 일은 타일의 경계선을 여백 안으로 복사하는 것이다. 이론적으로는 여백은 렌더링되지 않아야 하지만, 때때로 렌더링된다. 특히, 안티-앨리어싱 텍스처나 3D 투영을 사용한 것이라면 더 그렇다.
도구를 사용하는 방법:
$ cd cocos2d/tools $ python spritesheet-artifact-fixer.py -f spritesheet.png -x 32 -y 32 -m 2 -s 2
다른 도구는 –extrude
옵션으로 TexturePacker 을 사용하는 것이다.
$ TexturePacker *.png --extrude 1 --plist test.plist --sheet test.png
좌표와 GID
좌표
GID
타이틀의 GID 는 타이틀의 전역적으로 구별하는 식별 기호이다. 이 값은 unsigned int
형이며 1 부터 타일의 개수까지 차례대로 번호가 부여된다.
5 개의 다른 타일이 있다면
- Tile 0 은 GID 1
- Tile 1 은 GID 2
- Tile 2 은 GID 3
- 등등.
GID 0 은 빈 타일을 표현하는 데 사용된다.
TMX 노드 생성
CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"hexa-test.tmx"]; [self addChild:map];
디폴트로 모든 타일은 앨리아싱된다. 안티-앨리어싱 타일을 원하면 다음과 같이 작업해야 한다.
// TMX 맵 생성 CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"]; [self addChild:map]; // 모든 레이어를 반복하면서 'antialias' 로 설정한다 for( CCTMXLayer* child in [map children] ) { [[child texture] setAntiAliasTexParameters]; }
완전한 소스:
타일 얻기/추가/삭제/수정
특정 좌표에서 타일(CCSprite) 얻기
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);
특정 좌표에서 타일의 GID 얻기
CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"]; CCTMXLayer *layer = [map layerNamed:@"Layer 0"]; unsigned int gid = [layer tileGIDAt:ccp(0,63)];
특정 좌표에 새로운 타일의 GID 설정하기
CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"]; CCTMXLayer *layer = [map layerNamed:@"Layer 0"]; [layer setTileGID:gid2 at:ccp(3,y)];
특정 좌표에 타일 제거하기
CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"]; CCTMXLayer *layer = [map layerNamed:@"Layer 0"]; [layer removeTileAt:ccp(15,15)];
레이어 반복
CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal-test2.tmx"]; CCTMXLayer *layer = [map layerNamed:@"Layer 0"]; CGSize s = [layer layerSize]; for( int x=0; x
z 오더와 깊이 버퍼
이 정보는 v0.99.1 이후 버전부터 유효하며, Isometric 과 orthogonal 맵 에서는 가능하며 hexagonal 맵에서는 불가능하다.
만들고자 하는 게임이 sprite 의 Y 위치를 따라서 어떤 타일의 앞쪽이나 뒤로 sprite 를 위치시켜야할 때, 2 가지 옵션을 사용할 수 있다.
- OpenGL ES 깊이 버퍼 사용
- 멀티 TMX 레이어와 z-오더 사용
깊이 버퍼 사용
이 옵션은 OpenGL ES 깊이 버퍼를 사용한다. 그래서, 우선 적으로 해야할 작업은 z-버퍼와 2D 프로젝션을 생성하는 것이다.
// 직접적으로 윈도우 뷰에 붙기 전에 AppDelegate 에서 작성한다. // kDepthBuffer24 로 24 비트 버퍼를 사용할 수도 있다. [[CCDirector sharedDirector] setDepthBufferFormat:kDepthBuffer16]; // 이 코드는 아무 곳이나 원하는 위치에 넣을 수 있다. 실행 중에 프로젝션 방법을 바꿀 수 있다. [[CCDirector sharedDirector] setProjection:CCDirectorProjection2D];
2 TMX 레이어로 맵을 생성하는 것이 중요하다.
- 배경 레이어. 예: grass
- 전경 레이어. 예: trees
grass 레이어는 뒤쪽의 스프라이트가 되어, vertexZ 값이 가능한 가장 작은 값이 될 것이다. 예: -1000. trees 레이어는 타일들마다 다른 vertexZ 값들을 갖는다. 아래 쪽에 있는 타일은 위에 있는 타일보다 더 큰 vertexZ 값을 갖는다.
그래서, 해당 작업은 다음과 같다:
- Tiled 열기
- 배경 레이어 선택 (예: grass)
- Tiled → Layer → Layer Properties
- 추가: cc_vertex = -1000
- 전경 레이어 선택 (예: trees)
- Tiled → Layer → Layer Properties
- 추가: cc_vertexz = automatic
가장 중요한 작업은 스프라이트를 GL_ALPHA_TEST
가 가능한 상태로 드로잉하는 것이다. 예제:
// MySprite 는 CCSprite 를 상속받은 클래스이다. // CCSpriteSheet 를 사용하여 스프라이트를 드로잉한다면, CCSprite 가 아니라 CCSpriteSheet 를 상속받아야 한다. // 전역적으로 GL_ALPHA_TEST 를 설정할 수 있다. 설정하면, CCTMXLayer#draw 함수를 주석처리해야 한다. // 다른 방법은 아래 예제와 같다. @implementation MySprite -(void) draw { glEnable(GL_ALPHA_TEST); glAlphaFunc( GL_GREATER, 0 ); [super draw]; glDisable(GL_ALPHA_TEST); } @end
Q: cc_vertexz 의 작업 방식은 ?
A: cc_vertexz 는 자동으로 word 형식이나 정수를 받게 된다.
- 값이 음수나 양수인 정수라면, 숫자는 레이어의 모든 타일의 vertexZ 로 사용될 것이다.
- 값이 자동이라면, 타일의 첫 번째 열은 vertexZ 는 -1 이 되고, 두 번째 열은 vertexZ 가 -2 등을 자동으로 할당된다.
남은 작업은 Y 위치에 따라서 스프라이트의 vertexZ 값을 변경하는 것이다. 예제:
-(void) repositionSprite:(ccTime)dt { // 타일 높이는 101x81 CGPoint p = [sprite position]; [sprite setVertexZ: -( (p.y+81) /81) ]; }
샘플의 작동은 TileMapTest.m 를 참고해라.
Q: cc_alpha_func 는 언제 사용해야 하나?
A: cc_alpha_func
는 cc_vertexz=automatic
일 때 사용된다. 디폴트 값은 0 이다. 이 값은 GL_GREATER 함수를 사용하여 타일을 그릴 때 사용된다. 다음은 CCTMXLayer
로 타일을 그리는 방법이다.
// CCTMXLayer 드로잉 함수 -(void) draw { if (useAutomaticVertexZ_) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, alphaFuncValue_); } [super draw]; if (useAutomaticVertexZ_) glDisable(GL_ALPHA_TEST); }
예제:
다중 TMX 레이어와 z-오더 사용법
이 정보는 아직 가능하지 않다. 그러나 예제는 TileMapTest.m 에서 볼 수 있다.
스크린 샷
PGU 타일 맵 형식
PGU 타일 맵 형식도 사용할 수 있다.
이 형식은 크기 제한을 가지므로 유연하지 않고, 편집기 자체에도 약간의 버그를 갖기 때문에, 이 형식은 잘 다뤄지지 않는다. 예전 게임에 이 형식을 사용했다면 계속적으로 사용할 수 있지만, 추천되지 않는 형식이다. 대신 TMX 타일 맵이 추천된다.
이 형식에 대한 정보는 다음과 같다.