Czy powinienem używać plików tekstowych do zapisywania danych?

22

Moje pytanie brzmi, czy powinienem używać plików tekstowych do zapisywania danych mojej gry. Mam kilka podstawowych obaw związanych z tym:

  1. Naprawdę nie ma sposobu na ochronę danych, a zatem użytkownik może spieprzyć wszystko, jeśli go dotknie, a ja nie chcę, aby tak się stało.

  2. To chyba nie jest najskuteczniejszy sposób przechowywania moich danych (będzie ich dużo)

Wiem jednak, jak skutecznie parsować / pisać do plików tekstowych, więc dla prototypowania były fantastyczne. Chcę tylko spojrzeć w przyszłość, na co powinienem pomyśleć o zmianie, aby nie uderzyło mnie to w twarz pod koniec rozwoju.

Jeśli nie powinienem używać plików tekstowych, czego powinienem używać? Potrzebuję czegoś kompatybilnego z C ++.

Althezel
źródło
2
Pliki zip (z hasłem) - dostępnych jest wiele bibliotek, które pozwolą ci to zrobić, i powinno zaoszczędzić miejsce na dysku
SeanC
2
Zastosowanie prostego szyfru takiego jak en.wikipedia.org/wiki/ROT13 powinno wystarczyć, aby przeciętny użytkownik nie edytował plików. Zresztą wszyscy prawdopodobnie wiedzą, co robią.
Exilyth
1
Miej na swój sposób, ale lubię, że moje gry można łatwo modyfikować.
mmyers

Odpowiedzi:

28

Na razie, ponieważ dopiero zaczynasz, pliki tekstowe prawdopodobnie są w porządku. W twoim pytaniu jest kilka problemów, którymi się zajmę.

  1. Ochrona danych nie jest tak istotna, jak zapewne myślisz. Jeśli grasz w trybie dla wielu graczy, dane i tak zostaną zapisane po stronie serwera. Jeśli Twoja gra jest dla jednego gracza, to co jeśli gracze zmodyfikują dane? Jeśli coś zepsują, to naprawdę ich wina i mogą ponownie zainstalować.

  2. Wydajność to także coś, czego często nie planujemy właściwie. Nie powinno się naprawdę zoptymalizować aż faktycznie mierzyć problem z wydajnością. Domyślam się, że prawdopodobnie będziesz mieć dużo danych, które nie są tak duże i że pliki tekstowe będą w porządku.

Biorąc to pod uwagę, najlepiej jest jak najlepiej wyodrębnić procedury zapisywania i ładowania danych. Na przykład możesz mieć klasę podstawową, powiedzmy DataWriter, a następnie zapewnić różne implementacje różnych metod. Bardzo prosty przykład wyglądałby następująco:

class DataWriter {
  virtual void save(GameState state) = 0;

  virtual ~DataWriter() { }
};

class TextFileDataWriter : public DataWriter {
  virtual void save(GameState state) {
    //write to text file
  }
};

class DatabaseDataWriter : public DataWriter {
  virtual void save(GameState state) {
    //write to database
  }
};

Kiedy w końcu profilujesz grę i zdajesz sobie sprawę, że wąskim gardłem w wydajności jest zapisywanie plików, możesz zapewnić kolejną implementację tej klasy (na przykład zamiast pisać do bazy danych) z minimalnymi zmianami w wywoływanym kodzie.

