2013-03-26 3 views
0

C++로 매끄러운 2D 타일 맵 렌더러를 만들려고합니다. 목표는 플레이어가 각지도에서 다른지도로 진행할 때 화면을 거의 또는 전혀로드하지 않는 것입니다.매끄러운 타일 맵 렌더링 C++

예 : Each square is a zone/tilemap; the red square is the viewable area 위 그림의 각 사각형은 영역/타일 맵입니다. 빨간색 사각형은 볼 수있는 카메라입니다. 이 예에서, 각 영역은 256 * 256과 std::vector<std::vector<int> > 내부에 저장되어 - 또한 카메라가 60X60의 볼 수있는 영역 (의 32 × 32 타일)

내 문제는 현재를 결정하는 방법이다 가지고 말할 수 :

  1. 무엇 타일 각 주어진 영역에서 표시 할 수 있습니다.
  2. 타일을 그릴 오프셋을 계산하는 방법. 누군가가 내가 지불 :

    나는 무역에 의해 소프트웨어 엔지니어 오전 기꺼이 이상입니다이 기술을 만들기에 관심이있는 경우

는 약간 관련, 그러나 그래픽은 거의 내 강점 없습니다. 최종 목표는 셰이더를 지원하는 OpenGL 3.2를 사용하여 구식 RPG를 개발하는 것입니다.

감사합니다.

+0

플레이어가 충분히 가까워지면 미니 크래프트 스타일로 '로드'청크를 만드십니까? 그가 멀리 떨어져있을 때 그들을 '언로드'하고로드 된 모든 청크를 렌더링합니다. 그렇다면 사용자는 맵 대신 갭을 결코 보지 못할 것입니다. ^^ – Patashu

+0

당신의 질문은 정확히 무엇입니까? – Xymostech

+0

재미있는 생각 Patashu,하지만 정말로 나를 혼란스럽게하는 것은 모든 영역 데이터를 표시하는 방법입니다. 네 std :: vector > - 각각 256x256 타일을 가지고 있다고 가정 해 보겠습니다. 어떤 영역이 서로 관련이 있는지 알고 있지만 렌더링해야 할 데이터와 불행하게도 혼란스러워하는 부분을 결정해야합니다. –

답변

0

와우 이것은 나를 되찾아줍니다. 좋아, 여기에 내가 어떻게 그 일을 구현했는지 (directdraw 7을 사용하지만이 뒤에있는 그래픽 엔진은 무의미 함). 이 코드는 특정 지점에서 카메라가 볼 수있는 것을 그리기 만합니다 (그리면 반드시 그려야합니다). 또한이 코드는 오래되었고 처음 개발하는 방법을 배우기 시작했을 때 주위에 있습니다. 그것은 매우 예쁘지 않을 것입니다 :

// set original render location to x = 0, y = 0, width = tileWidth, height = tileHeight 
// this is the top left corner of the screen 
RECT renderLoc = { 0, 0, g_MapData.m_TileSize, g_MapData.m_TileSize }; 

// the first column of visible tiles is given by the x coordinate divided 
// by the tilesize and first visible row is given by the y coordinate/tileWidth 
int xStartCol = g_MapData.m_xCamera/g_MapData.m_TileSize; 
int yStartRow = g_MapData.m_yCamera/g_MapData.m_TileSize; 

// calculate the number of tiles in the current resolution that are visible 
int xVisibleTiles = (dd7.m_ScreenWidth/g_MapData.m_TileSize); 
int yVisibleTiles = (dd7.m_ScreenHeight/g_MapData.m_TileSize); 

// if the tilesize is not divisible by the screensize then the 
// number of visible tiles will not calculate correctly. It will 
// be a float and since this is truncated, it will contain a row or 
// column less than what it requires. This code compensates for that 
// by just adding one more row to round up instead of down. 
if (dd7.m_ScreenWidth%g_MapData.m_TileSize) { xVisibleTiles++; } 

if (dd7.m_ScreenHeight%g_MapData.m_TileSize) { yVisibleTiles++; } 

// now just add the size in tiles of the visible screen to get the end 
int xEndCol = xStartCol + xVisibleTiles; 
int yEndRow = yStartRow + yVisibleTiles; 

// Visible tiles referring to the tiles that can be displayed across and 
//down on the screen (this depends on the resolution set) 

// now check if the camera coordinates are divisible by the tile size 
int x, y, l; // variables for loops and checks 

x = g_MapData.m_xCamera % g_MapData.m_TileSize; 
y = g_MapData.m_yCamera % g_MapData.m_TileSize; 

if (!x) 
{ 
    // remove a column to draw since it divided perfectly. We originally  
    //added one to the visible rows and columns 
xEndCol--; 
} 
else 
{ 
// need to move renderLoc RECT. Since there could be half a column  
//exposed which forces us to draw that portion. we only want to draw what 
//is currently on the viewable screen to save memory. 
renderLoc.left -= x; 
renderLoc.right -= x; 
} 

// now do the same for rows 
if (!y) 
{ 
yEndRow--; 
else 
{ 
renderLoc.top -= y; 
renderLoc.bottom -= y; 
} 

// now check to make sure we're not exceeding map size 
if (xEndCol > g_MapData.m_xMaxTiles) { xEndCol = g_MapData.m_xMaxTiles; } 
if (yEndRow > g_MapData.m_yMaxTiles) { yEndRow = g_MapData.m_yMaxTiles; } 

// Now Draw! 
// for each layer 
for (l = 0; l < g_MapData.m_Layers; l++) { 
// draw the rows 
for (x = xStartCol; x <= xEndCol; x++) { 
    // column by column 
    for (y = yStartRow; y <= yEndRow; y++) {    
    tileToRender = g_MapData.m_Tiles[x][y][l]; 
// Finish your drawing.. 
+1

큰지도 파일을 피하는 것이 목적이 아니라면, 정말 필요할 때마다 디스크에서 메모리를 페이징하는 것이 아니라면, 이렇게하면 여러 가지 작은지도로 분할 할 필요가 없습니다. . 하나의 파일 또는 많은 파일이 실제로는 무의미한 경우 –

+0

원래 작은지도 (아마도 500x500이라고 말하면서)가 많은 것을 목표로 삼았습니다. 페이징 메모리에 익숙하지 않고 휴대 기기를 대상으로하는 방법이 얼마나 안전한 지 확신 할 수 없습니다. . 당신은 하나의 대용량 파일과 std :: deque가 올바르게 작동한다고 가정하니 디스크에서 페이징 될 때 데이터가 양쪽 끝에서 밀리거나 튕겨 나올 것입니까? –

+1

목표가 하나의 커다란 연속적인 세계를 가지기 때문에 여러 가지 작은지도 파일로 물건을 분할하는 것이 실제로 의미가 있습니다. 단지 자신 만의 문제를 만드는 것 같습니다.지도가 절대적으로 엄청나다면 반드시 페이징을 디스크 및 페이징으로보아야하지만 이는 비용이 많이 들고 특히 모바일 장치에서 성능을 저하시킬 수 있습니다. 하나의 큰지도를 만들고 그지도를 메모리에 보관하는 것이 좋습니다 –