Dlaczego kodowanie zawartości jest złe?

41

Wiem, że większość gier przechowuje tekst dialogowy w plikach, ale widziałem też, że kilka gier tekstowych faktycznie programuje zawartość (mapę, opcje, możliwe polecenia gracza, tekst fabuły) do kodu gry.

Mogę wymyślić kilka powodów, ale jaki jest główny powód, dla którego nawet gry tekstowe przechowują wszystko w plikach poza programem?

Szczegóły implementacji niewiele różnią się między trzymaniem zawartości w czymś takim, jak popularny format XML, analizowaniem go, a następnie renderowaniem map / wyświetlaniem tekstu na podstawie zmiennych utworzonych z pliku XML, a po prostu rezygnacją z pliku XML. Oba kończą się łańcuchami, które wysyłają na ekran. Czy różnica nie jest tylko zapisem?

Niektóre gry zawierają nawet grafikę (ASCII art?) Wewnątrz kodu. Wiem, że to nie jest właściwe i mogę odgadnąć kilka powodów, dla których jest to złe, ale nie znam też głównego powodu.

Bardzo popularne jest to, że większość treści znajduje się poza programem. Nawet Dwarf Fortress nie używa rzeczywistych znaków ASCII, ale obrazy znaków ASCII załadowane do pamięci.

Pytam przede wszystkim, ponieważ tworzenie, analizowanie i praca z plikami XML to trochę PITA. Wiesz ... w porównaniu do leniwej alternatywy polegającej na tym, że każdy unikalny loch (treść) ma swoją klasę.

użytkownik50286
źródło
9
Gry oparte na tekście zawierają dużo kodu, ale myślę, że dzieje się tak z powodu czasu ich opracowania i złych wyborów projektowych. To samo może dotyczyć Dwarf Fortress. Osobiście wziąłem wszystkie moje gry tekstowe i przeniosłem zawartość poza źródło do bazy danych. To znacznie ułatwiło mi życie.
Glen Swan
7
i18n byłby bardzo trudny do wykonania z zawartością osadzoną w źródle.
pllee
5
Nie jestem pewien, czy jest to specyficzne dla rozwoju gry. W przyszłości rozważ zapytanie o programistę SE lub przepełnienie stosu.
MichaelHouse
13
just making every unique dungeon (content) its own class.To tylko sprawiło, że zadrżałem. Oddzielenie danych od logiki jest dla mnie tak fundamentalną zasadą, że jestem zaskoczony, że programiści wciąż ją łamią.
Lilienthal,
4
Bez względu na to, co zdecydujesz, pamiętaj, że na stałe zapisywane treści pozwalają na znacznie więcej specjalnych przypadków. Chcesz, aby jakiś szef pojawił się tylko między północą a 7 rano (w czasie rzeczywistym)? Znacznie łatwiej jest to zakodować na stałe niż stworzyć ogólny sposób, w jaki potwory pojawiają się tylko w określonych momentach.
user253751

Odpowiedzi:

85

