Процедурне генерування будівлі певної площі


15

Я та команда працюють над грою на заводі будівельника, яка дає гравцеві випадкову фабрику на початку гри. Щоб спробувати переконатися, що існує відчуття «справедливості», в ідеалі фабрика, що генерується випадковим чином, мала б площу в межах кількох одиниць (значення заповнювача) 30.

Написати базовий генератор випадкових прямокутників досить просто, щоб відповідати цим характеристикам, але наша мета - фабрика бути складнішою, можливо, складеною з 2, 3 або навіть 4 прямокутників, що перетинаються, створюючи більш складні форми (подумайте про L, Будинки у формі U та O).

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

Ще кілька релевантних відомостей: 2D зверху вниз Деякі механізми мають факторний стиль, тому кімнати повинні мати розумну довжину та ширину, щоб звільнити місця для машин Зараз в Яві та Луї (можна використовувати вбудовані бібліотеки з будь-якої необхідності)

Спасибі заздалегідь!

EDIT: Коли я кажу "хороший" або "поганий" вихід, поганим результатом буде будь-який вихід, у якому простір не використовується. Заводські обмеження форми, де гравець може розмістити заводські машини, такі як конвеєрні стрічки. В ідеалі на фабриці не повинно бути ділянок, шириною яких є лише 1-2 блоки, форма не повинна бути одним або двома великими прямокутниками з лінією з 1-2 блоків, що «висить» на одну сторону. Хорошим результатом було б те, коли весь простір підлоги "працездатний", тому всі області шириною принаймні 3-4 блоки. Хороший вихід не завжди повинен бути складним (1 або 2 прямокутники добре), але він повинен мати неабиякі шанси, якщо він складається з більш ніж 1-2 прямокутників.

Відповіді:


7

Ви можете використовувати попередньо сформовані поліоміно як мета форми для побудови асортименту будівель.

Скажімо, ваша мінімальна прийнятна відстань - 3 блоки. Тоді найменша прийнятна будівельна одиниця, яку ми розглянемо, - це 3х3. Для зручності я зателефоную, що комірка & вона дає площу 9 блоків. Далі візьміть цільову початкову зону та розділіть її на область комірки. Використовуючи початкове значення, яке ви дали, ми отримуємо 3 333; тож 3 комірки дадуть вам трохи менше, ніж ви хочете, а 4 клітини дадуть вам більше.

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

Далі, випадковим чином виберіть поліоміно з потрібним числом клітин. Замініть кожен квадрат на поліоміно на будівельну клітинку, і ви маєте остаточну форму.

Для ілюстрації, скажімо, ми вирішили округлити. Ось усі поліоміно розміром 3 (не включаючи обертання / перевертання):

введіть тут опис зображення

Припустимо, ми випадковим чином вибираємо форму L і застосовуємо випадкове обертання, ваша будівля матиме такий макет:

введіть тут опис зображення

Пару питань. По-перше, існує обмеження кількості осередків, які ви можете використовувати. Вікіпедія дасть вам всі поліоміно розміром до 8 ( октоміно ). Він включає підсумкові дані до 12-ти розмірів, але я не знаю, чи є онлайн-список для всіх. По-друге, вищевказане рішення працює лише для розмірів будівель, кратних до 9. Є кілька способів вирішити деякі з цих питань:

1) Використовуйте інший розмір комірок. Наприклад, 3x4, 4x4 тощо.

2) Додайте додаткові клітини до вихідного полиомино. Це може бути складним, якщо ви повинні переконатися, що всі фігури однаково вірогідні, але шанси для більшості ігор для розробників ігор вам не потрібні по-справжньому рівномірного розподілу будівельних форм.

3) Відкладіть будівлю, щоб зробити її більшою. Повернувшись до прикладу, якщо ви використовували 3 комірки, ваша будівля мала б площу в 27 квадратів, що залишає вас коротким на 3. Потім можна сканувати периметр на предмет розташування, щоб склеїти розмір 1х3 групи квадратів. Поки ваша група макіяжу не менше AxB, де A принаймні ваша мінімально допустима відстань, ваш результат не порушить ваші мінімально допустимі обмеження на відстань. Створюючи приклад вище, ось ілюстрація можливого результату:

введіть тут опис зображення

4) Замість того, щоб вибивати занадто малу будівлю, ви можете обрізати занадто велику будівлю. Забезпечення дотримання мінімально допустимого обмеження відстані є складнішим, ніж варіант прокладки, але дасть вам більше альтернатив для розгляду.

Деякі інші коментарі:

