Autor Wątek: Dialogi  (Przeczytany 1874 razy)

Offline Norten

  • Użytkownik

# Listopad 06, 2015, 22:36:23
Witam, robię sobie aplikacje. Jednak po napisaniu wielu linijek kodu nagle zauważyłem że tworząc dialogi w grze tworzą się setki linijek.
Przykład:
do
        {
            mapa.ruch(Postac);
            mapa.wyswietlOsada();
            if (mapa.gracz_y==4&&mapa.gracz_x==10)
            {
                cout<<"Witaj jestem wojtem tej osady..."<<endl;
                cout<<"Mam dla ciebie zadanie"<<endl;
            }
            if (mapa.gracz_y==13&&mapa.gracz_x==4)
            {
                cout<<"Witaj w Karczmie "..."<<endl;
                cout<<"[1] Zamow piwo..."<<endl;
                cout<<"[2] Zagraj w kosci..."<<endl;
                cout<<"[3] Odejdz..."<<endl;
                cin>>karczmaWybor;
                if(karczmaWybor==1)
                {
                    if (Postac.moneta>=5)
                    {
                        cout<<"Zdrow jak ryba"<<endl;
                    Postac.moneta-=5;
                    Postac.zycie=Postac.zycieMax;
                    }
                    else
                        cout<<"Nie stac cie!"<<endl;
                }
                if(karczmaWybor==2)
                {
                    short stawka(0);
                    cout<<"Wybierz stawke badz odejdz..."<<endl;
                    cout<<"[1] Stawiam 5   monet"<<endl;
                    cout<<"[2] Stawiam 10  monet"<<endl;
                    cout<<"[3] Stawiam 15  monet"<<endl;
                    cout<<"[4] Stawiam 25  monet"<<endl;
                    cout<<"[5] Stawiam 50  monet"<<endl;
                    cout<<"[6] Stawiam 100 monet"<<endl;
                    cout<<"Kazdy inny wybor wycofuje cie z rozgrywki..."<<endl;
                    cin>>wybor;
                    switch (wybor)
                    {
                    case 1:
                        if(Postac.moneta>=5)
                        {
                            Postac.moneta-=5;
                            stawka = 5;
                        }
                        else
                            cout<<"Nie masz tyle monet... :D"<<endl;
                        break;
                    case 2:
                        if(Postac.moneta>=10)
                        {
                            Postac.moneta-=10;
                            stawka = 10;
                        }
                        else
                            cout<<"Nie masz tyle monet... :D"<<endl;
                        break;
                    case 3:
                        if(Postac.moneta>=15)
                        {
                            Postac.moneta-=15;
                            stawka = 15;
                        }
                        else
                            cout<<"Nie masz tyle monet... :D"<<endl;
                        break;
                    case 4:
                        if(Postac.moneta>=25)
                        {
                            Postac.moneta-=25;
                            stawka = 25;
                        }
                        else
                            cout<<"Nie masz tyle monet... :D"<<endl;
                        break;
                    case 5:
                        if(Postac.moneta>=50)
                        {
                            Postac.moneta-=50;
                            stawka= 50;
                        }
                        else
                            cout<<"Nie masz tyle monet... :D"<<endl;
                        break;
                    case 6:
                        if(Postac.moneta>=100)
                        {
                            Postac.moneta-=100;
                            stawka= 100;
                        }
                        else
                            cout<<"Nie masz tyle monet... :D"<<endl;
                        break;
                    default:
                        stawka=0;
                        break;
                    }
                    if(stawka>0)
                    {
                        void kosci();
                    }
                }
            }
    }

Czy można zrobić NPC tak by miał opcje handlu i dialogi w plikach? Mapa jest wczytywana z pliku i chwilowo działa na zasadzie czy dany element tablicy jest scianą czy nie czyli mapa składa się z zer i jedynek. Jak zrobić by przy okazji nie spradzać pozycji npc poprzez ify jak wyżej.
« Ostatnia zmiana: Listopad 07, 2015, 00:49:59 wysłana przez Xion »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Xender

  • Użytkownik

  • +1
# Listopad 06, 2015, 23:44:51
Czy można zrobić NPC tak by miał opcje handlu i dialogi w plikach?
Można, ale C++ nie ma na to gotowca w bibliotece standardowej.

