T-28976 » Prosty System Dialogów » str. 2 z 4 (2024)

AutorWiadomość

tBane

Temat założony przez niniejszego użytkownika

» 2024-06-03 21:37:43

dobra spróbuję.
nie wiem jak to dalej napisać...

Konstruktor DialogueOption:

C/C++

DialogueOption( std::wstring text, int nextDialogueID, std::function < bool() > condition = { } ) {
this->text = text;
this->nextDialogueID = nextDialogueID;
// this->visible = true/false
}

Dialogi:

C/C++

Dialogue * dial5 = new Dialogue( 5, L"Czego chcesz?" );
dial5->options.push_back( DialogueOption( L"Kim jesteś?", 6 ) );
dial5->options.push_back( DialogueOption( L"Co tutaj robisz?", 7 ) );
dial5->options.push_back( DialogueOption( L"Nauczysz mnie czegoś o polowaniu?", 10 ) );
dial5->options.push_back( DialogueOption( L"Mam skórę wilczura, chcesz ją odkupić?", 8,[ ] { return player->bag->hasItemsInInventory( "wolf skin", 1 ); } ) );
dial5->options.push_back( DialogueOption( L"Żegnaj", - 1 ) );
dialogues.push_back( dial5 );Dialogue * dial6 = new Dialogue( 6, L"Jestem myśliwym. Poluję na zwierzynę." );
dial6->options.push_back( DialogueOption( L"Kim jesteś?", 6 ) );
dial6->options.push_back( DialogueOption( L"Co tutaj robisz?", 7 ) );
dial6->options.push_back( DialogueOption( L"Nauczysz mnie czegoś o polowaniu?", 10 ) );
dial6->options.push_back( DialogueOption( L"Mam skórę wilczura, chcesz ją odkupić?", 8,[ ] { return player->bag->hasItemsInInventory( "wolf skin", 1 ); } ) );
dial6->options.push_back( DialogueOption( L"Żegnaj", - 1 ) );
dialogues.push_back( dial6 );Dialogue * dial7 = new Dialogue( 7, L"Obecnie odpoczywam, ale gdy tylko zbiorę siły, ruszę na polowanie." );
dial7->options.push_back( DialogueOption( L"Kim jesteś?", 6 ) );
dial7->options.push_back( DialogueOption( L"Co tutaj robisz?", 7 ) );
dial7->options.push_back( DialogueOption( L"Nauczysz mnie czegoś o polowaniu?", 10 ) );
dial7->options.push_back( DialogueOption( L"Mam skórę wilczura, chcesz ją odkupić?", 8,[ ] { return player->bag->hasItemsInInventory( "wolf skin", 1 ); } ) );
dial7->options.push_back( DialogueOption( L"Żegnaj", - 1 ) );
dialogues.push_back( dial7 );Dialogue * dial8 = new Dialogue( 8, L"Bardzo chętnie, dam ci za nią miksturę leczniczą." );
dial8->options.push_back( DialogueOption( L"Proszę, oto skóra wilczura", 9 ) );
dial8->options.push_back( DialogueOption( L"Może innym razem ... ", 5 ) );
dialogues.push_back( dial8 );Dialogue * dial9 = new Dialogue( 9, L"A to Twoja mikstura." );
dial9->options.push_back( DialogueOption( L"Kim jesteś?", 6 ) );
dial9->options.push_back( DialogueOption( L"Co tutaj robisz?", 7 ) );
dial9->options.push_back( DialogueOption( L"Nauczysz mnie czegoś o polowaniu?", 10 ) );
dial9->options.push_back( DialogueOption( L"Mam skórę wilczura, chcesz ją odkupić?", 8,[ ] { return player->bag->hasItemsInInventory( "wolf skin", 1 ); } ) );
dial9->options.push_back( DialogueOption( L"Żegnaj", - 1 ) );
dialogues.push_back( dial9 );Dialogue * dial10 = new Dialogue( 10, L"Niestety, nie jestem w stanie Cię niczego nauczyć." );
dial10->options.push_back( DialogueOption( L"Kim jesteś?", 6 ) );
dial10->options.push_back( DialogueOption( L"Co tutaj robisz?", 7 ) );
dial10->options.push_back( DialogueOption( L"Nauczysz mnie czegoś o polowaniu?", 10 ) );
dial10->options.push_back( DialogueOption( L"Mam skórę wilczura, chcesz ją odkupić?", 8,[ ] { return player->bag->hasItemsInInventory( "wolf skin", 1 ); } ) );
dial10->options.push_back( DialogueOption( L"Żegnaj", - 1 ) );
dialogues.push_back( dial10 );

