Cocos2d-html5로 Tiled Map Editor를 사용하는 방법

 

소개

Tiled Map Editor는 게임 수준과 타일맵을 만들 수 있는 유용한 도구입니다. 타일 애플리케이션은 Qt 애플리케이션 프레임워크와 함께 C++로 작성되며 무료입니다. 직사각형 타일맵뿐만 아니라 마름모형 타일맵도 만들 수 있습니다. 맵은 XML 기반 형식인 TMX 파일로 저장되므로 쉽게 읽을 수 있고 다양한 게임 엔진에서 작동됩니다.

공식 Tiled 웹 사이트:

http://www.mapeditor.org/ 

그림 1: Tiled Map Editor

TMX 맵은 다음과 같은 다양한 게임 엔진에서 이미 지원됩니다.

  • Cocos2d
  • Cocos2d-iPhone
  • Cocos2d-html5
  • AndEngine
  • melonJS
  • sprite.js
  • Unity 3D

전체 목록은 다음 주소에서 찾을 수 있습니다.

https://github.com/bjorn/tiled/wiki/Support-for-TMX-maps 

공식 웹사이트를 방문하거나 설치 가이드를 따르면 Tiled Map Editor 버전을 설치할 수 있습니다. Tiled 애플리케이션은 가장 많이 사용하는 운영 체제에서 작동해야 합니다.

  1. Windows
  2. Mac OS
  3. Linux: Ubuntu, Fedora, openSUSE, CentOS

 

TMX 맵 만들기

새로운 맵과 수준은 Tiled로 쉽게 만들 수 있습니다. 다음 자습서에서는 맵을 만들고 몇 가지 화려한 Tiled 기능을 사용하는 방법을 보여줍니다. RunSnailRun 샘플 애플리케이션에서 Tiled를 사용한 이후 생성한 애플리케이션을 예로 사용하겠습니다.

우선, Tiled를 열고 왼쪽 상단 모서리에 있는 "새로 만들기" 버튼을 누르십시오. 새로운 맵 설정 창이 표시됩니다. 

그림 2: 새로운 맵 메뉴

맵에 있어야 할 타일 개수와 타일 크기를 설정할 수 있습니다. 모든 맵 크기가 가능하지 않다는 것을 고려해야 하며 게임을 처음 작성 초반에 맵을 디자인해야 합니다. 

RunSnailRun에서 42 x 22 타일 크기의 맵을 사용했습니다. 이것은 1260 × 660픽셀입니다. 패딩과 맵 영역 바깥에 표시되는 게임 로고에 대한 일부 공간을 남기도록 디자인했습니다. 확인을 클릭한 후 새로운 타일맵을 볼 수 있습니다.

그림 3: 새로운 타일맵

이제 타일셋(이미지) 및 개체와 함께 맵을 작성해야 합니다. Cocos2d-x에서와 마찬가지로, 대부분의 그래픽 프로그램에서 레이어를 사용하여 Tiled에서 맵을 빌드합니다. 가장 좋은 방법은 모든 동일한 타일셋 또는 동일한 속성을 공유하는 모든 개체를 수집하는 레이어를 사용하는 것입니다. 예를 들어 RunSnailRun의 맵에는 배경에 대한 레이와 충돌 요소(양상추)에 대한 또 다른 레이어가 있습니다. 달팽이와 고슴도치는 다른 유형의 개체입니다.

시작 시 첫 번째 레이어에서 이미 만들어집니다. 이름은 보통 타일 레이어 1입니다. 두 번 클릭하면 이름을 변경할 수 있습니다. 예를 들어 "배경"으로 변경한 후 작성을 시작할 수 있습니다. 이를 수행하려면 일부 타일셋(이미지)을 가져와야 합니다.

  1. 맵 메뉴를 연 다음 "새로운 타일셋"을 클릭합니다. 
  2. 찾아보기를 클릭하고 추가하려는 이미지를 찾습니다.
  3. 확인을 클릭합니다.

타일셋 패널의 오른쪽에서 가져온 이미지를 확인할 수 있습니다. 이제 타일을 선택하고 맵에 배치할 수 있습니다. 

패널 상단에는 다음과 같은 많은 유용한 옵션이 있습니다.

  • 스탬프 브러시:이 옵션을 사용하면 단 하나의 타일셋이 맵에 배치됩니다.
  • 물통 채우기 도구: 이 옵션 세트를 사용하여 지정된 타일셋으로 전체 맵을 작성합니다.
  • 지우개: 선택한 타일을 지웁니다.
  • 사각형 선택: 이 옵션을 사용하여 영역을 선택하면 모든 수정이 이 영역 내부에만 적용됩니다.

배경을 만든 후 맵에 몇 가지 충돌 개체를 추가할 수도 있습니다. 그러면 플레이어가 맵 전체를 돌아다닐 수 없게 됩니다. 두 가지 방법으로 수행할 수 있습니다. 첫 번째 방법에서 충돌할 수 있는 바위, 강, 나무와 같은 모든 타일셋을 배치할 충돌 가능 레이어를 만들 수 있습니다. Cocos2d-x는 지정된 레이어에서 타일의 위치를 읽을 수 있으며 플레이어가 충돌 가능 타일로 이동하려는지 확인하고 멈출 수 있습니다.