Jest tego kilka przyczyn. Zaraz dotknę kilku:

  1. Sprawia, że ​​kod źródłowy jest bałaganem. Jeśli masz dużo okien dialogowych (drzew), ogromna część bazy kodu to tylko tekst, który nie ma nic wspólnego z twoim kodem gry.
  2. Będziesz musiał ponownie skompilować za każdym razem, gdy zmienisz tyle, co pojedynczą postać.
  3. Sam dialog jest trudny w nawigacji. Wyobrażam sobie, że próba zaimplementowania całego drzewa dialogowego, a tym bardziej kilku, całkowicie wewnątrz twojego źródła spowoduje zagnieżdżenie się spaghetti i zagnieżdżonych ifs, switches i tak dalej. W rezultacie powstaje kod podatny na błędy, trudny do odczytania i trudniejszy do debugowania.
  4. Jeśli chcesz umożliwić ludziom modyfikowanie lub rozszerzanie gry, jest to o wiele łatwiejsze, jeśli nie muszą oni radzić sobie z kodem źródłowym, aby coś zmienić.
  5. Powyższy punkt jest jeszcze ważniejszy, jeśli pracujesz w zespole. Nie chcesz, aby Twój pisarz musiał zadzierać z kodem tylko po to, aby wejść do okna dialogowego.
  6. Analizowanie XML lub innych standardowych formatów plików jest dość łatwe, jeśli korzystasz z istniejących bibliotek, więc koszt implementacji w ten sposób jest bardzo niski, zapewniając jednocześnie wiele korzyści i unikając wyżej wymienionych problemów i wiele więcej.
  7. Jak wskazano poniżej @MiloPrice, znacznie łatwiej jest zlokalizować grę, jeśli tekst znajduje się w plikach zewnętrznych. Możesz dodać język, dodając plik, Twój zespół może zająć się tłumaczeniem bez konieczności dotykania źródła (co jest szczególnie ważne, jeśli pozwalasz tłumaczyć ludziom, którzy nie powinni widzieć całego twojego kodu - pomyśl freelancerzy, ludzie z społeczność, która nie należy do Twojego zespołu itp.).
chrześcijanin
źródło
10
Nie powiedziałbym, że spowodowałoby to bałagan w twoim kodzie. W przeciwnym razie zawartość lub nie, wszystko można uznać za bałagan luzem. Możesz ustrukturyzować treść w dobrej strukturze, tak jak kod. Ale reszta punktów wciąż jest silna.
Glen Swan
28
Kolejną dużą zaletą jest łatwość lokalizacji / tłumaczenia.
Milo P,
2
@Christian: Możesz mieć program sterowany danymi, w którym dane są osadzone w programie w formacie, w którym są bezpośrednio użyteczne w miejscu (np. W C lub C ++, duże, miejmy nadzieję, consttablice o statycznym czasie przechowywania). Pozwala to zaoszczędzić cały kod i koszty pamięci w czasie wykonywania ładowania / konwersji zewnętrznej reprezentacji danych w czasie wykonywania. Oczywiście nadal obowiązują wszystkie inne powody, dla których dane pozostają zewnętrzne.
R ..
2
Osobiście preferuję jeszcze silniejsze podejście z tych samych powodów, które wymieniono tutaj: Przenieś większość kodu również w języku skryptowym. Zbuduj rdzeń w C / C ++, osadz język taki jak Python lub Lua i wyeksportuj do niego API. Don't Starvepodąża za tym podejściem i jest to jedna z najlepiej napisanych gier, jakie widziałem. Robią to również liczne inne gry z przeszłości i teraźniejszości, a także aplikacje (i rzadko narzędzia). Powiedziałbym, że ogólnie, poza małymi projektami i drobnymi narzędziami, ciężkie nakładanie warstw i separacja są zawsze twoim przyjacielem.
mechalynx
30

Umieszczenie danych treści gry w kodzie oznacza, że ​​aby zobaczyć potencjalną zmianę lub iterację danych treści gry, musisz ponownie skompilować grę. Jest to złe z dwóch powodów:

  • Wiele języków, w których pisane są gry, ma długi czas kompilacji. C ++ jest szczególnie zły pod tym względem, a C ++ jest bardzo popularnym językiem dla dużych gier komercyjnych. Jest to mniejszy problem z językami takimi jak C # i Java, ale nadal nie jest tak szybki, jak możliwość przechowywania danych gry w plikach zewnętrznych, które można ponownie załadować podczas działania gry, aby zobaczyć zmiany.

  • Wiele gier jest opracowywanych przez zespoły, które często składają się z nietechnicznych programistów (projektantów i artystów) tworzących treści. Nie tylko ludzie nietechniczni nie chcą ponownie kompilować gry ani zajmować się „uciążliwymi narzędziami programistycznymi” w celu powtarzania swoich treści, pożądane może być zminimalizowanie narażenia kodu źródłowego tylko na programistów (ponieważ mniej osób, które mają dostęp do kodu źródłowego, tym mniej osób może go wyciec - przypadkowo lub nie).

