티스토리 뷰

진짜 엄청 열심히 자료를 찾아다녔는데, 오늘에서야 잘 작동하는 소스를 찾을 수 있었다. 내 역량을 키워서 직접 수식을 만들 수 있으면 참 좋겠지만, 시간이 부족하다보니;;; 얼른 역량을 키워야 하는데 슬프다.


이 문제를 궁금해 하는 사람이 굉장히 많을 것 같은데 의외로 솔루션이 잘 검색되지 않아서 당황했다. 나 같은 경우에 처음에는 4개 직선의 방정식을 활용하여 타일 좌표를 구하는 방식을 이용했다. (참고 : http://eirenehue.egloos.com/970017) 소스는 다음과 같다. (나 같은 경우 맵 사이즈는 20 * 20, 타일 사이즈는 64 * 32 였다.)


bool decisionLineAndPosition( float slope, CCPoint p1, CCPoint p2 ) 

{

// slope의 기울기를 갖고 p1을 지나는 직선을 기준으로 p2이 직선 위쪽에 있는지, 아래쪽에 있는지 판단


// p2.y - p1.y = slope * (p2.x - p1.x)

float left = slope * (p2.x - p1.x);

float right = p2.y - p1.y;


// 직선 위에 있다 = true

// 직선 아래에 있다 = false

return left - right < 0;

};


// position은 node space 좌표이며 OpenGL 좌표계를 따른다. (좌하단이 (0, 0)이다.)

CCPoint GameTileMapLayer::GetTileCoordinateWithNodeSpacePosition( CCPoint position )

{

CCSize ms = this->getMapSize(); // 맵 사이즈

CCSize ts = this->getTileSize(); // 각각의 타일 사이즈


float slope = ts.height / ts.width;

int i, j;

for( i=0; i<ms.height; i++ )

{

for( j=0; j<ms.width; j++ )

{

// 특정 좌표상의 타일의 좌표를 구하는 함수, 타일의 좌하단 좌표를 반환한다.

CCPoint tilePos = _mapLayer->positionAt( ccp( j, i ) ); 

CCPoint L1L3 = ccp( tilePos.x, tilePos.y + ts.height/2 );

CCPoint L2L4 = ccp(tilePos.x + ts.width, tilePos.y + ts.height/2);


if ( decisionLineAndPosition( slope, L1L3, position ) == false && 

decisionLineAndPosition( slope, L2L4, position ) == true &&

decisionLineAndPosition( -1 * slope, L1L3, position ) == true &&

decisionLineAndPosition( -1 * slope, L2L4, position ) == false )

{

return ccp( j, i );

}

}

}


return ccp( -1, -1 );

}



하지만 개발을 하다가 갑작스럽게 문제가 발생했다. 바로 특정 좌표의 경우 타일 위치가 제대로 구해지지 않았던 것이다! 게다가 보면 알겠지만 위 방식의 문제점은 굉장히 노가다스러운 방법으로 타일 좌표를 구한다는 문제점을 갖고 있었다. 


이왕 이렇게 된 것, 진짜 맘 먹고 해결 방법을 찾아 나섰다. 정말 자료 안 나오더라.... 한국어 자료는 당연히 없었고, 외국 자료도 잘 되지 않는 것 투성이었다. 삽질에 삽질을 계속하다 결국 찾았다! 소스는 다음과 같다. (또한 Content scale factor를 적용했다. 만약 content scale factor를 사용하지 않는다면 CC_CONTENT_SCALE_FACTOR()를 나눠주는 부분을 삭제하면 된다.) 마찬가지로 함수의 인자인 position은 node space 좌표이다.


CCPoint GameTileMapLayer::GetTileCoordinateWithNodeSpacePosition( CCPoint position )

{

CCSize ms = this->getMapSize();

CCSize ts = this->getTileSize() / CC_CONTENT_SCALE_FACTOR();


float halfMapWidth = ms.width * 0.5;

CCPoint tilePosDiv = ccp( position.x / ts.width, position.y / ts.height );

float invereseTileY = ms.height - tilePosDiv.y;

float posX = (int)(invereseTileY + tilePosDiv.x - halfMapWidth);

float posY = (int)(invereseTileY - tilePosDiv.x + halfMapWidth);


if( 0 <= posX && posX < ms.width 

&& 0 <= posY && posY < ms.height )

return ccp( posX, posY );


return ccp( -1, -1 );

}


참고한 링크 : http://stackoverflow.com/questions/18095689/converting-isometric-tile-map-coordinates-to-screen-coordinates



댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday