Aby najpierw krótko odpowiedzieć na główne pytanie, głównymi zaletami proceduralnie generowanego świata gier są:
Świat może być ogromny , znacznie większy niż jakikolwiek ręcznie zaprojektowany świat gry.
Świat (lub przynajmniej jego części) można regenerować dla każdej gry, potencjalnie zwiększając wartość powtórki, ponieważ gracz zawsze będzie miał coś nowego do odkrycia.
Natomiast główne wady generowania procedur są następujące:
W zależności od zastosowanych metod generowania, może być trudno upewnić się, że świat jest zawsze możliwy do gry, tzn. Że gracz nie może utknąć bez możliwości kontynuacji tylko dlatego, że ma pecha z generacją świata.
Nawet jeśli możesz uniknąć generowania całkowicie niemożliwych do grania światów, losowe generowanie światów może prowadzić do bardzo zróżnicowanego poziomu trudności: czasami gracz może znaleźć wszystko, czego potrzebuje, wygodnie w kolejce do podjęcia, czasem może trwać długo, nie znajdując nic przydatnego .
W dłuższych okresach takie losowe fluktuacje zwykle się zmniejszają, ale jeśli trudność gry jest na przykład bardzo obciążona z przodu (typowa dla gier survivalowych), zły początek może zepsuć grę, podczas gdy bardzo szczęśliwy start może pozbawić ją wszystkich wyzwań.
Źle wykonane generowanie procedur może sprawić, że świat będzie monotonne i nudny: po obejrzeniu tuzina losowo wygenerowanych labiryntów wszystkie wyglądają tak samo, nawet jeśli różnią się szczegółami.
Ponadto, jeśli świat gry zostanie całkowicie zregenerowany dla każdej gry, nie będzie żadnych ustalonych lokalizacji ani funkcji, które gracz mógłby rozpoznać z poprzednich gier. Taki brak znajomości może utrudnić graczowi zaangażowanie się w grę na poziomie emocjonalnym lub wymianę doświadczeń z innymi graczami.
Istnieje również jedna rzecz, którą można liczyć na obu listach: w grze, w której świat jest losowo regenerowany dla każdej gry, nie może istnieć coś takiego jak „przewodnik”, ponieważ każda rozgrywka będzie inna.
(Ta niepowtarzalność może również stanowić problem przy testowaniu i debugowaniu, chociaż można jej przynajmniej częściowo uniknąć, umożliwiając określenie zarodka RNG, przynajmniej w trybie debugowania, i / lub udostępniając polecenie „oszukiwania”, które można wykorzystać do szybkie przewijanie do różnych etapów).
Jeśli jednak spojrzeć na listę wad, zobaczysz, że to głównie opisuje wady czystego pokolenia procesowego; wielu z nich można uniknąć, łącząc zawartość ręcznie i proceduralnie .
Na przykład, gracz zawsze może zacząć w ustalonym, ręcznie zaprojektowanym mieście, być może otoczonym szerszym mniej lub bardziej stałym regionem macierzystym, ale miejsca znajdujące się dalej od miasta można generować losowo, aby zawsze zapewniać nieznane regiony do eksploracji.
Mogą też znajdować się losowo inne ręcznie zaprojektowane miasta lub inne lokalizacje (mniej lub bardziej) na świecie, tak że gracz będzie musiał je znaleźć, ale będzie wiedział, czego się spodziewać, kiedy tam dotrze. I odwrotnie, wyróżniające się cechy, takie jak góry, można umieszczać ręcznie (przynajmniej w pobliżu stałej lokalizacji początkowej), ale szczegóły dotyczące ich terenu można losowo dobierać.
Jeśli chodzi o losowe umieszczanie powodujące zakleszczenia i zmienność trudności, można temu zaradzić, wdrażając różne kontrole spójności i równowagi nad algorytmem generowania proceduralnych światów. Na przykład, jeśli gracz potrzebuje określonego przedmiotu, aby móc przekroczyć wodę, możesz dołączyć kod, który upewnia się, że co najmniej jeden taki przedmiot jest umieszczony, aby gracz mógł do niego dotrzeć bez przekraczania wody.
Podobnie, możesz również ulepszyć swoje zasady rozmieszczania przedmiotów, aby żadne różdżki budzące równowagę nie zostały umieszczone, zanim gracz osiągnie poziom x , i być może, aby zapewnić, że co najmniej jedna zostanie umieszczona w stałym miejscu, w którym gracz może osiągnąć zanim dotrą do etapu, w którym będą go potrzebować, aby przetrwać.
Nawiasem mówiąc, powszechnym sposobem na mniej lub bardziej płynne tworzenie proceduralnych i ręcznie generowanych siatek treści jest rozpoczęcie procesu generowania ręcznego za pomocą generatora proceduralnego świata (być może odpowiednio zmodyfikowanego, np. W celu wygenerowania wioski lub szczytu górskiego, gdzie chcesz. ), aby zainicjować projektowany region, a następnie ręcznie go dostosować, aby dodać i dostosować wybrane szczegóły. (Może to również pozwolić na bardzo kompaktowe przechowywanie na poziomie, poprzez zapisanie jedynie ręcznych zmian oraz parametrów wyjściowych generatora i zastosowanych parametrów).
Inne sposoby łączenia treści ręcznych i proceduralnych obejmują pozostawienie pustych miejsc na ręcznie zaprojektowanych poziomach, które zostaną wypełnione losowymi treściami (np. Zamek może zawierać losowo wygenerowany labirynt w lochach, z ustalonym tylko konturem i wyjściami), lub projekt ręczny może określać jedynie ogólny zarys niektórych części poziomu (np. rozmieszczenie domów w mieście) i pozostawić szczegóły (takie jak dokładny wygląd każdego domu) do losowego wyboru.
W rzeczywistości nawet wiele gier, które mają całkowicie ustalony świat gry, wykorzystuje pewną formę generowania procedur w ramach procesu projektowania poziomów, ponieważ istnieją pewne aspekty generacji świata (takie jak tworzenie naturalnie wyglądającego terenu lub umieszczanie pojedynczych drzew w lesie) które są trudne i / lub żmudne do wykonania ręcznie, ale stosunkowo łatwe do zautomatyzowania.
I odwrotnie, większość proceduralnych generatorów światowych używa przynajmniej niektórych ręcznie zaprojektowanych obiektów i elementów do zbudowania świata. Można nawet mieć wiele poziomów zagnieżdżonego generowania losowego / ręcznego: na przykład świat generowany proceduralnie może obejmować miasto generowane ręcznie, otoczone lasami generowanymi proceduralnie z ręcznie rysowanym konturem, a drzewa generowane proceduralnie, z ręcznie zaprojektowanymi liśćmi.
Zauważ również, że generowanie treści proceduralnych niekoniecznie jest niezgodne ze stałym światem: możesz po prostu wybrać stałe źródło danych RNG i użyć go do wygenerowania swojego świata. Może to być przydatne, jeśli chcesz, aby gracze mogli odkrywać ogromny świat, ale chcesz, aby był taki sam dla każdej gry i każdego gracza.
Zauważ, że jeśli to zrobisz (a nawet jeśli nie zrobisz tego), naprawdę powinieneś zaprojektować swój generator światowy, aby działał w sposób hierarchiczny, używając wielu instancji RNG, takich jak np. Ogólny generator map zachowałby jedną instancję RNG którego użyłby do wygenerowania podregionów, przypisując do każdego podregionu inną wartość początkową, której generator regionu użyłby następnie do zainicjowania osobnej instancji RNG, której użyłby do wygenerowania regionu i tak dalej. Ma to na celu uniknięcie „efektu motyla”, polegającego na tym, że zmiana nawet najmniejszego szczegółu najmniejszej części mapy może zsynchronizować RNG i spowodować, że wszystko inne na świecie będzie zupełnie inne.
Innym ważnym sposobem na uniknięcie efektu motyla, szczególnie jeśli generujesz świat „w locie”, gdy gracz go eksploruje, jest całkowite unikanie normalnych RNG (z wyjątkiem procesów zachodzących „natychmiastowo” z punktu widzenia gracza, takich jak generowanie nowy poziom po wejściu do niego) i zamiast tego użyj metod generowania liczb losowych, które nie przechowują żadnego stanu wewnętrznego. Na przykład, wybierając ziarno dla podregionu, do którego gracz wkrótce wejdzie, generator światów ogólnych może wziąć współrzędne subregionu (i własne ogólne ziarno) i podać je do funkcji skrótu, aby wygenerować ziarno subregionu. W ten sposób każdy region zawsze będzie wyglądał tak samo, niezależnie od kolejności, w jakiej gracz do niego wejdzie.
Ps. Po tych wszystkich dygresjach pozwólcie mi krótko odpowiedzieć na wasze ostatnie pytanie dotyczące faktycznego kodu używanego do generowania procedur. Niestety, nie sądzę, że jest to naprawdę odpowiedzialne w jakimkolwiek sensownym sensie bez dużo bardziej szczegółowych szczegółów, niż podałeś, ponieważ istnieje dosłownie tyle różnych sposobów generowania proceduralnego świata, jak wiele gier z nich korzysta.
Na przykład pradziadek ze wszystkich generowanych proceduralnie gier eksploracyjnych to prawdopodobnie Łotrzyk , którego algorytm generowania poziomów polegał po prostu na losowym umieszczeniu wiązki prostokątnych pomieszczeń na większym prostokątnym poziomie i połączeniu tych pomieszczeń przejściami (i umieszczeniu schodów następny poziom na jednym z nich). Jego różnorodni następcy , od Nethacka po serię Diablo , opracowali ten system na wiele sposobów, ale większość zachowała podstawową ideę odrębnych poziomów składających się z pokoi, lochów i labiryntów, mniej lub bardziej losowo umieszczanych na mapie siatki.
I odwrotnie, w przypadku gier z otwartymi ustawieniami na zewnątrz, prawdopodobnie będziesz chciał zacząć od pewnego rodzaju algorytmu generowania fraktalnego terenu i zbudować inne funkcje (rzeki, lasy, miasta itp.). Lub możesz zrobić coś takiego, jak robi Minecraft i wygenerować losową teksturę proceduralną 3D , określającą, które części twojego krajobrazu są odpowiednio ziemią i powietrzem (skalowane i stronnicze, aby bardziej prawdopodobne było zmielenie niższych bloków), a następnie nałożyć elementy takie jak woda , gleba / skała, roślinność itp. na nim.
Oczywiście żadne z powyższych nie ma zastosowania, jeśli, powiedzmy, piszesz grę polegającą na eksploracji kosmosu , w takim przypadku musisz wygenerować wiązkę losowo rozmieszczonych układów gwiezdnych zgodnie z pewną funkcją gęstości, a następnie wygenerować losową zestaw gwiazd i planet w każdej z nich. A może ustawiasz graczy do eksploracji nieeukucydańskiego krajobrazu , w którym to przypadku staniesz przed zupełnie innym zestawem wyzwań (takich jak fakt, że głośność w danym promieniu rośnie wykładniczo, a nie wielomianowo, czyniąc ją naprawdę trudno zachować dużą mapę w pamięci).