Myślę, że przeceniasz złożoność ładowania danych z plików tekstowych lub XML. Przez większość czasu powinieneś używać do tego biblioteki, co znacznie ułatwia proces parsowania XML / JSON /. Tak, napisanie systemu ładowania poziomów opartego na danych jest nieco kosztowny, ale generalnie pozwoli to zaoszczędzić dużo czasu na dłuższą metę w porównaniu z tonami unikalnych klas reprezentujących każdy poziom.

Mniejsze lub prostsze gry mogą nie mieć tyle korzyści z długoterminowej inwestycji opartej na danych, więc jeśli programiści nie używają istniejących platform / mechanizmów, które je obsługują, może być bardziej wydajne dla nich po prostu kodowanie danych w kod gry.

Istnieje oczywiście wiele powodów, dla których dana gra może umieścić swoje dane w plikach zewnętrznych (lub nie); nie jest możliwe wyszczególnienie ich wszystkich. Na pewnym poziomie zazwyczaj sprowadzają się do dodatkowej prędkości iteracji lub elastyczności, które może zapewnić brak konieczności przebudowywania gry.

Josh
źródło
Nie sądzę, żeby czasy kompilacji były tak ważne, ale jako programista zawsze dążymy do „czystego kodu” ... to całkiem dobry powód do oddzielania rzeczy sam w sobie… treść powinna być zawartością, a nie kodem!
Wojna
4
@Wardy Czasy kompilacji są bardzo ważne w C ++. Pracowałem z rozwiązaniami, których budowa zajęła ponad 15 minut, albo ze względu na rozmiar projektu, agresywne użycie szablonów, a nawet lenistwo programistów (w tym niepotrzebne nagłówki). I jestem pewien, że tak jest w przypadku dużych gier komercyjnych.
concept3d
1
@ concept3d: Chciałbym, żeby mój projekt trwał 15 minut. Czysta kompilacja na dedykowanym serwerze kompilacji zajmuje ~ 50 minut.
Mooing Duck
im mniej osób ma dostęp do kodu źródłowego, tym mniej osób cierpi z powodu uszkodzenia mózgu spowodowanego przez C ++. : P
Sarge Barszcz
Wydaje mi się, że niektórym ludziom brakuje przeładowania - nikt nie przejmuje się tym, że ponowne skompilowanie gry zajmuje 30 sekund, artyści nie chcą zrestartować gry, chcą skrótu klawiaturowego, aby mogli przetestować różne animacje i tekstury w locie. W rzeczywistości jest to jedna z rzeczy, których chcą najbardziej. Zobaczenie, jak rzeczy wyglądają poza grą, to jedno, ale liczy się to, że zobaczysz je w grze.
wolfdawn
7

Jak zawsze, jak zawsze, to zależy. Ale najpierw chciałbym argumentować, że kodowanie twarde samo w sobie nie jest złe.

Mam zakodowane na stałe treści, w szczególności tekst dialogu, w niektórych prostych grach, a świat się nie skończył. My, programiści, uwielbiamy abstrakcje, ale pamiętaj, że każda warstwa abstrakcji sprawi, że Twój program będzie bardziej złożony i trudniejszy do zrozumienia.

Jeśli twoja gra jest na tyle prosta, że ​​można w niej na stałe zakodować niektóre treści, z pewnością rozważę to ze względu na prostotę.

To jednak nie przeskakuje zbytnio. Z pewnością najczęstszym powodem umieszczania treści w zasobach zewnętrznych jest uproszczenie pracy zespołowej, ponieważ jedna osoba lub zespół może skupić się na pisaniu gry, podczas gdy inna może skupić się na tworzeniu i dopracowywaniu treści.