pwny
źródło
To gra dla pojedynczego gracza, i to były moje myśli dokładnie, czy chcieli zepsuć dane. Nie wiem, coś w plikach tekstowych wydawało się po prostu nieprofesjonalne, i pomyślałem, że jeśli uda mi się powstrzymać użytkownika przed zepsuciem, prawdopodobnie powinienem. Co masz na myśli mówiąc „baza danych”? Często to słyszę, ale nie mam pojęcia, jaka jest dokładna definicja ani jaki to plik.
Althezel
6
@Althezel Chodzi o to, że niezależnie od tego, jak zapisujesz swoje dane, ktoś zdeterminowany, aby je zmodyfikować, będzie mógł to zrobić. W tym sensie marnowanie cennego czasu na rozwój jest zwykle marnowaniem czasu na próby wprowadzenia zabezpieczeń :)
pwny
@Althezel Jeśli chodzi o bazy danych, pomyśl o tym jako o mechanizmie, do którego przekazujesz żądania odczytu lub zapisu danych. Ten silnik jest odpowiedzialny za efektywne zapisywanie / czytanie, zwykle w formie relacyjnej w tabelach. W twoim przypadku rzuciłbym okiem na SQLite ( sqlite.org ). Zasadniczo użyłbyś biblioteki C ++, aby połączyć się z lokalną bazą danych SQLite (SQLite używa plików lokalnych) i przekazać wywołania biblioteki w składni SQL, aby uzyskać dostęp do twoich danych.
pwny
2
To smutny świat, gdy programiści chcą zablokować użytkownikom informacje przechowywane na ich komputerach.
ClassicThunder
2
Korzystanie z plików tekstowych wydaje się nieprofesjonalne, ponieważ bardzo niewiele gier przechowuje takie rzeczy jako „save-data.txt” - ale jeśli kiedykolwiek spędziłeś czas na przeglądaniu większości zapisanych plików gier, przekonasz się, że często są to tylko pliki tekstowe które czasami zawierają dane binarne. Na przykład każda gra z serii Civilization and Total War wykorzystuje rzeczywiste pliki .txt do szerokiej gamy danych gry. Najczęstszym „uaktualnieniem” do tego jest system bazy danych, który ostatecznie przechowuje dane jako plik płaski, który - z wyjątkiem niektórych binarnych obiektów blob - jest tylko plikiem tekstowym.
BrianH
3

Słowo Dane gry może na przykład oznaczać wiele rzeczy

  • Gamestate
  • Pliki konfiguracyjne
  • Mapy, tekstury, dźwięki, skrypty, dane animacji, ...
  • Lokalizacja
  • Dane układu GUI
  • więcej nie myślałem

Dla każdej kategorii możesz zastosować inne podejście.

Na przykład możesz użyć SQLite do lokalizacji, plików binarnych dla Map, tekstur, dźwięków i tak dalej.

Do konfiguracji należy użyć łatwych do zmiany plików XML.

Jak zawsze poprawną odpowiedzią jest „to zależy”.

Istnieje wiele parserów xml z powiązaniem c ++ i istnieje również powiązanie c ++ dla SQLite.

Quonux
źródło
Może to być kwestia religijna, ale wolałbym używać formatu pliku INI dla konfiguracji zamiast XML. To drugie wydaje się przesadą w tym scenariuszu. W bibliotekach doładowań znajduje się czytnik INI.
Artur Czajka
0

Możesz zapisać swoje dane jako binarny obiekt blob i przesłać strumieniowo dane z powrotem, gdy będziesz mieć dostęp do tego pliku. To rozwiązałoby oba problemy. Upewnij się tylko, że kod serializacji jest dokładnie taki sam jak de-serializacji.

Streaming w binarnym obiekcie blob jest stosunkowo szybki, a także uniemożliwia użytkownikowi zobaczenie danych i ich zmianę.

Możesz to wszystko osiągnąć za pomocą standardowych strumieni bibliotecznych.

SuperSquareBoy
źródło
2
Podczas gdy binarny obiekt blob jest szybki i łatwy (zarówno do programowania, jak i do ładowania / uruchamiania), największym problemem, jaki miałem z binarnym obiektem blob, jest jak tylko zmienisz cokolwiek w organizacji struktury danych (tyle, ile dodajesz jednego floatczłonka do jednego obiekt), stare zapisy stają się całkowicie nieprawidłowe. Trudno sobie z tym poradzić podczas programowania, ale jeśli jesteś do tego zdolny, to na pewno.
bobobobo