Szkic możliwego rozwiązania:
- Jakaś struktura danych w programie, mapująca identyfikatory na linie dialogowe - np. C++-owe std::map<std::string, std::string>.
- Odwoływanie się do tej struktury przy wyświetlaniu, np. dialogs["tavern-welcome"].
- Wypełnianie tej struktury danych z pliku przy starcie gry/poziomu.

Przykładowe konkretne formaty danych i/lub biblioteki do ich obsługi:
- Plik tekstowy z liniami w formacie <identyfikator> ':' <linia dialogowa>, gdzie identyfikator np. składa się tylko ze znaków alfanumerycznych, a tekst po dwukropku do końca linii to linia dialogowa. (Użyj std::getline(std::istream&, std::string&), nie in >> jakiś_string, operator >> na istream i stringach to w ogóle jakaś katastrofa...)
- Popularne ogólnego użytku tekstowe formaty danych jak INI, JSON, YAML, XML - w kolejności wzrastającej złożoności. Przy czym XML-a generalnie nie lubię i nie polecam.
- GNU Gettext (ew. inna implementacja) - dość złożony, stworzony specjalnie do tłumaczeń (co wyróżnia go od poprzedników). Z fajnych rzeczy, obsługuje odmianę przez liczby (można też na tej bazie próbować dohaczyć odmianę przez przypadki), np. "1 teges", "2,3,4 tegesy", "5 i więcej tegesów". Jeśli Cię zainteresuje, mogę opisać szczegóły.

Jak zrobić by przy okazji nie spradzać pozycji npc poprzez ify jak wyżej.
Zrobić osobny kontener (polecam std::vector) z obiektami ruchomymi i/lub nie będącymi częścią terenu, sprawdzać kolizje/interakcje ze wszystkimi takimi obiektami w pętli, po sprawdzeniu kolizji/interakcji z mapą terenu.

Przykładowy tutorial jak zaimplementować grę z terenem i obiektami ruchomymi: https://www.youtube.com/playlist?list=PLB54F0A8D6792DB82


Poza tym klasyka, czyli:

- Okropna duplikacja kodu w switch-case. Najpierw wydziel to do funkcji, jeśli potem w podobnych miejscach wyboru powstanie więcej podobnych funkcji, pomyśl, jak dalej wyeliminować duplikację. Zasada DRY, takie tam.

- Nazwy zmiennych/identyfikatory raczej powinny być po angielsku.

Kod: (cpp) [Zaznacz]
                    if(stawka>0)
                    {
                        void kosci();
                    }

Ten fragment prawie na pewno nie powinien tak wyglądać, choć jest składniowo poprawny.
To jest deklaracja funkcji w zasięgu bloku if, czyli bardzo lokalnym.
Wywołanie wyglądałoby kosci();, (lub rzadziej spotykane (void) kosci(); - to jeśli kosci zwraca jakąś wartość, a Ty chcesz ją zignorować explicite, np. żeby kompilator nie raportował ostrzeżeń o ignorowanej wartości).

Powodzenia.
« Ostatnia zmiana: Listopad 06, 2015, 23:50:21 wysłana przez Xender »

Offline maro

  • Użytkownik

# Listopad 07, 2015, 00:24:53
Zastanów się jak zaprojektować kod, tak żeby oddzielić silnik gry od danych (zawartości gry).

Np. silnik (zarządzanie grą: mapą, obiektami w grze, dialogami, questami)
dane (np. plik tekstowy z mapą, plik xml z drzewem dialogów, skrypty, itd)

Najlepiej poszukaj źródeł podobnych gier, zobacz jak są zbudowane. W tym momencie ciężko doradzić coś więcej.




Offline Krzysiek K.

  • Redaktor
    • DevKK.net

  • +2
# Listopad 07, 2015, 12:43:45
Cytuj
plik xml z drzewem dialogów
Jeśli nie planujesz pisać edytora i edytować to ręcznie, to są dużo lepsze i prostsze formaty do tego celu (np. JSON). Można by też pomyśleć np. o GML (format tekstowy do zapisu grafów) z uwagi na to, że są do tego darmowe edytory (np. yEd) gdzie w takiej sytuacji graf dialogów sobie po prostu wyklikasz.

Offline Lars Kormak

  • Użytkownik

# Listopad 08, 2015, 14:01:35
Jeśli chodzi o wyklikiwanie dialologów, to polecam to narzędzie: http://etodd.io/2014/05/16/the-poor-mans-dialogue-tree/