Jednak wyznaczenie granicy między programem a treścią nie zawsze jest naprawdę trywialne. Można powiedzieć, że tekstury mają 100% zawartości; ale co z teksturami generowanymi proceduralnie? Tekst dialogu można uznać za zawartość 100%; ale co się stanie, gdy okno dialogowe zmieni się w zależności od poprzednich działań? Inne elementy, które można uznać za 100% część programu, takie jak skrypty lub shadery, można również uznać za część zawartości gry. Czy powinny być zakodowane na stałe? czy powinny być ładowane jako zasób zewnętrzny?

Pamiętaj jednak, że każdy rodzaj treści, które wspierasz w grze, musi mieć związany z nią kod ładowania i interpretacji, więc ogólnie, w razie wątpliwości, zaleciłbym kodowanie na stałe i zabranie go do zewnętrznego źródła, gdy naprawdę potrzebuję tej elastyczności (nie wtedy, gdy myślisz, że - może - potrzebujesz, ale kiedy faktycznie tego potrzebujesz)

Wreszcie jedną z zalet przechowywania danych w plikach zasobów jest to, że można je ładować tylko wtedy, gdy są potrzebne (co może przyspieszyć ładowanie gry) i zwalniać je, gdy nie są już potrzebne (co pozwala mieć więcej treści niż może zmieścić się w pamięci). (Narożnik Nitpickers: biblioteki DLL zasobów można prawdopodobnie uznać za zasoby zewnętrzne)

Panda Piżama
źródło
7
„pamiętaj jednak, że każda warstwa abstrakcji sprawi, że Twój program będzie bardziej złożony i trudniejszy do zrozumienia”. Musiałbym się nie zgodzić, abstrakcja może uprościć program i na pewno powinna ułatwić zrozumienie.
NPSF3000,
1
Abstrakcje @ NPSF3000 zwiększą złożoność, ale mogą usunąć większą złożoność niż dodają.
user253751
2
@immibis, więc całkowita suma złożoności projektu po wdrożeniu abstrakcji powinna być niższa niż wcześniej.
NPSF3000,
3
@ NPSF3000: Chodzi mi o to, że nie powinieneś tworzyć abstrakcji tylko dlatego, że możesz. Czasami dane na stałe są prostsze, bardziej zrozumiałe i łatwiejsze dookoła. Najczęściej widziałem, jak gry podążają ścieżką do softcoding , co wydaje mi się godne ubolewania. Pamiętaj również, że dodawanie abstrakcji jest zawsze łatwiejsze niż ich usuwanie, dlatego jestem zwolennikiem dodawania abstrakcji tylko wtedy, gdy ich potrzebujesz.
Panda Pajama
@PandaPajama robienie czegoś „tylko dlatego, że możesz” może spowodować problem, niezależnie od tego, co to jest. To nie znaczy, że to coś jest z natury złożone, co było moim zmartwieniem. Ponadto, dlaczego uważasz, że dodawanie abstrakcji jest łatwiejsze niż ich usuwanie? Z góry myślę, że inaczej - późne dodanie abstrakcji może oznaczać znaczną refaktoryzację, ale nie mogę od razu pomyśleć o przypadku, w którym usunięcie niepotrzebnej abstrakcji byłoby skomplikowane. Zmiana ciągów znaków na XML powinna być trywialna.
NPSF3000
3

Głównym powodem przechowywania w plikach tekstowych jest możliwość ponownego użycia. Utworzenie frameworka do gry tekstowej, który odczytuje mapy, okna dialogowe i inne zasoby z pliku tekstowego, umożliwia ponowne użycie frameworka do innych gier. Wychodząc poza gry tekstowe, tak wielkie tytuły budżetowe jak Call of Duty wypuszczają co roku nową grę.

Innym powodem jest przenośność. Możesz używać tych samych plików dla Internetu, komputera PC, Maca, Androida itp. Wystarczy, że wykonasz makietę dla różnych platform, a większość danych gry pozostanie nietknięta.

