如何做“;映射块”;,比如terraria或minecraft地图

本文关键字:terraria 比如 minecraft 地图 何做 映射 | 更新日期: 2023-09-27 18:28:06

由于性能问题,我不得不将映射分割成块。我用这种方式管理地图:

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帧/秒的速度:

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仍然很低,并且取决于贴图的大小,而不是可见瓦片的数量。

如何做“;映射块”;,比如terraria或minecraft地图

您应该做的第一件事是,就像使用Draw方法一样,只创建/加载离您很近的瓦片。这样可以节省一些加载地图的时间,也可以节省一些内存。

你可以做的第二件事是直接从外部绘制瓷砖,而不是为瓷砖设置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
    }
}

基本上,在大地图中,减少一个瓦片分配的内存量的一切都会很好。

我遇到过这种问题。我在游戏中遇到了滞后,因为我这样调用地图平铺。

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

整个世界的所有数据都存储在map.data数组中。我没有使用chunk,chunk可以让我在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
  }
}

这将限制正在进行的迭代数量。你可能已经将循环设置为这样工作,但以防万一你像我一样在整个世界的每个瓦片上循环,也许这会有所帮助。我不是专业的游戏开发人员,也没有受过正规教育,所以这可能不是一个好答案,但我希望它能有所帮助。