우아한 자동 기울이기


10

사람들이 타일 기반 게임에서 자동 타일링을 구현하는 방법에 대한 정보를 찾고 있습니다. 지금까지 나는 하드 코딩 된 "if ... else ..."문장으로 항상 즉흥적으로 개선했으며 이제는 더 우아한 솔루션을 찾을 때가되었다고 결정했다. 나는 자동 타일링 구현과 주제에 대한 토론의 예를 인터넷에서 검색했지만 세 가지 기사 만 찾았습니다.

(특히 마지막 것은 포괄적이고 매우 도움이됩니다.)

또한 flixel과 같이 라이브러리를 구현하는 다양한 구현 및 라이브러리 문서를 살펴 보았습니다. http://www.flixel.org/features.html#tilemaps

안타깝게도 내가 찾은 모든 솔루션은 내가 처음 시작한 것만큼이나 즉흥적으로 이루어졌으며 가능한 모든 경우를 다루지 않습니다.

나는 배울 수있는 자동 기울이기 구현의 우아한 예를 찾고 있습니다.

답변:


10

나는 타일 ​​맵을 적용하기 위해 비트 단위 방법을 사용 했으며 매우 우아한 솔루션이라는 것을 알았습니다. 이 기사에서는 구체적인 예를 제공하고 여러 지형 유형을 처리하도록 알고리즘을 확장하는 방법에 대해 설명합니다.


이것은 flixel "AUTO"자동 기울임 모드에서 사용하는 알고리즘처럼 보입니다. 고맙습니다. 목록에 추가하겠습니다.
Radomir Dopieralski

3

나는이 문제를 직접 인터넷 검색하여 여기에 도착하고 링크 된 기사를 읽고 47 개의 타일 세트를 생성하는 비교적 컴팩트 한 솔루션을 제작했습니다. 다음과 같이 자동 타일 된 재료에는 2x3 타일셋이 필요합니다.2x3 자동 타일 세트

왼쪽 상단에 단일 타일 변형이 있고 오른쪽 상단에 내부 코너가 있고 하단에 4 개의 외부 코너 타일이 있습니다 (RPG Maker에서이 배열을 인식 할 수 있음).

트릭은 렌더링을 위해 각 "논리적"맵 타일을 4 개의 반 타일로 나누는 것입니다. 또한 타일셋의 반 타일은 생성 된 타일의 해당 위치 에만있을 수 있으므로 왼쪽 위 절반 타일은 왼쪽 위 위치에만 사용할 수 있습니다.

이 제한 사항은 8 개의 이웃 타일 대신 절반 타일 당 3 개의 전체 타일 이웃 만 확인하면된다는 것을 의미합니다.

이 아이디어를 신속하게 구현하여 테스트했습니다. 개념 증명 코드 (TypeScript)는 다음과 같습니다.

//const dirs = { N: 1, E: 2, S: 4, W:8, NE: 16, SE: 32, SW: 64, NW: 128 };
const edges = { A: 1+8+128, B: 1+2+16, C: 4+8+64, D: 4+2+32 };
const mapA = { 0:8, 128:8, 1:16, 8:10, 9:2, 137:18, 136:10, 129:16 };
const mapB = { 0:11, 16:11, 1:19, 2:9, 3:3, 19:17, 18:9, 17:19 };
const mapC = { 0:20, 64:20, 4:12, 8:22, 12:6, 76:14, 72:22, 68:12 };
const mapD = { 0:23, 32:23, 4:15, 2:21, 6:7, 38:13, 34:21, 36:15 };

export function GenerateAutotileMap(_map: number[][], _tile: integer): number[][]
{
    var result = [];
    for (var y=0; y < _map.length; y++) {
        const row = _map[y];
        const Y = y*2;
        // half-tiles
        result[Y] = [];
        result[Y+1] = [];
        // each row
        for (var x=0; x < row.length; x++) {
            // get the tile
            const t = row[x];
            const X = x*2;
            if (t != _tile) continue;
            // Check nearby tile materials.
            const neighbors = (North(_map, x, y) == t? 1:0)
                + (East(_map, x, y) == t? 2:0)
                + (South(_map, x, y) == t? 4:0)
                + (West(_map, x, y) == t? 8:0)
                + (NorthEast(_map, x, y) == t? 16:0)
                + (SouthEast(_map, x, y) == t? 32:0)
                + (SouthWest(_map, x, y) == t? 64:0)
                + (NorthWest(_map, x, y) == t? 128:0);
            // Isolated tile
            if (neighbors == 0) {
                result[Y][X] = 0;
                result[Y][X+1] = 1;
                result[Y+1][X] = 4;
                result[Y+1][X+1] = 5;
                continue;
            }
            // Find half-tiles.
            result[Y][X] = mapA[neighbors & edges.A];
            result[Y][X+1] = mapB[neighbors & edges.B];
            result[Y+1][X] = mapC[neighbors & edges.C];
            result[Y+1][X+1] = mapD[neighbors & edges.D];
        }
    }
    return result;
}    

설명:

  • A타일의 왼쪽 상단 부분, B오른쪽 상단, C왼쪽 D하단, 오른쪽 하단입니다.
  • edges 각각에 대한 비트 마스크를 보유하므로 관련 이웃 정보 만 가져올 수 있습니다.
  • map* 은 타일셋 이미지 (0..24)에서 인접 상태를 그래픽 인덱스에 매핑하는 사전입니다.
    • 각 반 타일은 3 개의 이웃을 확인하기 때문에 각각 2 ^ 3 = 8 상태를 갖습니다.
  • _tile 자동 기울이기 대상 타일입니다.
  • 논리 타일은 렌더링 타일의 두 배 크기이므로 렌더링 맵에서 모든 자율 좌표 (x, y)를 두 배로 늘려야합니다.

어쨌든 결과는 다음과 같습니다 (어쨌든 하나의 타일 만 있음).여기에 이미지 설명을 입력하십시오


0

나는 대부분의 링크를 읽었고 다른 해결책을 생각해내는 데 시간을 보냈다. 그것이 좋은지 아닌지는 모르겠지만 RPG Maker VX Ace 자동 타일 동작 (47 타일) 을 시뮬레이션하기 위해 다음과 같이 시작했습니다.

(왼쪽 0 또는 1) + (오른쪽 0 또는 1) + (위 0 또는 1) + (아래 0 또는 1) 이제 5 가지 경우가 있습니다.

4 = 타일 46이 배치 된 경우

3 명의 탑승자 =

2 4 경우 + 2 경우 알고리즘에 대해 잘 모르지만 만들 지점이 많지 않은 경우.

1 = 작업 중이지만 모든 방향이 4 가지 경우 끝날 수 있습니다

0 = 1, 2, 4, 8의 링크에 표시된 숫자 알고리즘을 사용할 수 있고 1에서 15까지 ID를 얻으면 직접 사용할 수 있습니다.

나는 프로그래머가 아니며 수학 알고리즘과 1, 2, 4, 8, 16, 32, 64, 128 솔루션으로 최고가 아닙니다.

어쩌면 내 접근법이 적어도 그것보다 낫습니다.


1
이 답변이 질문에 완전히 대답했는지 잘 모르겠습니다. 조금 더 설명해 주시겠습니까? 다른 것을 언급한다면, 적어도 그것에 연결할 수 있습니까?
Vaillancourt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.