Тільки тому, що ви могли використовувати всі можливі поліоміно заданого розміру, це не означає, що вам слід. Якщо деякі з них не розважають, порушуйте тему, ображають вашу аудиторію (свастичні зразки) або викликають якусь іншу проблему, вийміть їх. Крім того, ви можете зважити свою процедуру вибору, якщо деякі візерунки цікаві, але занадто дивні, щоб регулярно з'являтися. Нарешті, ви можете використовувати це рішення в поєднанні з вашою поточною стратегією. Можливо, 70% часу створюєш прямокутні будівлі та 30% часу використовуєш підхід поліоміно. Або, можливо, ви починаєте з прямокутної будівлі і склеюєте невелику полиомино ззовні.


16

Простий спосіб побудови генератора процедур:

  1. Випадково будуйте речі
  2. Запустіть функцію, яка перевіряє, чи хороший вихід
  3. Якщо результат не є хорошим, перейдіть до кроку 1

Навіть якщо для завершення потрібні тисячі пробіжок, більшість простих генераторів при такому підході отримують просто чудово. Перевага полягає в тому, що в генераторі не так багато розумних потреб, і оскільки перевірити, чи щось хороше, набагато простіше, ніж будувати те, що добре 100% часу, такий підхід дуже простий.

Ви перерахували деякі об'єктивні заходи щодо того, чи хороший результат; Цього повинно вистачити для створення швидкого та брудного генератора. Розмістіть прямокутники навмання всередині площі та відхиліть вихід, якщо, наприклад, є області, шириною лише 1-2 блоки.

Почніть з цього, вдосконаліть і оптимізуйте потім.


Дякую! Я пам’ятаю, що розглядав це, але думка про те, що є шанс на кілька секунд + час завантаження, зупинила мене. Зараз я усвідомлюю, наскільки цей шанс неймовірно малий. Мені доведеться спробувати це, але, можливо, я зачекаю, чи спочатку у когось є більш пряме рішення.
user2129189

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

3
Сам я не прихильник методів генерації відхилень та повторів. Вони досить швидкі, коли ваш генератор робить лише одну просту річ, але для ігрових рівнів ми зазвичай починаємо накладати більше функцій та кроки генерації, щоб зробити багатші карти. У цей момент ймовірність потрапляння на життєздатну карту є результатом ймовірності успіху кожного кроку, який може швидко скорочуватися. Це не просто академічне занепокоєння - я говорив із розробниками, яким довелося впровадити гарну / погану систему кешування насіння, щоб уникнути зайвих часів генерації, коли правильний генератор однопрохідного генератора був би простішим.
DMGregory

@DMGregory так, я точно можу це бачити. Основний випадковий генератор працював би як 99% часу протягом декількох проходів для мого випадку, але якщо я хочу додати більше складності пізніше, він може значно сповільнитись. Хто-небудь знає про будь-які реальні програми програмування / ігор програми здогадки та чекової моделі?
користувач2129189

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

7

Зважаючи на обмеження "всі області мають принаймні 3-4 блоки завширшки", перша ідея, яка стрибає мені на думку, - це щось на зразок наступного:

  1. виберіть один із 3x3, 3x4, 4x3 або 4x4
  2. розмістіть блок такого розміру в центрі сітки
  3. виберіть напрямок (вгору, вліво, вправо, вниз)
  4. спробуйте розмістити блок 3х3 поруч із раніше розміщеними блоками в цьому напрямку
  5. якщо вам вдасться, з деякою ймовірністю спробуйте розширити блок на блок 4x3 в одному з напрямків, які ви не просто вибрали
  6. з деякою ймовірністю пересуньте до випадкового краю заповнених блоками
  7. повторюйте кроки 3 - 6, поки площа не буде достатньо великою

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


4
Я б спростив речі, завжди починаючи з блоку 3x3, а потім додаючи 3x1 блоки у випадкових положеннях, де кожен квадрат є суміжним із існуючим. Додавши до блоку 3х3, є чотири можливі позиції. Усі дають вам блок 3x4, з шістьма можливими позиціями для наступного. Звідти стає складніше, але не так вже й погано.
JollyJoker

0

Подумайте про використання булевих NOT і UNION та вибір між ними випадковим чином.

  1. Помістіть випадковий прямокутник.
  2. Помістіть другий випадковий прямокутник.
  3. Випадково вибирайте, чи об’єднати їх, або ПІДТРИМАТИ другий з першого.
  4. Повторіть для ряду прямокутників. Хоча лише два-три можуть дати досить розумні результати.

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


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