지그재그 아이소 메트릭 맵 : 화면상의 포인트에 대한 맵 좌표 계산


12

나는 이미 이것에 관한 많은 리소스가 있다는 것을 알고 있지만, 내 좌표계와 일치하는 것을 찾지 못했고 그 솔루션을 필요에 맞게 조정하는 데 큰 문제가 있습니다. 내가 배운 것은 이것을 수행하는 가장 좋은 방법은 변환 행렬을 사용하는 것입니다. 그것을 구현하는 것은 문제가되지 않지만 좌표 공간을 어떤 방식으로 변환 해야하는지 모르겠습니다.

내 좌표계를 보여주는 이미지는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

화면상의 점을이 좌표계로 어떻게 변환합니까?



이것이 어떻게 도움이되는지 볼 수 없습니다. 내 말의 의미를 이해하지 못했다고 생각합니다.
Chris

그것은 다른 방법으로 변환을 수행하므로 변환해야합니다.
Markus von Broady

답변:


23

먼저 코드는 다음과 같습니다. 설명은 다음과 같습니다.

/*
 * tw, th contain the tile width and height.
 *
 * hitTest contains a single channel taken from a tile-shaped hit-test
 * image. Data was extracted with getImageData()
 */

worldToTilePos = function(x, y) {

    var eventilex = Math.floor(x%tw);
    var eventiley = Math.floor(y%th);

    if (hitTest[eventilex + eventiley * tw] !== 255) {
        /* On even tile */

        return {
            x: Math.floor((x + tw) / tw) - 1,
            y: 2 * (Math.floor((y + th) / th) - 1)
        };
    } else {
        /* On odd tile */

        return {
            x: Math.floor((x + tw / 2) / tw) - 1,
            y: 2 * (Math.floor((y + th / 2) / th)) - 1
        };
    }
};

이 코드는 질문에 표시된지도에서 즉시 작동하지 않습니다. 홀수 타일은 왼쪽으로 오프셋되고 홀수 타일은 일반적으로 오른쪽으로 오프셋되기 때문입니다 ( 타일 ​​맵 편집기 의 경우와 동일 ). 홀수-타일 경우 반환 된 x 값을 조정하여이 문제를 쉽게 해결할 수 있어야합니다.

설명

이 작업을 수행하는 데있어 좀 더 무차별 한 방법 인 것 같지만 픽셀 완벽하고 약간 더 유연하다는 이점이 있습니다.

비결은지도를 단일 엇갈린 격자가 아니라 두 격자가 서로 겹쳐서 보는 것입니다. 홀수 행 격자와 짝수 행 격자가 있지만 대신 빨강과 녹색으로 호출하여 예쁜 다이어그램을 만들 수 있습니다.

빨간색과 녹색의 두 그리드

그 이미지의 오른쪽에 자주색 점으로 점을 표시했습니다. 이것이 우리가 원래 타일 공간에서 찾으려고하는 예시 포인트입니다.

세계의 어떤 점에서 주목해야 할 점은 항상 정확히 하나의 영역에 빨간색 영역과 녹색 영역이 있다는 것입니다. 그 지역을 찾아 보자 ...

두 후보 지역

이제 두 영역 중 올바른 영역을 선택하십시오. 항상 정확히 하나의 답이있을 것입니다.

여기에서 우리는 좀 더 간단한 산술을 할 수 있고 샘플 지점에서 두 영역의 각 중심점까지의 제곱 거리를 계산할 수 있습니다. 가장 가까운 것이 우리의 대답입니다.

그러나 다른 방법이 있습니다. 각 테스트 영역에 대해 타일의 정확한 모양과 일치하는 비트 맵을 샘플링합니다. 단일 타일에 대한 로컬 좌표로 변환 된 지점에서 샘플링합니다. 이 예에서는 다음과 같습니다.

포인트 샘플

왼쪽에서 녹색 영역을 확인하고 적중 (검정색 픽셀)을 얻습니다. 오른쪽에서 빨간색 영역을 테스트하고 누락 (흰색 픽셀)을 얻습니다. 두 번째 테스트는 항상 하나 또는 다른 것이기 때문에 중복되지는 않습니다.

그런 다음 1,1의 홀수 타일에 도달했다는 결론에 도달합니다. 이 좌표는 홀수 및 짝수 행에 대해 다른 변환을 사용하여 원래 타일 좌표에 간단하게 매핑해야합니다.

이 방법을 사용하면 픽셀 테스트 비트 맵에서 간단한 픽셀 별 속성을 가질 수 있습니다. 예를 들어 흰색은 타일이 벗겨졌고 검은 색은 적중했고 파란색은 물이며 빨간색은 단단합니다.


2
굉장 해요 ³입니다!
HumanCatfood '

