tBane Temat założony przez niniejszego użytkownika |
System Zadań/Misji w grze » 2024-08-02 20:02:20 Witam. Napisałem prosty system zadań/misji w mojej grze 2D RPG. Czy jest to dobra metoda ? #ifndef Quests_hpp #define Quests_hpp
enum class questCondition { currentHP, showDialogue, haveArmor, haveHelmet, havePants, position_x, position_y }; enum class questState { unstarted, actual, ended };
class Step { public: questCondition condition; string value; Step( questCondition condition, string value ) { this->condition = condition; this->value = value; } bool check() { if( condition == questCondition::currentHP ) { if( player->HP >= atoi( value.c_str() ) ) return true; } if( condition == questCondition::showDialogue ) { setDialogue( atoi( value.c_str() ) ); return true; } if( condition == questCondition::haveArmor ) { if( value == "true" ) { if( player->armor != nullptr ) return true; } if( value == "false" ) { if( player->armor == nullptr ) return true; } } if( condition == questCondition::haveHelmet ) { if( value == "true" ) { if( player->helmet != nullptr ) return true; } if( value == "false" ) { if( player->helmet == nullptr ) return true; } } if( condition == questCondition::havePants ) { if( value == "true" ) { if( player->pants != nullptr ) return true; } if( value == "false" ) { if( player->pants == nullptr ) return true; } } if( condition == questCondition::position_x ) { if( abs( player->position.x - atoi( value.c_str() ) ) < 50 ) { return true; } } if( condition == questCondition::position_y ) { if( abs( player->position.y - atoi( value.c_str() ) ) < 50 ) { return true; } } return false; } };
class Quest { public: int id; string name; questState state; std::vector < Step * > steps; int currentStep; Quest( int id, string name ) { this->id = id; this->name = name; steps.clear(); state = questState::unstarted; currentStep = 0; } void addStep( questCondition condition, string value ) { Step * step = new Step( condition, value ); steps.push_back( step ); } void check() { if( currentStep >= steps.size() - 1 ) state = questState::ended; if( steps[ currentStep ]->check() ) currentStep++; } };
std::vector < Quest * > quests;
void loadQuests() { quests.clear(); Quest * quest1 = new Quest( 0, "Zjedz coś, ubierz się a potem pójdź w wyznaczone miejsce" ); quest1->addStep( questCondition::currentHP, "40" ); quest1->addStep( questCondition::showDialogue, "13" ); quest1->addStep( questCondition::haveArmor, "true" ); quest1->addStep( questCondition::haveHelmet, "true" ); quest1->addStep( questCondition::havePants, "true" ); quest1->addStep( questCondition::showDialogue, "14" ); quest1->addStep( questCondition::position_x, "2750" ); quest1->addStep( questCondition::position_y, "340" ); quest1->addStep( questCondition::showDialogue, "15" ); quest1->state = questState::actual; quests.push_back( quest1 ); }
void checkQuests() { for( auto & quest: quests ) { if( quest->state == questState::actual ) { quest->check(); } } }
#endif
|
|
pekfos |
» 2024-08-03 18:25:19 To bardziej Quest pasuje do "kroku" w zadaniu, bo te warunki to chyba powinny być wszystkie spełnione naraz? Te przykładowe zadanie mówi że masz założyć przedmioty (możesz od razu zdjąć), następnie udać się na pozycję x~2750, potem y~340, niekoniecznie naraz. Więc jeśli ma tam na ciebie czekać zasadzka, to własną pozycję X możesz wybrać tak by cię tam akurat nie było. Nie takie exploity już gracze znajdowali. Poza tym te zadania są z definicji liniowe. Jeżeli dialog ma tu jakieś opcje, to musiałby być ostatni w zadaniu i aktywować jedno z możliwych kontynuacji zadań i to w każdym możliwym przypadku, inaczej zadanie urwie się bez możliwości wznowienia. if( condition == questCondition::havePants ) { if( value == "true" ) { if( player->pants != nullptr ) return true; } if( value == "false" ) { if( player->pants == nullptr ) return true; } } A jak nie będzie ani jedno ani drugie, to kicha? Powinieneś już wiedzieć lepiej niż kopiować kod, to powinno wyglądać tak: if( condition == questCondition::havePants ) { return compareConditionBoolean( value, player->pants != nullptr ); } |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-08-04 14:48:13 Jak nie będzie ani jedno ani drugie wtedy zwraca false. Position_x i position_y zastąpiłem zwykłym position. quest1->addStep( questCondition::position, "2750 340", L"powinienem iść wzdłóż ścieżki" );
|
|
pekfos |
» 2024-08-04 22:46:40 Jak nie będzie ani jedno ani drugie wtedy zwraca false. Czyli kicha, bo warunek jest zawsze fałszywy i pewnie wyjdzie to dopiero w praniu. Nigdy nie polegaj na tym że napis nie będzie miał żadnego typo, bo będzie miał. Od zachowania programu w tym przypadku będzie zależało jak długo będziesz tego szukał. Najlepiej jakby jakiś parser sprawdzał czy napis ma jedną z poprawnych wartości, wtedy wiadomo od razu że jest błąd i gdzie. A jak quest po prostu i po cichu nie zadziała jak dojdziesz do konkretnego punktu, to znacznie gorzej. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-08-04 22:57:26 Nie rozumiem. Na końcu funkcji ustawiłem return false na wypadek, gdyby żaden z warunków nie został spełniony. bool check() { if( condition == questCondition::havePants ) { if( value == "true" ) { if( player->pants != nullptr ) return true; } if( value == "false" ) { if( player->pants == nullptr ) return true; } } return false; }
|
|
pekfos |
» 2024-08-04 23:09:35 Jak się zachowa gra jak havePants będzie miało warunek "flase"? I nie mam na myśli że "zwrócisz false - o, tutaj", tylko jak się gra zachowa jako całość. Bo mi to wygląda na soft lock. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-08-04 23:18:38 Wtedy, quest się dalej nie wykona, bo zwróci false w funkcji check() |
|
« 1 » |