Wychodząc poza gry tekstowe, posiadanie skryptu i danych przechowywanych w plikach skróci czas ponownej kompilacji i pozwoli ci stworzyć interfejs do łatwiejszej manipulacji danymi.

Ted Wagner
źródło
1
Oczywiście posiadanie większości rzeczy wielokrotnego użytku zmusza cię do unikania robienia czegokolwiek „specjalnego”, wbrew regułom, które już masz. Zdecydowanie nie opowiadam się za twardym kodowaniem dużych gier, ale jest to niezwykle przydatne, gdy tworzysz prototypy lub piszesz gry eksperymentalne - daje to znacznie większą elastyczność. Oczywiście ma swoją cenę, więc zwykle dobrym pomysłem jest przefakturowanie wszystkiego, gdy gra rzeczywiście zadziała. Rozgrywka jest trudna - upewnij się, że możesz ją przetestować bez nurkowania w architektonicznym piekle: D Zazwyczaj łatwiej jest znaleźć ogólną formę po zdobyciu betonów.
Luaan
3

W celu szybszego wprowadzania zmian przyspiesza rozwój większych produkcji o tonę.

Nie musisz uczyć wszystkich, jak wejść i edytować źródło, aby wprowadzać proste zmiany. Wyciągając go z rzeczywistego kodu, więcej osób ma szansę się wygłupić, łatwiej jest dowiedzieć się, z jakimi opcjami możesz grać, a cały proces dostrajania różnych części gry zajmuje znacznie mniej czasu. Nawet pytania i odpowiedzi mogą w tym pomóc.

John Cobalt
źródło
3

Nie mogę uwierzyć, że nikt o tym jeszcze nie wspominał, ale głównym powodem jest to, że lokalizacja jest DUŻO łatwiejsza. Jeśli potrzebujesz obsługi angielskiego, francuskiego, niemieckiego, hiszpańskiego, portugalskiego, włoskiego, rosyjskiego, chińskiego i innego języka, do którego dążysz, na stałe musisz mieć oddzielne kodowanie dla każdego języka. Oznacza to również, że jeśli chcesz usunąć pewne treści (czytaj: cenzura), musisz zmienić sam kod, aby go uniknąć, zamiast mówić „po prostu zastąp tę minigrę sondowania analnego banerem pasywno-agresywnym, który graficznie wyjaśnia, co się dzieje „. Jest to również dość nieprzyjazne dla konsumentów, ponieważ prawdopodobnie będą musieli ponownie uruchomić grę, aby zmienić język, ponieważ musisz załadować inne biblioteki. Wreszcie,

Z drugiej strony, jeśli korzystasz z zasobów zewnętrznych, obsługa różnych języków oznacza po prostu załadowanie innego pliku zasobów. Można to łatwo zrobić, gdy gra jest uruchomiona. oznacza to, że możesz mieć jedną bazę kodu, co znacznie upraszcza rozwój. Oznacza to również, że możesz łatwo dodać obsługę po wydaniu dla innych języków. Wreszcie oznacza to, że możesz pozwolić użytkownikowi zrezygnować z instalowania określonych języków (funkcja, która nie zdarza się często w grach, ale która jest nadal możliwa), aby zaoszczędzić miejsce na dysku i przepustowość.

Nzall
źródło
3

Myślę, że kluczowym zwrotem jest rozdzielenie obaw .

Jeśli twój kod nie zawiera tekstu, kod staje się mniej skomplikowany. Programista piszący kod nie musi myśleć o konkretnym tekście i może skupić się na kodzie.

Nie musi myśleć o lokalizacji. Osoba dokonująca lokalizacji nie musi się martwić o kod.

chrześcijanin
źródło
3

Myślę, że zbyt łatwo jest być „więdnącym niż biały” facetem i gorąco polecam za pomocą zewnętrznego pliku zasobów tekstowych.

Dlaczego? Ponieważ istnieje tutaj wybór, który dotyczy zrównoważenia kosztów / problemów / zalet każdego rozwiązania.

