Помогите с реализацией программы на C #: несколько массивов списков или лучший способ? - PullRequest
4 голосов
/ 18 марта 2010

Я создаю RPG на основе плиток 2D в XNA и нахожусь на начальной стадии проектирования. Я думал о том, как я хочу, чтобы мой плиточный двигатель работал, и придумал набросок. По сути, я хочу сетку плиток, но в каждом местоположении я хочу добавить несколько плиток и иметь смещение. Мне бы хотелось, чтобы я мог добавить что-то вроде отдельных деревьев на карте мира, чтобы придать больше блеска. Или поставьте бутылки на бар в каком-нибудь городе, не тяня за собой кучу разных плиток с разными бутылками.

Но, возможно, моя досягаемость больше, чем моя хватка. Я пошел, чтобы реализовать идею, и у меня было что-то вроде этого в моем объекте карты:

List<Tile>[,] Grid;

Но потом я подумал об этом. Допустим, у меня была карта мира 200х200, которая на самом деле была бы довольно маленькой, если говорить о РПГ. Это составит 40 000 списков. Я думаю, что должен быть лучший путь. Теперь это предварительная оптимизация. Я не знаю, удастся ли мне с этим справиться, если бы я спроектировал свои карты и игру, но это кажется неоправданно неэффективным, и что-то может всплыть, если моя игра станет более сложной.

У меня есть идея сделать смещение и несколько плиток необязательными, чтобы я платил за них только при необходимости. Но я не уверен, как бы я это сделал. Несколько массив объектов?

object[,] Grid;

Итак, вот мои критерии:

  • 2D сетка местоположений плитки
  • Каждая ячейка имеет минимум 1 плитку, но дополнительно может иметь больше
  • Каждая дополнительная плитка может иметь смещение по осям X и Y для точного размещения

Может ли кто-нибудь помочь с некоторыми идеями для реализации такого дизайна (не нужно, чтобы это было сделано для меня, просто идеи) при минимальном использовании памяти?

Если вам нужно больше фона, примерно то, что составляют мои объекты Map и Tile:

public struct Map
{
    public Texture2D Texture;
    public List<Rectangle> Sources; //Source Rectangles for where in Texture to get the sprite
    public List<Tile>[,] Grid;
}
public struct Tile
{
    public int Index; //Where in Sources to find the source Rectangle
    public int X, Y; //Optional offsets
}

Ответы [ 3 ]

4 голосов
/ 18 марта 2010

Что вы могли бы сделать, это просто иметь массив Tile:

class Grid
{
    Tile[,] grid;
}

... и класс Tile содержит List<Sprite>:

class Tile
{
    List<Sprite> sprites;
}

... и этот класс Sprite будет иметь вашу текстуру и смещение:

class Sprite
{
    Vector2 offset;
    Texture2D texture;
}

Завершите все это, используя методы рисования:

class Grid
{
    Tile[,] grid;

    void Draw(GraphicsDevice graphics)
    {
        // call your tiles Draw()
    }


}

class Tile
{
    List<Sprite> sprites;
    void Draw(GraphicsDevice graphics, int x, int y)
    {
        // call your sprites Draw()
    }
}

class Sprite
{
    Vector2 offset;
    Texture2D texture; // or texture and rectangle, or whatever

    void Draw(GraphicsDevice graphics, int x, int y)
    {
        // draw the sprite to graphics using x, y, offset and texture
    }
}

Конечно, все становится намного сложнее, но вы должны понять.

Разделение всех ваших задач по разным классам позволяет легко добавить новую функциональность, которая не будет конфликтовать с существующим кодом. Попытка объединить все ваши данные в одном объекте, например, в List [,], является плохой формой и в конечном итоге укусит вас, когда вы попытаетесь расширить.

1 голос
/ 18 марта 2010

Вы, по сути, хотите, чтобы разреженная матрица представляла «украшения» на каждой плитке. Разреженная матрица - это матричная структура, в которой не все элементы должны иметь значение. Есть библиотеки C #, которые представляют их.

Простой подход заключается в использовании обычного словаря, в котором ключом является Tile # (уникальный номер каждой плитки), который, например, можно рассчитать с использованием формулы того же типа, что и для обращения к видеопамяти: Y * MAXIMUM_X + X Для данной плитки просто проверьте, есть ли запись для ее уникального номера плитки. Словарь, вероятно, должен содержать список украшений для этой конкретной плитки:

Dictionary<int, List<Sprites>> spritesPerTile;
// ...
if (spritesPerTile.ContainsKey(tileNumber))
{
    List<Sprites> decorationsThisTile = spritesPerTile[tileNumber];
    // Proceed to render sprites on this tile.
}
1 голос
/ 18 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...