나는 이미 이것에 관한 많은 리소스가 있다는 것을 알고 있지만, 내 좌표계와 일치하는 것을 찾지 못했고 그 솔루션을 필요에 맞게 조정하는 데 큰 문제가 있습니다. 내가 배운 것은 이것을 수행하는 가장 좋은 방법은 변환 행렬을 사용하는 것입니다. 그것을 구현하는 것은 문제가되지 않지만 좌표 공간을 어떤 방식으로 변환 해야하는지 모르겠습니다.
내 좌표계를 보여주는 이미지는 다음과 같습니다.
화면상의 점을이 좌표계로 어떻게 변환합니까?
나는 이미 이것에 관한 많은 리소스가 있다는 것을 알고 있지만, 내 좌표계와 일치하는 것을 찾지 못했고 그 솔루션을 필요에 맞게 조정하는 데 큰 문제가 있습니다. 내가 배운 것은 이것을 수행하는 가장 좋은 방법은 변환 행렬을 사용하는 것입니다. 그것을 구현하는 것은 문제가되지 않지만 좌표 공간을 어떤 방식으로 변환 해야하는지 모르겠습니다.
내 좌표계를 보여주는 이미지는 다음과 같습니다.
화면상의 점을이 좌표계로 어떻게 변환합니까?
답변:
먼저 코드는 다음과 같습니다. 설명은 다음과 같습니다.
/*
* 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의 홀수 타일에 도달했다는 결론에 도달합니다. 이 좌표는 홀수 및 짝수 행에 대해 다른 변환을 사용하여 원래 타일 좌표에 간단하게 매핑해야합니다.
이 방법을 사용하면 픽셀 테스트 비트 맵에서 간단한 픽셀 별 속성을 가질 수 있습니다. 예를 들어 흰색은 타일이 벗겨졌고 검은 색은 적중했고 파란색은 물이며 빨간색은 단단합니다.
나는 당신이 가진 문제가 좌표 공간에 있다고 생각합니다. 타일에 부여한 좌표는 실제로 등각 투영이 아닙니다. xAxis를 대각선 아래로 오른쪽으로 이동하고 yAxis를 대각선 아래로 왼쪽으로 이동하는 것으로 생각해야합니다 (또는 그 변형)
그림 좌표축을 따라 이동하면 "타일 공간"에서 대각선 방향으로 이동하므로 사각형이 다이아몬드로 표시됩니다 (모든 것이 더 복잡 해짐)
찾고있는 변환 행렬은 x 및 y 축으로 만들어졌습니다. 다음 계산을 수행하는 것과 사실상 동일합니다.
screenOffsetXY = screenPointXY - tileOriginXY;
tileX = dot(screenOffsetXY, xAxis) / tileWidth;
tileY = dot(screenOffsetXY, yAxis) / tileWidth;
편집 : 방금 비슷한 질문을했지만 (내가 이야기 한 좌표계와 함께) 누군가가 여기에 훨씬 더 철저한 답변을주었습니다.
기본적으로 이벤트 리스너를 사용하여 창에서 마우스 위치를 가져 오려면 마우스 위치에서 창에서 캔버스 위치의 오프셋을 제거해야하므로 마우스 위치는 캔버스를 기준으로합니다.
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를 배우고 싶을 수도 있습니다.
좌표 공간을 변경 하여이 문제를 해결했습니다. 이제 첫 번째 행에서 오프셋없이 시작하여 비트를 조정할 수있는 실제 예제를 찾았습니다.
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;