다른 방법은 각 유형의 지형 레이어 하나를 만들어 나무 레이어, 바위 레이어 등을 배치하는 것입니다. 그런 다음 투명 타일셋으로 별도의 다른 레이어에 만듭니다. 이러한 타일 위에 투명한 타일셋을 배치하여 교차되지 않을 타일을 지정할 수 있습니다.

RunSnailRun에서 양상추는 단 하나의 충돌 개체 유형입니다. 추가 레이어가 없도록 결정한 이유입니다. "collidable"이라고 하는 하나의 수준이 생성되고 이 수준 내부에 양상추를 배치합니다. 

전에 언급했듯이, 달팽이와 고슴도치는 개체입니다. 즉 이미지로 표시되지는 않지만 위치와 요소의 일부 속성을 저장합니다. 애플리케이션에서 맵에 달팽이 개체와 고슴도치 개체를 배치한 다음 Cocos2d-x를 사용하여 두 개체의 위치를 읽고 스프라이트를 만듭니다.

Tiled에서 개체 레이어를 만들기 위해 레이어 메뉴를 열고 "개체 레이어 추가"를 클릭해야 합니다. 이제 개체 레이어에 대한 이름을 설정합니다. 이 경우에는 달팽이와 고슴도치에 대해 두 개의 개체 레이어를 생성했습니다. 개체 레이어를 만든 후에 개체를 만들 수 있습니다. 이제 다음과 같아야 합니다.

그림 4: 두 개의 타일 레이어 및 하나의 개체 레이어로 구성된 Tiled로 만든 맵

이제 맵을 저장하고 게임 폴더 내부 어딘가에 배치해야 합니다.

 

Cocos2d-x에서 TMX 맵 사용

Cocos2d-x에서 맵으로 TMX 파일을 로드할 수 있는 특별 클래스가 있습니다. 또한, 이 클래스에는 TMX 맵 속성을 다루는 데 도움이 되는 몇 가지 추가 함수가 있습니다. 단일 격자인 레이어에 액세스하고 속성을 읽을 수 있습니다. Tile 애플리케이션에서 생성된 맵을 로드하는 방법에 대한 RunSnailRun 애플리케이션의 코드 조각입니다.

classes.maps.TiledMeadow = cc.TMXTiledMap.extend({
    ctor : function() {
        this._super();
        this.initWithTMXFile("images/tiledMeadow.tmx");
    }
});
var tiledMap = new classes.maps.TiledMeadow();

 

보시다시피 TiledMeadow 클래스는 TMXTiledMap을 확장하고 생성될 때 tiledMeadow.tmx 파일을 로드합니다.

TiledMap 개체를 생성한 맵 레이어에 추가하면 타일 레이어만 표시됩니다. 달팽이와 같은 개체 레이어는 표시되지 않으며 양상추에 대한 충돌을 확인하는 메커니즘도 없습니다. 직접 수행해야 합니다. 다음은 샘플 애플리케이션에서 수행되는 방법입니다.

TMX 파일을 로드한 후 맵 속성을 읽기 위해 몇 가지 기존 함수를 사용할 수 있습니다. 예를 들어 모든 충돌 가능 타일을 읽고 반영하는 사각형을 만들 수 있습니다.

initObstacles : function() {
    this.obstacles = [];
    var mapWidth = this.getMapSize().width;
    var mapHeight = this.getMapSize().height;
    var tileWidth = this.getTileSize().width;
    var tileHeight = this.getTileSize().height;
    var collidableLayer = this.getLayer("collidable");
    var i, j;
    for (i = 0; i < mapWidth; i++){
        for (j = 0; j < mapHeight; j++){
            var tileCoord = new cc.Point(i, j);
            var gid = collidableLayer.getTileGIDAt(tileCoord);
            if(gid) {
                var tileXPositon = i * tileWidth;
                var tileYPosition = (mapHeight * tileHeight) - ((j+1) * tileHeight);
                var react = cc.rect(tileXPositon, tileYPosition, tileWidth, tileHeight);
                this.obstacles.push(react);
            }
        }
    }
}

 

Cocos2d-x를 사용하면 확인하려는 레이어 이름으로 getLayer() 함수를 호출하여 맵에서 레이어에 액세스할 수 있습니다. 또한 그리드 위치를 전달해야 할 getTileGIDAt() 함수를 사용하여 레이어 내부의 그리드에 액세스할 수 있습니다.

“충돌 가능” 타일 위치를 확인하는 앞서 언급한 함수를 사용하여 전체 맵을 통해 반복됩니다. 각 충돌 가능 타일을 찾는 후 나중에 충돌 감지를 위해 사용될 사각형을 만들었습니다.

비슷한 방법을 사용하여 모든 달팽이의 위치를 읽습니다. 코드 조각입니다.

