怎么做“地图块”,如terraria或minecraft地图?

时间:2012-03-18 13:02:07

标签: c# algorithm xna-4.0

由于性能问题,我必须将地图切割成块。 我以这种方式管理地图:

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);        
        }
    }
}

(同样的,对于更新方法)。

所以我尝试学习像我的世界或者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仍然很低,取决于地图的大小而不是可见的瓷砖数量。

2 个答案:

答案 0 :(得分: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);
    }

这可能会也可能没用,具体取决于您处理数据的方式。

另一件可以帮助你的事情是关于colid矩形。如果您正在使用它进行碰撞检测,可能最好自己进行检测,例如:

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

基本上,在大地图中,减少一个图块分配的内存量的所有内容都会很好。

答案 1 :(得分:0)

我遇到过这种问题。我的游戏经历了滞后,因为我正在调用这样的地图图块。

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

整个世界的所有数据都存储在该map.data数组中。我没有使用块,块可以让我循环一个二维数组。也许如果循环仅在当前块上循环并且可能是周围的循环以进行转换,这将有所帮助。因此,如果地图中有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
  }
}

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