tBane Temat założony przez niniejszego użytkownika |
System Dialogów v2 » 2024-06-06 21:04:43 Witam. Spać nie mogłem za sprawą pekfosa i korci mnie strasznie ten styl dialogów. Tylko nie wiem od czego zacząć. Rozpisałem sobie przykładowy dialog, ale nie wiem jak go podzielić na funkcje i jakich struktur użyć. -"W czym mogę pomóc?" (NPC) -"Kim jesteś?" (Player) -"Nazywam się Gorn i jestem myśliwym." (NPC) -"Na co polujesz?" (Player) -"Poluję na dziobaki oraz wilczury" (NPC) -"Jak idą łowy?" (Player) -"Nie najlepiej. Ostatnio coraz mniej zwierzyny. Jak tak dalej pójdzie, to będę musiał zmienić tereny łowieckie." (NPC) -"W okolicy nadal widać potwory." (Player) -"Tak, ale jest ich coraz mniej. Kiedyś to było, a teraz zwyczajnie mało." (NPC) -"Masz rację. Nie ma już tu na co polować." (Player) -<ifHasItem "wolf skin" 1> "Mam skórę wilczura. Chcesz ją ode mnie odkupić?" (Player) -"Chętnie. Dam ci za każdą miksturę leczniczą" (NPC) -"Proszę oto skóra wilczura" <removeItem "wolf skin" 1> (Player) -"Masz, w zamian mikstura lecznicza. Tak jak się umawialiśmy." <addItem "potion" 1> (NPC) -"Może innym razem ..." (Player) -<ifHasItem "dziobak skin" 1> "Mam skórę dziobaka. Chcesz ją odkupić?" (Player) -"Za skórę dziobaka, mogę dać Ci 10 sztuk złota." (NPC) -"Zgoda. Oto Twoja skóra." <removeItem "dziobak skin" 1> (Player) -"Trzymaj to złoto." <addItem "gold" 10> (NPC) ="Może innym razem ..." (Player) -"Żegnaj" <end>
ogólnie dialog ma strukturę następującą (z tym dam radę) <warunek> "Tekst Dialogu" <funkcja> (Player) lub "Tekst Dialogu" <funkcja> (NPC) struktury zapewne powinny wyglądać takclass DialogueOption { public: std::wstring text; int nextDialogueID; std::function < bool() > conditions; std::function < void() > actions; };
class Dialogue { public: int id; std::wstring text; std::vector < DialogueOption > options; std::function < void() > actions; };
nie mam pojęcia jak wczytać ten dialog .. |
|
pekfos |
» 2024-06-06 23:09:39 Do czego jest (Player) i (NPC)? Jak tylko dla czytelności, by było widać czy to jest opcja czy odpowiedź, to krócej byłoby to załatwić tym pierwszym znakiem w linii (który zresztą pominąłeś w opisie). Znak - mógłby być wymagany dla opcji i nie byłoby go dla odpowiedzi. Trochę by to uprościło i ograniczyło ilość pisania. Na dobrą sprawę można nawet darować sobie wcięcie między odpowiedzią i opcjami, skoro są rozróżnione znakiem -: "W czym mogę pomóc?" -"Kim jesteś?" "Nazywam się Gorn i jestem myśliwym." -"Na co polujesz?" Więc dwa rodzaje linii by miały taką gramatykę: - <warunek>? "Tekst Dialogu" <funkcja>? "Tekst Dialogu" <funkcja>? Znak zapytania określa opcjonalny element. Pewnie należałoby dopuszczać spacje/tabulacje między każdym elementem by parser nie był wybredny. Co do ładowania takiej zagnieżdżonej struktury, po prostu ładuj linie po kolei i patrz na ilość tabulacji na początku linii. Można to zrobić funkcją rekurencyjną, chociaż pewnie prościej utrzymywać tu własny stos. Przykład: #include <iostream> #include <string> #include <vector>
bool parse() { std::string line, dialogue; std::vector < std::string > stack; while( std::getline( std::cin, line ) ) { size_t tabs = line.find_first_not_of( "\t" ); if( tabs == std::string::npos ) continue; while( tabs < stack.size() ) { dialogue = stack.back(); stack.pop_back(); } if( line[ tabs ] == '-' ) { if( tabs != stack.size() || dialogue.empty() ) return false; std::cout << "Dialog: " << dialogue << ", opcja: " << line.substr( tabs + 1 ) << '\n'; } else { if( tabs == stack.size() ) { if( !dialogue.empty() ) return false; } else if( tabs == stack.size() + 1 ) { stack.push_back( dialogue ); } else return false; dialogue = line.substr( tabs ); } } return true; }
int main() { if( !parse() ) std::cout << "Blad parsowania\n"; } a -a1 Dialog: a, opcja: a1 -a2 Dialog: a, opcja: a2 b -b2 Dialog: b, opcja: b2 c -c1 Dialog: c, opcja: c1 -c2 Dialog: c, opcja: c2 -b3 Dialog: b, opcja: b3 d -d1 Dialog: d, opcja: d1 -a3 Dialog: a, opcja: a3 W przypadku błędu parsowania, warto by wypisać komunikat błędu (aktualnie napisany tylko w komentarzu) wraz z numerem linii. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-06-08 02:51:44 dla poniższego dialogu funkcja nie działa. Wyskakuje mi błąd "druga definicja tego samego dialogu" "W czym mogę pomóc?" -"Kim jesteś?" "Nazywam się Gorn i jestem myśliwym." -"Na co polujesz?" "Głównie na dziobaki oraz wilczury."
"W czym mogę pomóc?" -"Kim jesteś?" Dialog: "W czym moge pomóc?", opcja: "Kim jestes?" "Nazywam się Gorn i jestem myśliwym." druga definicja tego samego dialogu Blad parsowania
|
|
pekfos |
» 2024-06-08 13:27:22 U mnie działa. Przykład oczekuje jednego drzewa z dialogiem i poprawnymi wcięciami, konkretnie z użyciem tabulatora. W podanym wyniku wyraźnie nie podawałeś wcięć, bo nic nie jest wcięte. Powinno to wyglądać tak "W czym mogę pomóc?" -"Kim jesteś?" Dialog: "W czym mogę pomóc?", opcja: "Kim jesteś?" "Nazywam się Gorn i jestem myśliwym." -"Na co polujesz?" Dialog: "W czym mogę pomóc?", opcja: "Na co polujesz?" "Głównie na dziobaki oraz wilczury." |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-06-08 18:32:10 ok. Wydaje mi się, że wcześniej poprawnie używałem tabulatorów, ale najważniejsze, że już działa. "W czym mogę pomóc?" -"Kim jesteś?" -"Nazywam się Gorn i jestem myśliwym." -"Na co polujesz?" -"Poluję na dziobaki oraz wilczury"
"W czym mogę pomóc? -"Kim jesteś?" Dialog: "W czym moge pomóc?", opcja: "Kim jestes?" -"Nazywam się Gorn i jestem myśliwym." Dialog: "W czym moge pomóc?", opcja: "Nazywam sie Gorn i jestem mysliwym." -"Na co polujesz?" Dialog: "W czym moge pomóc?", opcja: "Na co polujesz?"
teraz jeszcze mam pytanie, jak opakować to w klasy ? I jak rozróżniać dialogi, bo getDialogueID(string dialog) jest nieoptymalne chyba class DialogueOption { public: int nextDialogueID; string text; DialogueOption( int nextDialogueID, string text ) { this->nextDialogueID = nextDialogueID; this->text = text; } };
class Dialogue { public: int id; string text; std::vector < DialogueOption * > options; Dialogue( int id, string text ) { this->id = id; this->text = text; } addOption( int nextDialogueID, string text ) { options.push_back( new DialogueOption( nextDialogueID, text ) ); } };
|
|
pekfos |
» 2024-06-08 21:40:19 A co potrzebujesz rozróżniać? Na pewno musi się dać powiązać NPC z jego dialogiem, co można zrobić przez nazwę pliku. Po wczytaniu będziesz znać nadany ID dialogu dla głównego dialogu drzewa. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-06-09 01:54:31 Wcześniej miałem dialogi opakowane w 2 klasy. Jedna to była Dialogue i odpowiadała za dialog po stronie NPC, druga zaś to DialogueOption i służyła do wyboru odpowiedzi przez gracza. Teraz zmieniliśmy sposób reprezentacji drzewa dialogu na taki, że wszystkie wypowiedzi zarowno po stronie gracza jak i NPC występujące po głównej wypowiedzi są traktowane jako DialogueOption i nie wiem jak to opakować w klasy.
id wcześniej było indeksem odpowiedzi po stronie NPC. Teraz id ma być indeksem drzewa dialogu, nie pojedynczej wypowiedzi. Nie wiem w jaki sposób teraz to uporządkować. |
|
pekfos |
» 2024-06-09 12:34:38 Zmienił się format pliku, nie reprezentacja dialogu w programie. Klasy mogą zostać bez zmian. |
|
« 1 » 2 |