Створіть рівні регіони на шістнадцятковій карті


13

Беручи для прикладу велику (X на Y) шестигранну карту, як я можу поділити її на N областей з’єднаних шестигранників, щоб імітувати країни?

Мета - генерувати шістнадцяткову карту, схожу на карту реального життя із країнами різної форми, але однакових розмірів.

Відповіді:


13

Ви спробували Алгоритм Ллойда ? Процедура досить проста і призведе до отримання досить регулярних регіонів (залежно від кількості запущених ітерацій).

  1. Почніть плиткою карти порожніми шестигранниками.
  2. Вибирайте N шестигрань навмання Вони представлятимуть «центр масовості» для кожної країни.
  3. Позначте кожну шістнадцятку шістнадцятковою центральною шістнадцяткою ( діаграма Вороного ). Країна я є безліч всіх прокльонів , найбільш близьких до i - го центру гекса.
  4. Обчисліть новий центр мас для кожної країни.
  5. Повторіть кроки 3 і 4 стільки разів, скільки потрібно згладити створені регіони.

Вам не доведеться запускати його дуже довго, щоб створити приємну вигляд карти. Цей приклад вимагав лише трьох ітерацій.


Дуже приємно, і +1 за те, що я маю приклад особливо, але я б трохи хвилювався, що це трохи надто регулярно! Однак, результати справді виглядають чудово, особливо в таких масштабах, і це також чудовий спосіб висіву інших методів.
Стівен Стадницький

1
Мій приклад надихнув публікацію в блозі про генерацію полігонових карт . Автор додав шум до країв кожної області, щоб зробити більш нерівний вигляд (прокрутіть донизу, щоб побачити це). Вам потрібно буде використовувати набагато більше шістнадцяткових значень, ніж я, щоб зробити це життєздатним варіантом, але це, безумовно, можливо.
Майкл Кристофік

3

Один простий спосіб ви можете спробувати.

  1. Випадково виберіть nшестигранників. Кожен з них розпочне групу.
  2. Для кожної групи спробуйте розгорнути початковий шестигранник у випадковому напрямку.
  3. Якщо всі шестигранники навколо вибраного шестигранника зайняті, позначте як прослуховування, змініть шестигранник.
  4. Повторіть, поки кожна група не набере 20 шістнадцяткових знаків або не буде більше місця для розширення (усі шістнадцяткові кнопки).

Я не тестував, але це повинно створити острови і дещо уникати довгих тонких брекетів. Також, швидше за все, будуть межі сусідів, але необов'язково кожен з них матиме зв'язок з іншими, що щільність буде залежати від значення n.
Деякі групи також можуть бути прикуті до інших і досягають розміру менше 20, ви можете забезпечити вирощений простір, нерестуючи стартові шестигранники на мінімальній відстані один від одного.
Тестуйте і підкручуйте за потребою.


Крім того, не пов’язану з цією проблемою, але дуже, дуже корисно працювати з шестигранниками, відвідайте цю сторінку: http://www.redblobgames.com/grids/hexagons/#basics
Вона об'єднує цілу купу шістнадцяткових відомостей в одному місці з приємний візуальний.


Мабуть, мабуть, слід включити механіку для групи А, щоб надати вузли групі B, якщо група B межує з групою A і не має куди більше йти. Поки група А має порожній простір для розширення, щоб замінити втрачені вузли. Тоді не має значення, з чого вони почали. Оскільки це діє на зразок "відступу".
MichaelHouse

Я думаю, що, можливо, започаткую країну, спершу сформуй кутові групи, потім ті крайові дали б те, що я хочу. Я спробую це, коли повернусь додому.
MadCatPT

@ Byte56 Так, я насправді щось подібне подумав під час обіду. Якщо кутову групу ніде не виросло, вона просто взяла шестигранник іншої групи і нехай ця група знайде порожнє місце при наступній ітерації. Це повинно мати певну гарантію, щоб уникнути 2 кутових груп, які нескінченно знущаються одна над одною.
петерваз

Реальні країни часто мають межі річок чи гір. Коли ви розширюєтесь у випадковому напрямку, ви можете спробувати зменшити ймовірність розширення, якщо наступний шестигранник буде з іншого боку річки чи гірського хребта.
amitp

@amitp Якби ОП очікувала врахування цих факторів, він, мабуть, зазначив би їх. Я не припускаю, просто працюю всередині оригінальних приміщень.
петерваз

2

Я безумовно думаю, що деякий тип структури графіків зробив би це можливим. В основному створіть край між двома шестигранними вузлами, якщо вони знаходяться поруч один з одним, щоб імітувати всю карту. Однак я не впевнений у точному алгоритмі створення "країни" на цій карті. Річ у тому, що залежно від того, як ви хочете, щоб країна "виглядала", вам знадобляться різні алгоритми.

