11-12-2012, 03:37 PM
Important notice: carnat = tech stuff.
Din cauza bug-ului cu enum-ul si din cauza ca a aparut nevoia unor comportamente custom ale item-urilor, aveam nevoie de o solutie mai buna decat cea de dinainte.
Two hours and a beer later, gasit-am si solutie Am postat aici multi carnati (mai interesanti sau mai putin interesanti), iar dupa mine asta e cel mai interesant de pana acum.
Prima data aveam in plan mosteniri, si cate o clasa per item, avand in vedere ca ar fi fain un comportament flexibil si complet custom, pentru item-uri.
But then... daca ar fi fost 900 de items, am fi avut 900 de clase? That sucks. Prea stangaci si !elegant. Am ajuns la, dupa parerea mea, cea mai buna solutie avand in vedere structura existenta. Si de ce nu, o solutie excelenta din mai toate punctele de vedere. Solutia se bazeaza pe delegates (think pointeri catre functii (C++)).
Puncte forte:
- Structura solutiei este curata, si permite dezvoltarea cu usurinta a comportamentelor custom.
- Nu a fost nevoie sa modific decat o linie de cod din ce aveam deja; solutia s-a "instalat" ca un addon, iar la final am scos ce nu mai trebuia din lucrurile vechi.
- Cand vrem comportament custom, codul nou se rezuma doar la o functie extra implementata.
- Avem libertatea dorita cand vine vorba de comportament custom.
- Aceeasi solutie poate fi folosita la ORICE alt element din joc care utilizeaza comportamente custom. Spre exemplu, putem folosi acelasi sistem pentru a defini: rutine custom pentru fiecare personaj in parte, reactii custom a obiectelor interactive si-asa mai departe. Totul cu 1 singura clasa de baza + 1 metoda.
- Volumul de cod este suficient de scazut, DAR...
- poate fi scazut si mai mult folosind metode comune pentru obiectele deloc diferite. Spre exemplu, 5 mancaruri banale care influenteaza atribute si nimic mai mult, ar putea sa aibe ca si comportament o functie comuna DEFAULT_CONSUME.
Screeny details:
Delegate & base item class:
Se pot adauga usor alte functii delegate, pentru un alt tip de comportament. De exemplu, pentru un eveniment cu totul nou: ridicarea unui obiect.
Vrem sa avem un inel blestemat in ceva cripta uitata, iar in momentul in care jucatorul il ridica de jos, sa primeasca un curse de toata frumusetea care sa-l faca sa uite toate magiile? Ba chiar mai mult, sa inceapa imediat un summon undeads, ca sa se invete minte (jucatorul, nu inelul)? Nimic mai simplu; un delegate special pentru noul eveniment, de exemplu PickUpEvent, si un camp nou in BaseItem, precum OnPickUp.
Mai ramane doar sa implementam functia custom, dupa structura delegate-ului, si sa o atribuim item-ului.
Sample events (consume):
Functiile custom; in imagine doar consume-uri.
Items:
Se observa usurinta cu care se atribuie o functie custom unui item. E basically doar un assign.
Din cauza bug-ului cu enum-ul si din cauza ca a aparut nevoia unor comportamente custom ale item-urilor, aveam nevoie de o solutie mai buna decat cea de dinainte.
Two hours and a beer later, gasit-am si solutie Am postat aici multi carnati (mai interesanti sau mai putin interesanti), iar dupa mine asta e cel mai interesant de pana acum.
Prima data aveam in plan mosteniri, si cate o clasa per item, avand in vedere ca ar fi fain un comportament flexibil si complet custom, pentru item-uri.
But then... daca ar fi fost 900 de items, am fi avut 900 de clase? That sucks. Prea stangaci si !elegant. Am ajuns la, dupa parerea mea, cea mai buna solutie avand in vedere structura existenta. Si de ce nu, o solutie excelenta din mai toate punctele de vedere. Solutia se bazeaza pe delegates (think pointeri catre functii (C++)).
Puncte forte:
- Structura solutiei este curata, si permite dezvoltarea cu usurinta a comportamentelor custom.
- Nu a fost nevoie sa modific decat o linie de cod din ce aveam deja; solutia s-a "instalat" ca un addon, iar la final am scos ce nu mai trebuia din lucrurile vechi.
- Cand vrem comportament custom, codul nou se rezuma doar la o functie extra implementata.
- Avem libertatea dorita cand vine vorba de comportament custom.
- Aceeasi solutie poate fi folosita la ORICE alt element din joc care utilizeaza comportamente custom. Spre exemplu, putem folosi acelasi sistem pentru a defini: rutine custom pentru fiecare personaj in parte, reactii custom a obiectelor interactive si-asa mai departe. Totul cu 1 singura clasa de baza + 1 metoda.
- Volumul de cod este suficient de scazut, DAR...
- poate fi scazut si mai mult folosind metode comune pentru obiectele deloc diferite. Spre exemplu, 5 mancaruri banale care influenteaza atribute si nimic mai mult, ar putea sa aibe ca si comportament o functie comuna DEFAULT_CONSUME.
Screeny details:
Delegate & base item class:
Se pot adauga usor alte functii delegate, pentru un alt tip de comportament. De exemplu, pentru un eveniment cu totul nou: ridicarea unui obiect.
Vrem sa avem un inel blestemat in ceva cripta uitata, iar in momentul in care jucatorul il ridica de jos, sa primeasca un curse de toata frumusetea care sa-l faca sa uite toate magiile? Ba chiar mai mult, sa inceapa imediat un summon undeads, ca sa se invete minte (jucatorul, nu inelul)? Nimic mai simplu; un delegate special pentru noul eveniment, de exemplu PickUpEvent, si un camp nou in BaseItem, precum OnPickUp.
Mai ramane doar sa implementam functia custom, dupa structura delegate-ului, si sa o atribuim item-ului.
Sample events (consume):
Functiile custom; in imagine doar consume-uri.
Items:
Se observa usurinta cu care se atribuie o functie custom unui item. E basically doar un assign.