Как создать карту на Java?
Я пытаюсь завершить 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 класса, расширяющих ее). Я до сих пор не имею ни малейшего представления о том, как собрать и сгенерировать карта.
Спасибо, что уделили мне время.
8 ответов:
Не начинайте с реализации, начните с того, как вы хотели бы использовать карту. Это даст вам некоторые ограничения, как его реализовать. Например:
Когда вы рисуете карту, как вы получаете к ней доступ? По координатам? Или "идите на запад от плитки X"?
[EDIT] предлагаю начать с основного цикла игры RPG. Вам нужно будет разместить символ / маркер где-то (т. е. ему нужно какое-то отношение к плитке).
Затем вам нужно переместить символ. Персонаж должен иметь возможность изучить текущую плитку (противников, предметы, тип). Ему нужен способ узнать, как он может двигаться (например, есть ли стена справа?)
Это дает вам интерфейс для вашей карты: услуги, которые она предоставляет для других объектов в игре. Когда у вас есть представление о том, что должен обеспечить интерфейс, это должно дать вам представление о том, как реализовать карту (структуру данных).
Что касается генерации карты, используйте генератор случайных чисел плюс некоторый "здравый смысл". Взгляните на эту картину. соседние плитки: когда они все городские, эта плитка, вероятно, тоже городская. То же самое и с равнинами. Холмы-это единичные объекты, и они встречаются реже всего.
Запустите этот код, распечатайте карту в виде ASCII ("C"ity, "P"lain, "H"ill), чтобы увидеть, работает ли он.
Чтобы создать такую карту без использования матрицы, я рекомендую начать с центральной плитки,а затем заполнить карту снаружи, используя модифицированный алгоритм поиска по ширине. Прежде всего, нам нужно что-то немного лучше, чем список соседних плиток. Вы можете просто иметь четыре переменные, по одной для каждого направления, в котором хранится следующая плитка, как таковая:
Предположим, мы начнем с самой центральной плитки. Все, что вам нужно сделать сейчас, это выяснить, сколько направлений являются нулевыми, и создайте новый объект Tablellone для каждого направления, убедившись, что вы задали каждую из переменных в этом текущем объекте и задали соответствующую противоположную переменную в созданном объекте.private Tabellone up = null; private Tabellone down = null; private Tabellone left = null; private Tabellone right = null;После того, как вы заполнили все направления на этой плитке, вы выбираете одну из других плиток, которые вы создали, и выполняете ту же операцию. Именно здесь появляется алгоритм поиска по ширине. Вы можете использовать очередь, чтобы пройти через каждую плитку, которую вы создали,и заполнить направления. Чтобы остановить алгоритм, просто установите ограничение на количество плиток, которые вы хотите создать, и используйте счетчик, чтобы отслеживать, сколько их было создано.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";Это уровень игры. За исключением пробела, там пять символов. Хэш ( # ) означает стену. Доллар ( $ ) представляет собой коробку для перемещения. Точка (.) символ обозначает место, куда мы должны переместить коробку. Символ at ( @ ) - это сокобан. И, наконец, символ новой строки (\n) начинает новую строку мира.
Является ли скорость или память огромной проблемой для этого проекта? Если нет, то почему бы вам не использовать 2d массив?
Что-то вроде
Casella map [][] = new Casella[xSize][ySize];Отсюда его легко концептуализировать, просто представьте его в виде таблицы excel, где каждая ячейка представляет собой плитку на карте.
Путь, которым вы идете, прекрасен, хотя иногда его немного трудно осмыслить. У вас есть список соседних плиток. Итак, создавая свою карту, вы начинаете где-то, возможно, сверху слева, и идете оттуда.
Ты можно использовать вложенные циклы for для настройки карты и определения граничных элементов.
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 плиток и не имеющая упорядоченной смежности, лучше всего использовать нематричное решение, общее решение состоит в том, чтобы просто смоделировать ее как граф, используя либо список смежности для несимметричной смежности, либо список инцидентности для симметричной смежности. Если вы используете список инцидентов, вам нужен объект edge, содержащий вершины ребро соединяется, если вы используете список смежности A multimap может быть круто использовать.
Если вы хотите нематричное решение с упорядоченной смежностью, у Альбертопля есть решение для этого.
Предполагая, что у вас есть карта, которая имеет X плиток в ширину и Y плиток в высоту, а плитки, которые находятся рядом друг с другом, смежны, так что каждая плитка имеет максимум 4 и минимум 2 смежных плитки, вы можете использовать матрицу для доступа к плиткам, а также представлять смежность по матричной смежности. То идея заключается в том, что карта[Y][X] соседствует с картой[Y+1][X] и картой[Y][X+1] и обратно. Это решение также может соответствовать максимальному 6 и минимальному 3 смежности плитки, Если плитка [Y+1] [X+1] смежна с плиткой[Y] [X]. Плюс к этому заключается в том, что вы можете легко разобрать карту, и поскольку она имеет 2 измерения, ее естественно моделировать так. Недостатком является то, что как только плитка установлена, вы не можете изменить ее смежность без изменения матрицы. Поскольку это не то, что вы предлагали профессору, вы можете не хотеть этого делать, но если у вас есть (статический) упорядоченная смежность это может быть самый простой способ сделать это.
Я справился с этим, используя списки смежности. Каждая ячейка будет иметь ArrayList, содержащий индексы соседних ячеек. Эти индексы-те, которые упомянутая ячейка имеет в списке ArrayList карт ячеек.
Если это карта на основе плиток, то каждая комната имеет фиксированную связь с соседними комнатами. Возможно, Вам не нужно беспокоиться о координатах (хотя это может быть проще, если плитки квадратные), но вам нужно будет беспокоиться о направлениях.
Если плитки квадратные, направления сторон света (n, s, e, w) могут быть всем, о чем вам нужно заботиться. Если это шестигранные плитки, вы можете пронумеровать свои выходы 1-6 (возможно, со статическими конечными константами). Тогда каждая соседняя плитка может быть связана с этой вместе с его выход.
Как сказал Аарон, вам нужно сначала решить, как будут отображаться координаты.
Но вы не ограничены системой координат X-Y-Z. Например, каждая плитка может быть связана с любой другой плиткой на вашей карте. Все зависит от того, как вы хотите его построить.Вы говорите, что создаете RPG-игру, тогда вам нужно иметь хороший обзор местности, окружающей вашего персонажа. Она многоуровневая? Как персонаж перемещается с одной плитки на другую? Есть ли движение в одну сторону?
Есть, буквально, десятки вопросов, которые нужно задать при разработке карты для игры.
Вы должны очень хорошо спланировать его, прежде чем начать кодирование.
Comments