Как сделать «куски карты», как карты террариумов или майнкрафт? - PullRequest
1 голос
/ 18 марта 2012

Из-за проблем с производительностью мне приходится разрезать карты на куски. Я управляю картами следующим образом:

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. И, видимо, они загружают «куски».

То, что я хотел бы понять, это как сократить мой список в Чанке и как отображать в зависимости от положения моего персонажа. Я пытаюсь много вещей без успеха.

Заранее спасибо, что поставили меня на правильный путь!

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 все еще низкие и зависят от размера карты, а не от количества видимых тайлов.

Ответы [ 2 ]

0 голосов
/ 09 сентября 2014

У меня была такая проблема.У меня возникла задержка в игре, потому что я так называл плитку карты.

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

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

0 голосов
/ 18 марта 2012

Первое, что вы должны сделать, как и в случае с методом 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);
    }

Это может или не может быть полезно, в зависимости от того, как вы обрабатываете данные.

Еще одна вещь, которая может вам помочь, - это прямоугольный столбик.Если вы используете его для обнаружения коллизий, возможно, лучше сделать это самостоятельно, например:

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

В принципе, все, что уменьшает объем памяти, выделяемой одной плиткой, будет хорошо, когда вбольшие карты.

...