Jak radzić sobie z Block World, takim jak Minecraft

9

Chcę napisać prostą grę ze światem bloków, jak w Minecraft. Moje teoretyczne pytanie brzmi: jaki jest najlepszy sposób obsługi tych informacji blokowych podczas gry. Moim pierwszym pomysłem była ogromna tablica, ale myślę, że spowoduje to brak pamięci. Może muszę tylko ładować bloki w pobliżu odtwarzacza.

Jak poradzić sobie z ładowaniem potrzebnych informacji o blokach z pliku i przechowywanie tylko tych potrzebnych w pamięci?

danijar
źródło
2
Minecraft ładuje świat w dość duże kostki zwane kawałkami, nie wszystkie naraz. Nie jestem pewien dokładnych szczegółów. Źródło Minecraft jest dość łatwe do zdobycia, jeśli chcesz zobaczyć, jak to minęło.
ratbum
Spójrz na wiki Minecraft: minecraftwiki.net/wiki/Chunk
tom van green
Wiedziałem już o kawałkach w Minecraft, ale i tak dziękuję.
danijar
To złożone pytanie jest nieodpowiednie dla zakresu tego bloga.

Odpowiedzi:

9

Istnieje kilka różnych sposobów przechowywania danych dla gry z blokami, takimi jak Minecraft.

Sposób, w jaki uważam, że robi to Minecraft, rozbija świat na kawałki 16x16x256. Kawałki wokół odtwarzacza są ładowane do pamięci, gdy gracz rozpoczyna grę, a następnie wątek tła ładuje się więcej, gdy spacerujesz. Oto wideo, które to pokazuje: http://www.youtube.com/watch?v=oR_ZdJH9eho .

Innym sposobem na to jest rozbicie świata na oktree. Michael Goodfellow napisał blog o implementacji świata kostki o tej strukturze danych: http://www.sea-of-memes.com/LetsCode1/LetsCode1.html . Octree jest fajny, ponieważ daje trochę wbudowanej kompresji, ale prawdopodobnie będzie nieco trudniej pracować z tablicą.

O zachowaniu „tylko tych potrzebnych w pamięci?” Jest to trochę trudniejsze, ponieważ musisz zapytać, co jest „potrzebne”. Jeśli masz NPC, którzy mieszkają w innej części świata z AI, która wchodzi w interakcje ze środowiskiem, wtedy „potrzebujesz” dużo więcej świata, aby być w pamięci. Dane świata Voxel mogą być bardzo duże bardzo szybko, dlatego najlepiej jest zachować jak najmniejszą ilość pamięci. (IE, w pobliżu odtwarzacza są tylko postacie niezależne).

Silnik graficzny będzie „potrzebował” każdego bloku, który nie jest całkowicie otoczony innymi nieprzezroczystymi blokami. Zwykłym sposobem renderowania świata jest zbudowanie pojedynczej siatki, która zawiera wierzchołki dla każdego widocznego bloku. Rysowanie jest znacznie szybsze, ponieważ wykonujesz tylko 1 wywołanie metod losowania dla 65 536 bloków (w kawałkach wielkości Minecraft). Ponieważ silnik graficzny będzie musiał zbudować tę siatkę, zazwyczaj musi znać wszystkie kostki w porcji. Zauważ, że właśnie dlatego, gdy patrzysz przez podłogę w Minecraft, duża część świata jest niewidoczna. Jest tak, ponieważ każdy blok otoczony ze wszystkich sześciu stron jest pomijany. Wierzę, że Minecraft zmniejsza również liczbę wierzchołków, łącząc poziome boki tego samego rodzaju tekstury w jednym polu z powtarzającą się teksturą.

Moja rada to pójść z kawałkami 16x16x256. Przechowuj je w tablicy, ponieważ będziesz potrzebować szybkiej iteracji i edycji ze względu na budowanie siatki i logiki gry (wykrywanie kolizji, dodawanie / usuwanie bloków itp.). Następnie załaduj jak najwięcej kawałków w kręgu wokół gracza. Skaluj liczbę porcji w górę lub w dół, aby uzyskać lepsze lub gorsze komputery.

Ładowanie fragmentów będzie ogromnym hitem dla wydajności, więc umieść je w wątku, który biegnie z czasem. Zrób to, abyś mógł całkowicie załadować 3 nowe fragmenty w czasie, gdy gracz musi przejść od jednego końca fragmentu do drugiego.

