Jaki jest dobry płaski format pliku do przechowywania mapy kafelków 2D, która może rosnąć nieskończenie w dowolnym kierunku?

9

Tworzę prosty silnik map, który będzie automatycznie rozszerzany w dowolnym kierunku z treściami generowanymi proceduralnie w razie potrzeby.

Jaki jest dobry sposób na przechowywanie danych mapy zakotwiczonych na początku 0,0, aby prostokątny podzbiór danych mapy mógł być ładowany szybko i skutecznie z dowolnego punktu na mapie?

Mam pomysł, że może powinienem podzielić mapę na odrębne sektory, a następnie użyć jakiegoś formatu nagłówka, aby określić, gdzie w pliku jest zapisany określony sektor. Czy to dobra technika, czy są lepsze, bardziej wydajne techniki, na które mogę spojrzeć?

Nathan Ridley
źródło

Odpowiedzi:

7

Odradzałbym używanie jednego płaskiego pliku dla teoretycznie nieskończonych ilości danych.

Jeśli masz teoretycznie nieskończoną ilość danych, potrzebujesz dostępu losowego , co oznacza wiele plików lub bazy danych - lub indeksowanego formatu plików płaskich, który obejmuje ponowne rozwiązanie problemów z indeksowaniem już rozwiązanych przez systemy plików lub bazę danych.

Jeśli rozłożysz swoje fragmenty na wiele plików, uzyskanie fragmentu na (-110, 5000) to tylko kwestia powiedzenia „% APPDATA% / game / map / -110 / 5000.dat” (lub innej nazwy pliku, jeśli chcesz zacznij je kompresować). Bazy danych potrzebują tylko zapytania. Jeśli fragment nie ma żadnych danych, po prostu nie możesz nic przechowywać. Pojedynczy płaski plik nie zapewnia szybkości i wygody losowego dostępu od samego początku.

W jednym pliku o dowolnym rozmiarze, aby uzyskać szybki dostęp losowy, musisz mieć gwarancję położenia dowolnego fragmentu danych, co oznacza użycie indeksu (ponieważ surowe wyszukiwanie binarne przez fragmenty danych obniża wydajność i tworzy siatkę w twoim plik z „pustymi” punktami daje problem Byte56 ). Po opracowaniu systemu indeksowania, poprawieniu wydajności i napisaniu interfejsu API odtworzono coś w rodzaju systemu plików lub bazy danych. Chyba że faktycznie coś zyskasz, prawdopodobnie nie jest to warte inwestycji. Na przykład, Steam czerpie ogromne korzyści ze swoich formatów plików GCF / NCF.

Jeśli chcesz trochę zabezpieczyć swoje zapisy, nadal możesz to zrobić. Na przykład możesz zaszyfrować każdy pojedynczy fragment. Aby zapobiec ich usunięciu, możesz mieć centralny skrót oparty na istniejących zapisanych danych. Jeśli zapisane dane nie pasują do wartości skrótu (a program nie spowodował zmiany), fragment został usunięty.

doppelgreener
źródło
4

Najczęściej stosowanym rozwiązaniem jest podział na wiele plików, jednak twoje pytanie oznacza tylko jeden plik. Jedyną sensowną opcją (moim zdaniem) jest emulacja bardzo prostego systemu plików w tym pojedynczym pliku. Nie jest to naprawdę trudne, ale naprawdę powinieneś rozważyć użycie wielu plików, jeśli możesz.

Jeśli musisz trzymać się jednego pliku, możesz znaleźć inspirację dla swojej implementacji z ext2 fs. http://en.wikipedia.org/wiki/Ext2 Wiem, że pomogło mi to w podjęciu dobrych decyzji, kiedy musiałem wdrożyć prosty FS dla gry.

Ale tak naprawdę w przypadku każdej rosnącej mapy zwykle lepiej jest po prostu użyć pliku dla każdego „dostępnego” fragmentu.

Richard Fabian
źródło
4

Wdrożyłem system dzielenia dla mojej gry, gdy majstrowałem przy nieskończonych światach (nie jestem pewien, czy je zatrzymam, czy nie). W celu użycia z jednym plikiem, najpierw użyłem pozycji świata fragmentu, aby obliczyć przesunięcie bajtu do pliku. Zakłada to statyczny rozmiar porcji lub przynajmniej statyczny maksymalny. Jeśli jednak użytkownik miałby na chwilę ruszyć w jednym kierunku, ten plik stałby się bardzo rzadki ze względu na swój rozmiar, ponieważ istniały duże obszary lądu, które nie zostały jeszcze wygenerowane, więc w pliku były puste miejsca.

Próbowałem także dwóch systemów plików. Jeden plik zawiera mapę par „pozycja fragmentu” na „przesunięcie pliku fragmentu”. Drugi zawiera wszystkie części. Gdy generowany jest nowy fragment, po prostu idzie na koniec pliku fragmentu, a jego przesunięcie jest przechowywane w pliku position-> offset. Ten problem występował, gdy miałeś DUŻO kawałków i znalezienie przesunięcia w pliku pozycja-> przesunięcie zajęło trochę czasu. Jeśli uznasz, że jest to wykonalne, możesz załadować dane pozycji> przesunięcia do mapy mieszania podczas ładowania, aby mieć szybki dostęp.

Na razie korzystam z drugiej opcji, ale mogę przejść na coś innego, jeśli stwierdzę, że brakuje wydajności. Może dzięki tym informacjom będziesz w stanie stworzyć coś, co Ci odpowiada. Powodzenia!

MichaelHouse
źródło
Proponuję zajrzeć do sqlite sqlite.org . Jest bardzo samodzielny, indeksowany, obsługuje obiekty BLOB itp. Pomogłoby to w wydajności i usunął „dziury” w pliku.
Daniel Blezek