2013-03-26 2 views
0

Я пытаюсь создать бесшовный 2D-рендеринга tilemap в C++. Цель состоит в том, чтобы практически не загружать экраны, поскольку игрок переходит с каждой карты на другую.Бесшовные Tilemap Rendering C++

Например: Each square is a zone/tilemap; the red square is the viewable area Каждый квадрат на картинке выше, это зона/плитка; красный квадрат - видимая камера. В этом примере каждая зона 256х256 и хранится внутри std::vector<std::vector<int> > - позволяет также сказать, камера имеет видимую область 60х60 (от 32x32 плитки)

Мои вопросы в настоящее время являются, как решить:

  1. Какие плитки для отображения из каждой данной зоны.
  2. Как рассчитать смещение, чтобы нарисовать плитки.

Слегка связаны, если кто-то заинтересован в создании этой технологии я более чем готов заплатить за это :)

Я инженер-программист по профессии, однако графика вряд ли мой конек. Конечной целью является разработка старой школьной RPG с использованием OpenGL 3.2 с поддержкой шейдеров.

Спасибо всем!

+0

Сделайте это в стиле minecraft - куски «нагрузки», когда игрок достаточно близко к ним. «разгрузите» их, когда он окажется достаточно далеко, и сделайте все загруженные куски. Тогда пользователь никогда не увидит пробел, а не карту ^^ – Patashu

+0

В чем именно ваш вопрос? – Xymostech

+0

Интересная мысль Паташу, однако меня действительно смущает, как отобразить все данные зоны. Допустим, у вас есть четыре std :: vector > - каждый имеет 256x256 плит. Вы знаете, какие зоны связаны друг с другом, однако решают, какие данные должны быть представлены, и где я, к сожалению, смущен. –

ответ

0

Ничего себе это возвращает меня .. Хорошо, вот как я реализовал это в тот же день (используя directdraw 7, но действительно графический движок позади этого не имеет значения). Этот код только рисует то, что камера может видеть в любой заданной точке (на самом деле это единственное, что вы должны рисовать). Также имейте в виду, что этот код OLD и около того, когда я начал изучать, как развиваться. Это не будет очень красиво:

// 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

Поскольку ваша цель - иметь один большой смежный мир, действительно имеет смысл для вас разделить вещи на кучу других небольших файлов карт. Кажется, вы только создаете проблемы для себя.Если ваша карта абсолютно колоссальна, вам обязательно нужно будет найти пейджинг на диск и пейджинг, но это может быть дорогостоящим и может повредить производительность, особенно на мобильных устройствах. Я рекомендую вам создать только одну большую карту и сохранить эту карту в памяти. –

Смежные вопросы