2012-03-18 42 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 
    } 
} 

这会限制迭代的进行量。你可能已经设置好了你的循环,就像这样,但是为了防止你在整个世界中的每一个区域循环,就像我可能会有所帮助。我不是一个专业的游戏开发者,也没有正式的教育,所以这可能不是一个好的答案,但我希望它有帮助。