Kiedy korzystam z zewnętrznego pliku ... Myślę, że inne odpowiedzi wystarczająco dobrze wyjaśniają korzyści. Ale co z kosztami? Musisz zdefiniować prawidłowy formalizm, zbudować interpretera, uzgodnić format pliku, a co gorsza ... zbudować inną aplikację - edytor -. Co stanowi problem 0,00%, jeśli jesteś członkiem zespołu 50 programistów tworzących duży projekt. Ale jeśli jesteś sam: utknąłeś w martwym punkcie.

Ponownie nie nie doceniam ogromnych korzyści płynących z zewnętrznego źródła: programowanie oparte na danych wydaje mi się sposobem na grę wideo. Ale nie zapominajmy o kosztach.

Z drugiej strony, umieszczenie tekstu w kodzie pozwala na szybkie tworzenie prototypów, dlatego należy go preferować za pierwszym razem. W związku z tym, w miarę dojrzewania projektu, radzę przeanalizować dane potrzebne do modelowania dialogów (nastrój / stan historii / ...). Następnie w pewnym momencie decydujesz o niektórych klasach / regułach / formacie pliku i wybierasz się do rzeczy, umożliwiając innym osobom edycję / oddzielenie kodu od treści i tak dalej. LUB w przypadku gry z prostymi oknami dialogowymi (Mario ...) po prostu uważasz, że koszt jest zbyt wysoki i trzymasz kilka łańcuchów / zachowań na stałe.
Twoja decyzja.

(Uwaga na temat lokalizacji: to tylko tablica skrótów, więc jest to niezależny i łatwy do rozwiązania problem).

GameAlchemist
źródło
Niektóre z tych rzeczy są jednak nadal prawdziwe, jeśli umieścisz tekst w kodzie. Nadal potrzebujesz określonego formatu, sposobu poruszania się po drzewie i tak dalej. Mając to na uwadze, wszelkie dodatkowe koszty wdrożenia zewnętrznego źródła treści wydają się stosunkowo niskie, zwłaszcza że istnieją dojrzałe biblioteki i edytory do analizowania, pisania, edycji i tworzenia tych plików. W zależności od złożoności okien dialogowych możesz nawet uciec bez specjalistycznego edytora i po prostu użyć standardowego edytora tekstu.
Christian
1
Pewnie: może nie byłem wystarczająco jasny, miałem na myśli, że dopiero po kilku iteracjach wiesz, jaki jest kształt twoich okien dialogowych (od prostej linii prostej do złożonego drzewa lub maszyny stanów). W pierwszych krokach kilka (najłatwiejszych) ifs + trochę zakodowanych ciągów znaków jest w porządku, imho. Następnie, kiedy możesz wyraźnie przewidzieć swoje potrzeby, dokonaj wyboru po dokonaniu oceny kosztów / korzyści każdego rozwiązania.
GameAlchemist
Środkiem, którego używam w moim obecnym projekcie gry jednoosobowej jest posiadanie na stałe zakodowanej treści, która jest generowana z przeanalizowanych plików przed czasem kompilacji. W wielu przypadkach byłoby to najgorsze rozwiązanie dla obu światów, ale do tego, czego potrzebuję, jest całkiem dobre.
glenatron
2

Wydaje mi się, że licencjonowanie może być również powodem do niewłączania treści do kodu.

Na przykład,

  • Twój kod może być FLOSS , ale nie chcesz w ogóle licencjonować swoich treści (być może chcesz opublikować swój kod gry, aby inni mogli go używać do tworzenia podobnych gier z inną zawartością)
  • Twój kod może być FLOSS, ale chcesz użyć licencji Creative Commons dla swoich treści (ponieważ licencje na oprogramowanie nie działają świetnie dla treści i odwrotnie)
  • Twój kod może być zastrzeżony , ale ponownie wykorzystujesz bezpłatną treść
  • Twój kod może być zastrzeżony, ale chcesz publikować własne treści na licencji free / libre
unor
źródło