Zastanawiam się nad napisaniem małej przygodowej gry tekstowej, ale nie jestem pewien, jak zaprojektować świat z technicznego punktu widzenia.
Moją pierwszą myślą jest zrobienie tego w XML, zaprojektowałem coś takiego. Przepraszamy za stos plików XML, ale czułem, że ważne jest pełne wyjaśnienie tego, co robię.
<level>
<start>
<!-- start in kitchen with empty inventory -->
<room>Kitchen</room>
<inventory></inventory>
</start>
<rooms>
<room>
<name>Kitchen</name>
<description>A small kitchen that looks like it hasn't been used in a while. It has a table in the middle, and there are some cupboards. There is a door to the north, which leads to the garden.</description>
<!-- IDs of the objects the room contains -->
<objects>
<object>Cupboards</object>
<object>Knife</object>
<object>Batteries</object>
</objects>
</room>
<room>
<name>Garden</name>
<description>The garden is wild and full of prickly bushes. To the north there is a path, which leads into the trees. To the south there is a house.</description>
<objects>
</objects>
</room>
<room>
<name>Woods</name>
<description>The woods are quite dark, with little light bleeding in from the garden. It is eerily quiet.</description>
<objects>
<object>Trees01</object>
</objects>
</room>
</rooms>
<doors>
<!--
a door isn't necessarily a door.
each door has a type, i.e. "There is a <type> leading to..."
from and to are references the rooms that this door joins.
direction specifies the direction (N,S,E,W,Up,Down) from <from> to <to>
-->
<door>
<type>door</type>
<direction>N</direction>
<from>Kitchen</from>
<to>Garden</to>
</door>
<door>
<type>path</type>
<direction>N</direction>
<from>Garden</type>
<to>Woods</type>
</door>
</doors>
<variables>
<!-- variables set by actions -->
<variable name="cupboard_open">0</variable>
</variables>
<objects>
<!-- definitions for objects -->
<object>
<name>Trees01</name>
<displayName>Trees</displayName>
<actions>
<!-- any actions not defined will show the default failure message -->
<action>
<command>EXAMINE</command>
<message>The trees are tall and thick. There aren't any low branches, so it'd be difficult to climb them.</message>
</action>
</actions>
</object>
<object>
<name>Cupboards</name>
<displayName>Cupboards</displayName>
<actions>
<action>
<!-- requirements make the command only work when they are met -->
<requirements>
<!-- equivilent of "if(cupboard_open == 1)" -->
<require operation="equal" value="1">cupboard_open</require>
</requirements>
<command>EXAMINE</command>
<!-- fail message is the message displayed when the requirements aren't met -->
<failMessage>The cupboard is closed.</failMessage>
<message>The cupboard contains some batteires.</message>
</action>
<action>
<requirements>
<require operation="equal" value="0">cupboard_open</require>
</requirements>
<command>OPEN</command>
<failMessage>The cupboard is already open.</failMessage>
<message>You open the cupboard. It contains some batteries.</message>
<!-- assigns is a list of operations performed on variables when the action succeeds -->
<assigns>
<assign operation="set" value="1">cupboard_open</assign>
</assigns>
</action>
<action>
<requirements>
<require operation="equal" value="1">cupboard_open</require>
</requirements>
<command>CLOSE</command>
<failMessage>The cupboard is already closed.</failMessage>
<message>You closed the cupboard./message>
<assigns>
<assign operation="set" value="0">cupboard_open</assign>
</assigns>
</action>
</actions>
</object>
<object>
<name>Batteries</name>
<displayName>Batteries</displayName>
<!-- by setting inventory to non-zero, we can put it in our bag -->
<inventory>1</inventory>
<actions>
<action>
<requirements>
<require operation="equal" value="1">cupboard_open</require>
</requirements>
<command>GET</command>
<!-- failMessage isn't required here, it'll just show the usual "You can't see any <blank>." message -->
<message>You picked up the batteries.</message>
</action>
</actions>
</object>
</objects>
</level>
Oczywiście musiało być coś więcej niż to. Konieczne są interakcje z ludźmi i wrogami, a także śmierć i zakończenie. Ponieważ XML jest dość trudny w obsłudze, prawdopodobnie stworzyłbym jakiś edytor światowy.
Chciałbym wiedzieć, czy ta metoda ma jakieś wady i czy istnieje „lepszy” lub bardziej standardowy sposób jej wykonania.
c#
xml
text-based
adventure-games
Wielomian
źródło
źródło
Odpowiedzi:
Jeśli nie jesteś całkowicie przywiązany do C #, wówczas „bardziej standardowym” sposobem jest skorzystanie z jednego z wielu narzędzi do tworzenia tekstowych przygód, które już istnieją, aby pomóc ludziom stworzyć dokładnie taką grę. Narzędzia te zapewniają już działający parser, obsługę śmierci, zapisywanie / przywracanie / cofanie, interakcję między postaciami i inne podobne standardowe funkcje tekstowej przygody. Obecnie najpopularniejszymi systemami do tworzenia treści są Inform i TADS (choć dostępnych jest również pół tuzina innych)
Inform może zostać skompilowany do większości zestawów instrukcji maszyny wirtualnej Z Machine używanych przez gry Infocom lub do najnowszych zestawów instrukcji maszyny wirtualnej glulx. Z drugiej strony TADS kompiluje się do własnego kodu maszyny wirtualnej.
Każdy typ pliku binarnego może być obsługiwany przez większość współczesnych interaktywnych interpretatorów fikcji (w dawnych czasach często potrzebowaliśmy osobnych interpretatorów dla gier TADS z gier ZMachine z gier glulx. Ale na szczęście te dni już minęły.) Tłumacze są dostępni tylko dla o każdej platformie, którą chcesz; Mac / PC / Linux / BSD / iOS / Android / Kindle / browser / itp. Dzięki temu masz już wiele platform i dobrze się o nie troszczysz.
Na większości platform obecnie polecanym tłumaczem jest Gargoyle , ale jest wiele innych, więc nie krępuj się eksperymentować.
Kodowanie w Inform (szczególnie w najnowszej wersji) wymaga trochę czasu, aby się przyzwyczaić, ponieważ sam marketing jest bardziej skierowany do autorów niż do inżynierów, a więc jego składnia wygląda dziwnie i prawie konwersacyjnie. W składni Inform 7 przykład będzie wyglądał następująco:
Podczas gdy TADS wygląda bardziej jak tradycyjny język programowania, a ta sama gra w TADS wygląda następująco:
Oba systemy są swobodnie dostępne, bardzo często używane i mają mnóstwo dokumentacji instruktażowej (dostępnej z linków, które podałem powyżej), więc warto sprawdzić oba i wybrać ten, który wolisz.
Zauważ, że oba systemy mają subtelnie różne standardowe zachowania (chociaż oba mogą być modyfikowane). Oto zrzut ekranu z gry, opracowany ze źródła Inform:
A oto jedna z rozgrywanej gry (w terminalu - typografia może być o wiele ładniejsza niż ta), jak skompilowano ze źródła Tads:
Ciekawe punkty do zapamiętania: TADS domyślnie wyświetla „wynik” w prawym górnym rogu (ale możesz go wyłączyć), a Inform nie (ale możesz go włączyć). Inform poinformuje domyślnie, że pozycje w opisie pokoju wskazują stan otwarty / zamknięty, a Tads nie. Chłopcy mają tendencję do automatycznego podejmowania działań w celu wykonania poleceń gracza (chyba, że mówisz, żeby tego nie robić), a Inform zwykle tego nie robi (chyba, że tak mówisz).
Każda z nich może być wykorzystana do stworzenia dowolnej gry (ponieważ obie są wysoce konfigurowalne), ale Inform ma bardziej ukierunkowaną konstrukcję na tworzenie interaktywnej fikcji w nowoczesnym stylu (często z minimalnymi łamigłówkami i więcej narracji w stylu), gdzie TADS jest bardziej uporządkowany w kierunku tworzenia przygód tekstowych w starym stylu (często silnie skoncentrowanych na zagadkach i rygorystycznie definiujących mechanikę światowego modelu gry).
źródło