P-181176

pekfos

» 2024-06-03 21:49:59

Nagłówek

<functional>

.

Taka myśl: Ja tylko zgaduję jaką grę chcesz zrobić, a wydajesz się skupiać na rozwiązywaniu przykładowych problemów które podaję. Co powiesz na to żeby jednak zrobić to jako jeden wielki switch-case który robi wszystko manualnie zamiast używać obiektowej reprezentacji drzewa dialogów? I tak nadajesz identyfikatory ręcznie, mając switch kompilator przynajmniej sprawdzi ich unikalność. To będzie spaghetti i będzie mało skalowalne, ale: możesz zrobić szybko co*kolwiek, bez potykania się o ograniczenia własnego języka skryptów i obiektowej struktury. Zrób tak trochę reprezentatywnego contentu do gry, jaką chcesz zrobić. Wtedy odpowiedz sobie na pytanie "czy chcę to zrobić bardziej profesjonalnie?" i jeśli tak, "co musi potrafić mój system dialogów/zadań by przeportować istniejący content". Teraz lecisz z rozwiązaniem nie mając wymagań, co wróży refaktor. Robiąc content i (w miarę potrzeb) system równolegle, każda zmiana systemu będzie robiona z myślą "jak to zrobić najprościej" i "jak nie zepsuć wszystkiego innego", co zwykle oznacza hack i prowizorkę.

tBane

Temat założony przez niniejszego użytkownika

» 2024-06-03 21:55:42

Skrypty i tak będą, bo zamierzam trochę więcej opcji dodać, ale zaintrygowałeś mnie tą lambdą i jednak chcę się jej nauczyć.

Dodałem nagłówek <functional>.
Jak teraz przetworzyć tę lambdę ?

P-181178

pekfos

» 2024-06-03 22:12:09

Po pierwsze, jak menu ma być zduplikowane, to wcale nie znaczy że kod musi być zduplikowany. Łatwiej będzie to zmieniać (i mi na to patrzeć).

C/C++

std::vector < DialogueOption > menuHandlarza;
menuHandlarza.emplace_back( L"Kim jesteś?", 6 ); // emplace_back(XXX) równoważne do push_back(TypElementu(XXX))
menuHandlarza.emplace_back( L"Co tutaj robisz?", 7 );
menuHandlarza.emplace_back( L"Nauczysz mnie czegoś o polowaniu?", 10 );
menuHandlarza.emplace_back( L"Mam skórę wilczura, chcesz ją odkupić?", 8,[ ] { return player->bag->hasItemsInInventory( "wolf skin", 1 ); } );
menuHandlarza.emplace_back( L"Żegnaj", - 1 );Dialogue * dial9 = new Dialogue( 9, L"A to Twoja mikstura." );
dial9->options = menuHandlarza;
dialogues.push_back( dial9 );Dialogue * dial10 = new Dialogue( 10, L"Niestety, nie jestem w stanie Cię niczego nauczyć." );
dial10->options = menuHandlarza;
dialogues.push_back( dial10 );

Utwórz pole typu

std::function<bool()>

w

DialogueOption

i po prostu przypisz w konstruktorze.

C/C++

DialogueOption( std::wstring text, int nextDialogueID, std::function < bool() > condition = { } ) {
this->text = text;
this->nextDialogueID = nextDialogueID;
this->condition = condition;
// this->visible = true/false
}

Kod na sprawdzenie warunku już podałem wcześniej:

C/C++

for( auto & option: dial->options )
{
if( option.condition && !option.condition() )
continue; // Warunek ustawiony i zwraca false = pomiń

effectiveOptions.push_back( option );
}

Sugeruję jednorazowo utworzyć kopię opcji które mają być wyświetlone, bo wtedy łatwo jest stwierdzić na przykład ile ich jest, bez konieczności sprawdzania warunków bez przerwy. Nie wiem jak wygląda kod obsługi tych dialogów, ale przefiltrowane

effectiveOptions

powinno dać się łatwo zintegrować.

Jak teraz przetworzyć tę lambdę ?

Nie musisz wiedzieć nic o niej. Wszystko to jest ukryte przez

std::function<>

.

C/C++