환상적이고 잘 설명 된 답변-이제 코드로 구현하면됩니다. 오리지널 포스터는 자바 스크립트의 태그 이외의 언어 나 그 뒤에 코드에 대한 정보를 제공하지 않았기 때문에 A * 답변을 말합니다
Tom 'Blue'Piddock

1

나는 당신이 가진 문제가 좌표 공간에 있다고 생각합니다. 타일에 부여한 좌표는 실제로 등각 투영이 아닙니다. xAxis를 대각선 아래로 오른쪽으로 이동하고 yAxis를 대각선 아래로 왼쪽으로 이동하는 것으로 생각해야합니다 (또는 그 변형)

그림 좌표축을 따라 이동하면 "타일 공간"에서 대각선 방향으로 이동하므로 사각형이 다이아몬드로 표시됩니다 (모든 것이 더 복잡 해짐)

찾고있는 변환 행렬은 x 및 y 축으로 만들어졌습니다. 다음 계산을 수행하는 것과 사실상 동일합니다.

screenOffsetXY = screenPointXY - tileOriginXY;
tileX = dot(screenOffsetXY, xAxis) / tileWidth;
tileY = dot(screenOffsetXY, yAxis) / tileWidth;

편집 : 방금 비슷한 질문을했지만 (내가 이야기 한 좌표계와 함께) 누군가가 여기에 훨씬 더 철저한 답변을주었습니다.

마우스 좌표를 아이소 메트릭 인덱스로 변환하는 방법


0

기본적으로 이벤트 리스너를 사용하여 창에서 마우스 위치를 가져 오려면 마우스 위치에서 창에서 캔버스 위치의 오프셋을 제거해야하므로 마우스 위치는 캔버스를 기준으로합니다.

function mouseTwoGridPosition(e){

var mousex = e.pageX; //mouse position x
var mouseY = e.pageY;  //mouse position y
var canvas_width = 1000; //pixels
var offset_left = 100; //offset of canvas to window in pixels
var offset_top = 150; //offset of canvas to window in pixels

var isotile = 64; //if iso tile is 64 by 64

//get mouse position relative to canvas rather than window
var x = mousex - canvas_width/2 - offset_left;
var y = mousey - offset_top;


//convert to isometric grid
var tx = Math.round( (x + y * 2) / isotile) - 1;
var ty = Math.round((y * 2 - x) / isotile) - 1;

 //because your grid starts at 0/0 not 1/1 we subtract 1 
 // this is optional based on what grid number you want to start at



   return [tx,ty];
}

마우스 이동을 위해 캔버스에서 이벤트 리스닝을 수행하는 방법을 알고 있다고 가정합니다. 그렇지 않으면 아이소 메트릭 게임 디자인을 고려하기 전에 더 많은 JS를 배우고 싶을 수도 있습니다.


이게 너무 간단하지 않습니까? 나는 그것이 iso tile의 형태와 완벽하게 일치하기를 원합니다. 내가 올바르게 이해하면 직사각형 영역을 확인하고 있습니다.
Chris

isotile의 "형태"는 무엇을 의미합니까? 예를 들어 마우스가 0 : 1의 다이아몬드 모양 범위 내에 있다고 가정하면 마우스가 해당 경계를 벗어날 때까지 반환 값은 0 : 1이됩니다. 타일의 크기가 다양하면 내 방법이 작동하지 않습니다. 제공된 기능은 내가 사용하는 것이며 나에게 잘 작동합니다.
Dave

다른 모든 솔루션이 훨씬 복잡하기 때문에 궁금합니다. 타일은 물론 같은 크기이므로 이것을 확인하겠습니다.
Chris

잘 땜질하면 캔버스 왼쪽 및 위쪽 및 캔버스 너비의 올바른 오프셋을 얻을 수 있습니다. 수행 할 때 수학이 잘 작동합니다 (또한 isotile 크기 너비).
Dave

나와 같은 좌표계를 사용하고 있습니까? 여전히 완전히 꺼져 있습니다.
Chris

0

좌표 공간을 변경 하여이 문제를 해결했습니다. 이제 첫 번째 행에서 오프셋없이 시작하여 비트를 조정할 수있는 실제 예제를 찾았습니다.

    hWidth = this.tileset.tileSize.width / 2;
    hHeight = this.tileset.tileSize.height / 2;

    pX = point.x - halfWidth;
    pY = point.y - halfHeight;

    x = Math.floor((pX + (pY - hHeight) * 2) / this.tileset.tileSize.width);
    y = Math.floor((pY - (pX - hWidth) * 0.5) / this.tileset.tileSize.height);

    tx = Math.floor((x - y) / 2) + 1 + this.camera.x;
    ty = y + x + 2 + this.camera.y;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.