Я б рекомендував вибрати крапку і виїхати звідти назовні, вибравши випадкову плитку у вашій "країні, що росте", яка має сусідню плитку, яка не входить до країни.

Для вимкнення алгоритмів може використовуватися шаблон стратегії залежно від типу країни, який ви хочете. http://en.wikipedia.org/wiki/Strategy_pattern тобто ви хочете струнку країну узбережжя, як чилі? Або ви хочете чогось більш круглого і вміщеного?

Властивості графіків можуть також дозволяти налаштувати, як виглядає кінець "країни": http://en.wikipedia.org/wiki/Eccentricity_(graph_theory)

Хочете велику країну? Налаштуйте властивості графіка та змушуйте генеровану країну (яка є лише графіком) мати властивості, які надають їй "вигляд", який ви хочете.

І останнє, але не менш важливе, графіки також будуть дуже корисними для визначення меж між країнами. Ви можете побудувати графік, який має зв'язок між двома вузлами, якщо країни межують між собою. Це може бути корисним для певного типу розділів у вашій грі і дозволить вам, можливо, оптимізувати певні речі в подальшому розвитку.


2

Одне невелике зауваження: ви говорите: "виглядає як карта реального життя із країнами різної форми, але однакових розмірів), але" реальні "країни сильно відрізняються за розмірами навіть у певних регіонах - навіть" великі "країни Європи можуть сильно відрізнятися, наприклад, Франція більше ніж удвічі більша, ніж Італія. Зважаючи на це, очевидно, що є геймплейні регіони, щоб спробувати зберегти розміри приблизно однакові - просто пам’ятайте, що невелика варіація тут, мабуть, хороша річ!

Моїм початковим підходом до проблеми було б "еволюціонувати" (а не "рости") ваші регіони:

  • Почніть з конкретного поділу карти на приблизно однакові за розміром шматки прямими лініями (наприклад, якщо ви хотіли 6 країн, то ви можете розділити карту на три горизонтальні фрагменти, а потім розділити кожен з цих фрагментів "по діагоналі" на дві частини). Це, очевидно, легко зробити програмно, тим більше, що це не повинно бути дуже точним (адже, мабуть, це не повинно бути дуже точним).
  • Зробіть початковий перехід на поділ, будуючи структуру даних "кордону": набір шестигранників, які мають сусіда, який зараз належить до іншої країни. Це також вдалий час для підрахунку кількості гекса в кожній країні.

Тепер, наскільки ви хочете, запустіть такий псевдокод:

Pick a random hex A from the boundary list;
Pick a random neighbor B of this hex from a different country;
if (A's country has more hexes than B's country has) {
  change hex A to belong to B's country;
} else if (B's country has more hexes than A's country has) {
  change hex B to belong to A's country;
} else {
  flip a coin to decide which to change;
}
if ( the changed hex's old country has become disconnected ) {
  undo and reject this move;
} else {
  update the boundary list around the changed hex and its neighbors;
}

Це дозволить підтримувати приблизний баланс між розмірами будь-яких двох сусідніх країн, а "відключена" перевірка (що можна зробити за допомогою простого алгоритму заповнення заливів) гарантує, що жодна країна ніколи не розпадається на частини. Оновлення списку кордонів - це операція постійного часу - змінений шестигранник, очевидно, завжди залишатиметься на кордоні, і ви можете просто перевірити його шість сусідів, щоб побачити, чи хтось із них став або прикордонною коміркою (тому що його сусід зараз у інша країна) або перестала бути прикордонною коміркою (оскільки її сусід зараз знаходиться в тій же країні), змінюючи встановлений кордон у міру необхідності.

Для вдосконалення цього підходу ви навіть можете зробити умову, при якій шістнадцятковий змінить трохи рандомізований варіант - замість того, щоб завжди «врівноважувати» дві країни, ви завжди можете робити своп з певною вірогідністю і навіть поступово зменшувати цю ймовірність над час (подібний до процесу охолодження в алгоритмі імітаційного відпалу ), щоб почати змушувати їх бути приблизно однакового розміру.

Зверніть увагу, що це не гарантує, що всі області точно однакового розміру (що неможливо, якщо N все одно не розділяє розмір вашої сітки), і навіть не гарантуватиме, що всі країни знаходяться в межах однієї шестигранної частини один одного в районі; він повинен гарантувати (запускати достатньо ітерацій), що кожна країна не більше ніж на один шестигранник більша або менша, ніж кожен з її безпосередніх сусідів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.