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?
c++
voxels
minecraft-modding
data
danijar
źródło
źródło
Odpowiedzi:
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.
źródło
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
źródło
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.
źródło