Вопрос

Я пытаюсь завершить RPG-игру для проекта, но понятия не имею, как составить карту игры. Он не должен быть графическим, но код для всей карты и каждой плитки должен быть правильным.

До сих пор я думал о создании нематериальной карты (по просьбе профессора) с использованием ArrayList, который содержит все связанные плитки.

public abstract class Casella {
/** 
 * @uml.property name="tabellone"
 * @uml.associationEnd multiplicity="(1 1)" inverse="casella:Tabellone"
 * @uml.association name="contains"
 */

private int id;
private boolean free = true;
private List adjacent;
private List items;
private Tabellone tabellone = null;

public void in(){
    free = false;
}

public void out(){
    free = true;
}

}

Это был код для одной плитки (которая имеет 3 класса, расширяющих ее). Я до сих пор не знаю, как собрать и создать карту.

Спасибо за ваше время.

Это было полезно?

Решение 6

Мне удалось это с помощью списков смежности. Каждая ячейка будет иметь ArrayList, содержащий индексы соседних ячеек. Это те индексы, которые указанная ячейка имеет в карте ArrayList ячеек.

http://en.wikipedia.org/wiki/Adjacency_list

Другие советы

Не начинайте с реализации, начните с того, как вы хотели бы использовать карту. Это даст вам некоторые ограничения, как реализовать это. Например:

Когда вы рисуете карту, как вы к ней получаете доступ? По координатам? Или "иди на запад от плитки X"?

[EDIT] Я предлагаю начать с основного цикла игры RPG. Вам нужно будет поместить символ / жетон где-нибудь (то есть, ему нужно какое-то отношение к плитке).

Тогда вам нужно переместить персонажа. Персонаж должен уметь исследовать текущий тайл (противники, предметы, тип). Ему нужен способ узнать, как он может двигаться (т.е. есть ли стена справа?)

Это дает вам интерфейс для вашей карты: сервисы, которые она предоставляет для других объектов в игре. Когда у вас есть представление о том, что должен предоставлять интерфейс, это должно дать вам представление о том, как реализовать карту (структуру данных).

Что касается генерации карты, используйте генератор случайных чисел и немного "здравого смысла". Посмотрите на соседние плитки: когда они все городские, эта плитка, вероятно, тоже город. То же самое для равнин. Холмы - особые предметы, и они встречаются реже.

Запустите этот код, распечатайте карту как ASCII («C», «P», «H»), чтобы проверить, работает ли она.

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

private Tabellone up = null;
private Tabellone down = null;
private Tabellone left = null;
private Tabellone right = null;

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

Tabellone adj = new Tabellone();
up = adj;
adj.setDown(this);

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

int count = 0;
ArrayList<Tabellone> queue = new ArrayList<Tabellone>()
queue.add(/*center tile*/);
while (count < 100) { //if we want 100 tiles
  //take out the center tile from the beginning of the array list, create a tile for each direction and add those tiles to the array list, then increment count by 1.
}

Примечание. Этот алгоритм в его нынешнем виде создаст карту в форме ромба. Если вам нужен квадрат, вам также потребуется переменная для каждого диагонального направления.

Конечно, если это кажется немного сложнее, чем хотелось бы, я бы порекомендовал систему координат.

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

private String level =
          "    ######\n"
        + "    ##   #\n"
        + "    ##$  #\n"
        + "  ####  $##\n"
        + "  ##  $ $ #\n"
        + "#### # ## #   ######\n"
        + "##   # ## #####  ..#\n"
        + "## $  $          ..#\n"
        + "###### ### #@##  ..#\n"
        + "    ##     #########\n"
        + "    ########\n";

Это уровень игры. За исключением места, есть пять символов. Хеш (#) обозначает стену. Доллар ($) представляет собой поле для перемещения. Точка (.) Символ представляет место, где мы должны переместить поле. Символ (@) - это сокобан. И, наконец, символ новой строки (\ n) начинает новую строку в мире.

Скорость или память - огромное беспокойство для этого проекта? Если нет, то почему бы вам не использовать 2d массив?

Что-то вроде

Casella map [][] = new Casella[xSize][ySize];

Отсюда легко понять концепцию, просто представьте ее в виде таблицы Excel, где каждая ячейка является плиткой на карте.

Тем не менее, путь, по которому вы идете, хорош, иногда его сложно осмыслить. У вас есть список смежных плиток. Итак, при создании вашей карты вы начинаете где-то, возможно, слева вверху, и идете оттуда.

Вы можете использовать вложенные циклы для настройки карты и определения краевых элементов.

for(int i = 0; i < XSIZE ; ++i)
    for(int j = 0; j < YSIZE ; ++j)
        if(j==0) //found left edge (i.e. no adjacent ones to the left)
        if(j==(YSIZE)) //found right edge (you get the picture) 

Смысл использования петель и проверки ребер заключается в том, что вам нужно будет ссылаться назад и вперед, вверх и вниз для каждой плитки, за исключением краев, где у вас будет 2 или 3 ссылки вместо 4.

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

Предполагая, что у вас есть карта с X-плитками и без упорядоченной смежности, нематериальное решение является наилучшим, общее решение состоит в том, чтобы просто смоделировать его как граф, используя либо список смежности для несимметричной смежности, либо список инцидентности для симметричной смежности , Если вы используете список инцидентности, вам нужен объект ребра, который содержит вершины, с которыми соединяется ребро, если вы используете список смежности a multimap может быть круто использовать.

Если вы хотите нематериальное решение с упорядоченной смежностью, AlbertoPL найдет решение для этого.

Предполагая, что у вас есть карта, которая имеет X плиток в ширину и Y плиток в высоту, а плитки, расположенные рядом друг с другом, являются смежными, так что каждая плитка имеет не более 4 и не менее 2 смежных плиток, вы можете использовать матрицу для доступа к плиткам. а также представляют смежность по матричной смежности. Идея состоит в том, что карта [Y] [X] смежна с картой [Y + 1] [X] и картой [Y] [X + 1] и наоборот. Это решение может также соответствовать максимум 6 и минимум 3 смежности плитки, если плитка [Y + 1] [X + 1] смежна с плиткой [Y] [X]. Помимо этого, вы можете легко анализировать карту, и, поскольку она имеет 2 измерения, естественно моделировать ее следующим образом. Недостатком является то, что после установки плитки вы не можете изменить ее смежность без изменения матрицы. Поскольку это не то, что вы, профессор, предложили, возможно, вы не захотите это делать, но если у вас есть (статическая) упорядоченная смежность, это может быть самый простой способ сделать это.

Если это карта на основе тайлов, то каждая комната имеет фиксированную связь с соседними комнатами. Возможно, вам не нужно беспокоиться о координатах (хотя это может быть проще, если плитки квадратные), но вам нужно будет беспокоиться о направлениях.

Если плитки имеют квадратную форму, вам могут понадобиться кардинальные направления (n, s, e, w). Если это шестнадцатеричные плитки, вы можете пронумеровать свои выходы 1-6 (возможно, со статическими конечными константами). Тогда каждый соседний тайл может быть связан с этим вместе с его выходом.

Как сказал Аарон , сначала необходимо решить, какими будут координаты отображения.

Но вы не ограничены системой координат X-Y-Z. Например, каждая плитка может быть связана с любой другой плиткой на вашей карте. Все зависит от того, как вы хотите его построить.

Вы говорите, что строите RPG-игру, и вам нужно хорошо видеть местность, окружающую вашего персонажа. Это многоуровневый? Как персонаж перемещается из одной плитки в другую? Это движение в одну сторону?

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

Вы должны спланировать это очень хорошо, прежде чем начинать кодирование.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top