Thomas Marnell
źródło
Dziękuję Ci! W AI nie ma nic, ponieważ piszę klienta do gry MMO. Obliczanie NPC odbywa się przez serwer. Jedno uzupełnienie: silnik graficzny nie wymaga „każdego bloku, który nie jest całkowicie otoczony innymi nieprzezroczystymi blokami”. Jeśli są jaskinie, gracz nie widzi, że są nieważne. ;-)
danijar
2
O jaskiniach, których gracz nie widzi ... Myślę, że używa mniejszej mocy, aby tylko narysować jaskinie, niż ustalić, czy jaskinia została całkowicie zablokowana. A jeśli nie narysujesz jaskiń, to jeśli usuniesz blok, potencjalnie będziesz musiał ponownie wygenerować siatkę dla wielu fragmentów zamiast tylko jednego. Byłoby fajnie znaleźć sposób na wykluczenie jaskiń, po prostu nie mogę wymyślić sposobu, aby zrobić to skutecznie: D.
Thomas Marnell,
3

Może nie mam najlepszego sposobu na wyjaśnienie tego, ale spróbuję.

Myślę, że najlepszym sposobem na zrozumienie, jak zwiększyć efektywność, jest zrozumienie wokseli. Minecraft jest oparty na wokselach, używa po prostu kostek zamiast kulek itp.

Zasadniczo woksel jest kształtem 3D, który może mieć dynamicznie zmienianą objętość, a gdy głośność się zmienia, zmienia się również kształt. Chunk to zestaw wokseli o wymiarach X na X na X. Na przykład możesz mieć fragment, który ma woksele 16 x 16 x 16, a następnie możesz mieć liczbę X fragmentów. Będziesz miał ustawiony dystans, że jeśli gracz znajduje się dalej niż N od jakichkolwiek fragmentów, nie uwzględniaj ich w swoich obliczeniach. Jest to trochę podobne do odległości przycinania, ale musiałoby również obowiązywać dla każdego fragmentu. W ten sposób możesz mieć go tak, aby zawsze mógł znajdować się w centrum Chunk, powiedzmy, zestaw 3 x 3 kawałków.

Tak więc miałbyś klasę do obsługi poszczególnych wokseli. Nazwiemy to Voxel_cl. A potem miałbyś klasę do obsługi kawałków wokseli, o nazwie Chunk_cl. I wtedy miałbyś jakąś światowej klasy, która generuje wszystkie fragmenty, które generowałyby woksele, o nazwie World_cl.

Więc teraz zamiast ogromnej tablicy wszystkiego, miałbyś tablicę 9 kawałków w dowolnym momencie, aw klasie kawałków miałbyś tablicę 4096 wokseli.

Pamiętaj, że jest to dość proste wyjaśnienie. Obecnie pracuję nad czymś za pomocą wokseli, więc pomyślałem, że wrzucę swój wkład = -)

Aby uzyskać więcej informacji na temat wokseli, sprawdź http://en.wikipedia.org/wiki/Marching_cubes

Mungoid
źródło
3
Marching Cubes polega na wizualizacji wokseli. A Minecraft nawet tego nie używa; po prostu rysuje kostki, a dokładnie o to nie chodzi w Marching Cubes .
Nicol Bolas
Dziękuję za wyjaśnienie! Nigdy wcześniej nie słyszałem o Voxels i wydaje się to bardzo ważne dla mojego projektu. Ale mam teraz pytanie.
danijar
Rozumiem tworzenie tablicy bliskich fragmentów, w której każdy element zawiera tablicę wokseli tego fragmentu. Ale potem muszę poradzić sobie ze zmianą porcji, gdy gracz porusza się po świecie. Czy muszę odczytać potrzebne fragmenty z pliku składowania? Czy jest dobry sposób na zachowanie ich w pamięci?
danijar
2
@danijar Po prostu kilka ciekawostek, piksel jest skrótem od „elementu obrazu”, woksel powstaje w ten sam sposób z „elementu objętości”. Nie, żeby to miało znaczenie, ale skoro nie słyszałeś pojęcia woksel, zanim pomyślałem, że może cię to zainteresować.
Daniel Carlsson
1

Możesz spróbować po prostu renderować widoczne powierzchnie, komputer obsługuje dane bloków w tle, a renderer działa tylko z tym, co widzisz. Porcje 8x8 byłyby łatwiejsze w obsłudze.

Gandalf
źródło