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


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.