#include <iostream>
#include <functional>
int four() { return 4; }void test( std::function < int() > f = { } )
{
if( f )
std::cout << "returned: " << f() << '\n';
else
std::cout << "not set\n";

}int main()
{
test( four );
test([ ] { return 123; } );
test();
}

returned: 4
returned: 123
not set

P-181179

tBane

Temat założony przez niniejszego użytkownika

» 2024-06-03 22:23:49

Dobra. Działa. Funkcja renderująca chooseBox.

C/C++

void renderChooseBox( sf::RenderWindow * window ) {
sf::Texture dialogBoxTexture;
if( !dialogBoxTexture.loadFromFile( "assets/GUI/DialogBoxTexture.png" ) ) {
return;
}

sf::Sprite background;
background.setTexture( dialogBoxTexture );
background.setOrigin( dialogSize.x / 2.0f, dialogSize.y / 2.0f );
background.setPosition( view.getCenter().x, view.getCenter().y + screenHeight / 2.0f - dialogSize.y / 2.0f );
window->draw( background );


availableOptions.clear();
for( auto & o: currentDialogue->options ) {
if( o.condition && !o.condition() )
continue;

availableOptions.push_back( o );
}

for( int i = 0; i < availableOptions.size(); i++ ) {

sf::Text text = sf::Text( availableOptions[ i ].text, dialogBoxFont, characterSize );
if( i == chooseOption )
text.setFillColor( sf::Color( 255, 201, 14 ) );
else
text.setFillColor( textColor );

textPosition.x = background.getPosition().x - dialogSize.x / 2.f + padding;
textPosition.y = background.getPosition().y - dialogSize.y / 2.f + float( i ) * lineHeight + padding;
text.setPosition( textPosition );

window->draw( text );

}


}


T-28976 » Prosty System Dialogów » str. 2 z 4 (1)

P-181180

pekfos

» 2024-06-03 22:49:55

Po tym jako konstruujesz dialogi w kodzie spodziewałem się że to co mówi NPC będzie widoczne razem z opcjami do wyboru. Miałoby sens dla kontekstu, a nie że gracz niecierpliwie pomija dialogi i nagle ma wybór "TAK/NIE" i wtedy uuhh... ;) Ale skoro wyświetlasz albo jedno, albo drugie, tym bardziej bym rozdzielił mowę NPC od wyborów gracza by nie duplikować rzeczy. Przykładowo konkretny numer "dialogu" mógłby się odnosić albo do

  • wyboru gracza, gdzie każda opcja prowadzi do stanu o innym (lub nie) numerze,
  • mowy NPC na którą gracz musi kliknąć "dalej" i jest jeden numer następnego stanu,
  • albo do czegoś zupełnie nie od parady. Meteor uderza w ziemię w czasie rozmowy. Jak się animacja skończy to przechodzimy do następnego stanu.

To ubrać w hierarchię klas by można było wszystko wrzucić do jednego kontenera.

No ale wychodzę tu trochę w system zadań, bo uważam że to ściśle powiązany temat. No chyba że dialogi to dwóch aktorów stojących na baczność i wymieniających zdania, a co*kolwiek ciekawszego będzie musiało zaczekać na koniec rozmowy i być zaimplementowane zupełnie niezależnym mechanizmem?

P-181181

tBane

Temat założony przez niniejszego użytkownika

» 2024-06-03 23:11:58

Mogę wyświetlać ostatni fragment wypowiedzi boota, z tym nie będzie problemu. Ale uważam, że obecna opcja jest wystarczająca :-)

P-181182

pekfos

» 2024-06-03 23:13:42

To ty masz wizję na tą grę, ja tylko zgaduję :)

P-181183

1 « 2 » 3 4
T-28976 » Prosty System Dialogów » str. 2 z 4 (2024)
Top Articles
Latest Posts
Article information

Author: Terence Hammes MD

Last Updated:

Views: 6097

Rating: 4.9 / 5 (69 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Terence Hammes MD

Birthday: 1992-04-11

Address: Suite 408 9446 Mercy Mews, West Roxie, CT 04904

Phone: +50312511349175

Job: Product Consulting Liaison

Hobby: Jogging, Motor sports, Nordic skating, Jigsaw puzzles, Bird watching, Nordic skating, Sculpting

Introduction: My name is Terence Hammes MD, I am a inexpensive, energetic, jolly, faithful, cheerful, proud, rich person who loves writing and wants to share my knowledge and understanding with you.