initSnails : function() {
    if (this.tiledMap) {
        var objectGroupSnails = this.tiledMap.getObjectGroup("snails");
        var objectSnails = objectGroupSnails.getObjects();
        this.numberOfSnails = objectSnails.length;
        var that = this;
        objectSnails.forEach(function(objectSnail) {
            var snail = new classes.sprites.Snail();
            snail.setPosition(new cc.Point(objectSnail.x, objectSnail.y));
            that.snails.push(snail);
            that.addChild(snail, 1);
        });
    }
}

 

이번에 모든 달팽이를 포함한 그룹에 액세스하기 위해 getObjectGroup() 함수를 사용했습니다. 목록에서 각 달팽이를 통해 반복됩니다. 각 달팽이에 대해 타일 맵에서 x 및 y 매개 변수를 참조하여 위치를 읽고 스프라이트를 생성하여 동일한 위치에서 Cocos2d-x 레이어에 배치했습니다. 같은 방법으로 Cocos2d-x 레이어에 고슴도치도 배치했습니다.

충돌 감지

이제 모든 달팽이와 고슴도치가 Tiled가 만든 TMX 맵에 정의된 위치에 따라 표시됩니다. 다음 문제는 모든 동물이 움직이기 시작할 때 원하는 곳으로 걷는다는 것입니다. 동물들은 서로 부딪히며 아무 일도 일어나지 않습니다. 일종의 충돌 감지 메커니즘이 필요합니다. 이 문제는 이전 문서(Tizen 애플리케이션의 Cocos2x-html5 게임 프레임워크: 추가 작업)에서 이미 설명되었지만 문서의 일관성을 위해 반복합니다. 또한 새로운 사례로 충돌 탐지를 확장합니다.

충돌 개체(양상추)를 반영하는 사각형이 이미 있고 달팽이와 고슴도치에 대한 사각형을 쉽게 만들 수 있으므로 맵의 개체가 이동할 때 서로 교차하는지 확인하기 위해 이러한 모든 사각형을 사용할 수 있습니다. 개체가 이동하는 동안 주요 게임 루프에서 이러한 사각형이 충돌하는지 확인하고 일부 액션(예를 들어 달팽이 사각형이 멈출 수 있는 양상추 사각형으로 이동하려는 경우)을 트리거합니다. 이것은 RunSnailRun 애플리케이션에서와 같은 업데이트 함수입니다.

update : function(dt) {
    var that = this;
    this.moveAndCheckForObstacles(this.hedgehog, dt);
    this.snails.forEach(function(snail) {
        that.moveAndCheckForObstacles(snail, dt);
    });
    this.collisionDetection();
}

 

보시다시피 고슴도치와 달팽이를 이동시키려고 하며 장애물(이 경우 양상추 1개)과 부딪히는지 확인합니다. 개체가 장애물과 충돌하는지 확인하기 위해 moveAndCheckForObstacles 함수를 사용합니다.

moveAndCheckForObstacles : function(object, dt) {
    var newPosition = object.move(dt, this.keyboardArrows);
    var newReactangle = cc.rect(newPosition.x+2 - object.width / 2, newPosition.y+2 - object.height / 2, object.width-4, object.height-4);
    if (!this.isCollisionInArray(newReactangle, this.tiledMap.obstacles)) {
        object.setPosition(newPosition);
    }
}

 

이 함수는 매우 간단하고 다음과 같이 작동합니다.

  • 새 위치를 계산하기 위해 개체에 알립니다.
  • 확보된 위치를 사용하여 새 사각형을 만들어 이동 후 개체의 위치를 정의합니다.
  • 이러한 새 사각형이 배열(이 경우 TMX 맵이 로드될 때 생성된 모든 양상추를 포함한 배열입니다)에서 정의된 사격형과 충돌하는지 확인하기 위해 isCollisionInArray 함수를 호출합니다.
  • 충돌이 없는 경우 새 위치에 개체를 설정합니다.

IsCollisionInArray 함수는 개체와 배열이라는 두 개의 인수를 사용합니다. 배열을 통해 반복하며 Cocos2d-x 함수 cc.rectIntersectsRect를 호출하여 배열의 항목이 전달된 개체와 충돌하는지 여부를 확인합니다. 이 함수는 다음과 유사하게 사용됩니다.

isCollisionInArray : function(item, array) {
    for (var i = 0; i < array.length; i++) {
        if (cc.rectIntersectsRect(item, array[i])) {
            return true;
        }
    }
    return false;
}

 

Tiled 애플리케이션을 사용하여 개체 레이어에서 추가된 모든 개체는 양상추와 충돌합니다. 양상추의 위치를 변경할 수 있으며 이러한 모든 메커니즘이 계속 작동해야 합니다.

요약

Tiled Map Editor는 TMX 맵을 만들 수 있는 매우 유용하고 간단한 도구입니다. 개체를 생성하고 개체와 레이어에 대한 속성을 정의할 수 있으며 Cocos2x-HTML5와 같은 게임 엔진에서 이러한 속성을 사용합니다. 게임 애플리케이션을 만드는 경우 Tiled 애플리케이션 사용을 고려하는 것이 좋습니다.

첨부 파일: