2012-03-18 41 views
1

由於性能問題,我不得不將我的地圖切成塊。 我管理的地圖以這樣的方式如何做「地圖塊」,比如terraria或我的世界地圖?

listMap[x][y] = new Tile (x,y); 

我妄圖切斷這個名單幾個「塊」,以避免加載所有的地圖,因爲FPS不是很高大的地圖。然而,當我更新或繪製時,我會用一個小塊範圍來做。這裏是我如何進行:

foreach (List<Tile> list in listMap) 
{ 
    foreach (Tile leTile in list) 
    { 
     if ((leTile.Position.X < screenWidth + hero.Pos.X) && 
      (leTile.Position.X > hero.Pos.X - tileSize) && 
      (leTile.Position.Y < screenHeight + hero.Pos.Y) && 
      (leTile.Position.Y > hero.Pos.Y - tileSize) 
     ) 
     { 
      leTile.Draw(spriteBatch, gameTime);   
     } 
    } 
} 

(和同樣的事情,更新方法)。

因此,我嘗試學習像Minecraft或terraria這樣的遊戲,並且任何兩個管理的地圖都比我的大得多,而沒有fps的下降。顯然,他們加載「塊」。

我想了解的是如何在Chunk中剪切我的列表,以及如何根據角色的位置來顯示。我嘗試了許多沒有成功的事情。

非常感謝您讓我走上正軌!

PS:再一次,對不起,我的英語:「( PPS:我不是一個實驗開發;)

編輯:

感謝IVlad,我獲得了10 fps的改變就像循環這個:

for (int x = (int)(hero.Pos.X)/tileSize; x < (hero.Pos.X/tileSize) + (int)(screenWidth/tileSize); x++) 
{ 
    for (int y = (int)(hero.Pos.Y)/tileSize; y < (hero.Pos.Y/tileSize) + (int)(screenHeight/tileSize); y++) 
    { 
     if (x >= 0 && y >= 0 && x <= tileXMax && y <= tileYMax) { 
      grille[x][y].Draw(spriteBatch, gameTime); 
     } 
    } 
} 

儘管如此,fps仍然很低,取決於地圖的大小,而不是可見瓦片的數量。

+0

究竟發生了什麼問題?它是否渲染了太多的瓷磚?你的方法似乎是正確的,因爲你只需要在屏幕上實際渲染瓷磚。 – 2012-03-18 13:11:19

+0

@SimeonVisser這是非常錯誤的fps。事實上,當我創建一個太大的地圖時,Fps非常低(1或2 fps)。我認爲,所有的列表都是「加載」的,並且遊戲不太喜歡它:/。 – 2012-03-18 13:15:50

+1

儘管您僅在屏幕上實際繪製切片,但如果我沒有弄錯,則會迭代地圖上的所有切片。難道你不應該找到你的角色所在的瓦片,只能在瓦片周圍迭代足夠的瓦片嗎? – IVlad 2012-03-18 13:16:19

回答

0

你應該做的第一件事就像使用Draw方法一樣,只創建/加載靠近你的貼圖。這應該會節省一些時間加載地圖,還有一些內存。

第二件事你可以做,而不必爲拼貼的繪圖功能,在每一個參考紋理,直接從外面畫他們,就像:

//in the load method... 
tileTextures = //a list/dictionary with all textures for tiles 

for (int x = minX; x < maxX; x++) 
    for (int y = minY; y < maxY; y++) 
    { 
     spriteBatch.Draw(tileTextures[list[x,y].TextureID], list[x,y].Position); 
    } 

這可能會或可能根據您處理數據的方式,這不會有用。

可以幫助你的另一件事是關於直角矩形。如果您使用的是它使碰撞檢測,也許是更好地使該檢測自己,例如:

void CheckCollision(Rectangle character) 
{ 
    int size = 16; 
    if (character.Right > this.Position.X && 
     character.Left < this.Position.X + size && 
     character.Bottom > this.Position.Y && 
     character.Top > this.Position.Y + size) 
    { 
     //Character is colliding with tile 
    } 
} 

基本上,這減少了由一個瓦片分配的內存量將好於大地圖時一切。

+0

事實上,我不認爲我可以從外面畫瓷磚,我所有的紋理列表/字典都在瓷磚類中。如果我在課外做所有事情,你認爲我會獲得FPS嗎?謝謝你的碰撞,你是對的,Colid矩形是爲他們做的,但暫時沒有做任何事情。它正在把我放在正確的軌道上,謝謝:) – 2012-03-19 12:44:23

+0

那麼,正如我所說,這取決於你如何處理數據。你可以完全做到這一點,我只是建議你儘可能多地保留那些課外的數據。例如,如果字典在tile類內部,那就是一個引用。紋理是另一個,等等......這些是額外的字節,它會乘以瓦片數量,所以2個參考文件=每個瓦片8個字節 - 2M個瓦片意味着16Mb額外的,這可能或不可能是好的。如果你可以像所有紋理一樣的TileManager,並且在你想繪製的時候檢索它們,我認爲那會很好。 – Osguima3 2012-03-20 16:13:31

0

我有這樣的問題。我經歷了我的遊戲滯後,因爲我正在像這樣調用地圖塊。

var mapTile = map.data[mapX + ":" + mapY]; 

整個世界的所有數據都存儲在那個map.data數組中。我沒有使用塊,塊可以讓我循環遍歷2D數組。如果循環只在當前塊上循環,也許周圍的變換會循環,這可能會有所幫助。所以如果地圖有100塊。它只會覆蓋9個塊而不是100個。這是一個簡單的例子。

for(var x = 0; x < map.chunk[chunk.x + ":" + chunk.y].data[x].length; x++) { 
    for(var y = 0; y < map.chunk[chunk.x + ":" + chunk.y].data[x][y].length) { 
    //Draw tiles here that are on screen 
    } 
} 

這會限制迭代的進行量。你可能已經設置好了你的循環,就像這樣,但是爲了防止你在整個世界中的每一個區域循環,就像我可能會有所幫助。我不是一個專業的遊戲開發者,也沒有正式的教育,所以這可能不是一個好的答案,但我希望它有幫助。