[ glorius @ 17.05.2014. 15:11 ] @
Dizajniram neku platformicu gde je protagonista vitez koji skakuce po platformama, moze da napadne macem i da baci po koju magiju.
Koristim SFML, Box2D i LUA.

Imam baznu klasu Actor za sve sto se vidi (ili ne vidi - box2d senzori) u Levelu i nju sam dizajnirao na sledeci nacin:

Code:


class DActor :
    public DObject
{
public:
    enum Properties
    {
        Position, 
        Angle, 
        ActorProperty = 1000
    };

    DActor(void);
    ~DActor(void);
private:
    Property<sf::Vector2f> m_pos;
    Property<float> m_fAngle;

    DComponent* m_pGraphicsComponent;
    DComponent* m_pPhysicsComponent;
    DComponent* m_pBehaviorComponent;
};



m_pGraphicsComponent sadrzi mapu sprajtova tako da je menjanje trenutne animacije/staticne slike enkapsulirano u toj komponenti.
m_pPhysicsComponent sadrzi b2Body za trenutni sprajt (box2D je tako napravljen da ako menjam trenutni sprajt moram da izbrisem b2Body proslog sprajta iz b2World-a pa da kreiram novi za sprajt koji trenutno postavljam)
m_pBehaviorComponent - upravljanje kretanjem, AI... moze biti hardcode-ovano u engine-u ili implementirano preko LUA skripte

Zvuci poznato? Ovaj koncept komponenti sam ukrao iz Unity :)

Sve ovo, bar meni, deluje kao stabilan dizajn, komponente mogu da saradjuju jedna sa drugom (Actor je neka vrsta Mediator patterna za komponente, svaka komponenta ima referencu na Actor tako da moze da pristupi drugim komponentama preko njega).

Ono sto ovde fali su State-ovi aktora. States koji bi Player (vitez) imao su: Attacking, Jumping, CastMagic, Idle (kada stoji), Walking, Dieing, ...

Imam klasu AbstractState i StateManager:

Code:


class DStateManager;

class DAbstractState :
    public DObject
{
public:
    ~DAbstractState();

    virtual void enter();
    virtual void exit();

    virtual void update(float dt) = 0;
protected:
    DAbstractState(DStateManager& stateManager);
private:
    DStateManager& m_stateManager;
};

class DStateManager : public DObject
{
    typedef std::map<std::string, DAbstractState*> States;
public:
    DStateManager();
    ~DStateManager();

    void registerState(const std::string& stateId, DAbstractState* pState);
    void changeState(const std::string& stateId);
    void changeState(DAbstractState* pState);

    DAbstractState* currentState();
private:
    DAbstractState* m_pCurrentState;
    States m_states;
};



StateManager moze da bude member Actora i kada se promeni iz Walking u Attacking ja komponente updateujem tako sto svaka komponenta ima mapu ciji je id isti kao id state-a:

GraphicsComponent ima mapu spriteova i onda pozovem changeSprite(stateId).
Isto i za ostale komponente.
BehaviorComponent moze iz lua skripte da menja state-ove, npr.

Problem koji imam je da dizajniram kombinovanje state-ova ali da dizajn ne bude messy.
Sta ako actor radi Attack ili CastMagic dok je u Jumping State?
Mogu da stavim u Jumping state bool bIsAttacking i bool bIsJumping ali mi to deluje kao ruzno resenje.
Ono sto mi pada na pamet je da mozda JumpingState ima member StateManager koji moze da ima Stateove Attacking i CastMagic. Ili da se uvede parent-child mehanizam za states. Ili da u Actor imam jos jedan StateManager pa da kombinujem nekako sa glavnim stateManagerom...
Ono sto mi treba je koliko toliko elegantno resenje.
Da li ste mozda imali iskustva sa ovim, svaki savet je dobrodosao :)
[ Rapaic Rajko @ 18.05.2014. 12:46 ] @
Mislim da moras malo drugacije da uradis States. Posao si od toga da objekat ima uvek samo jedno stanje, pa si naknadno uvideo da su moguce i kombinacije stanja.

Znaci, mora da postoji lista stanja (set). Pa prema tome, metode

Code:

    void changeState(const std::string& stateId);
    void changeState(DAbstractState* pState);


se menjaju u

Code:

    void addState(const std::string& stateId);
    void addState(DAbstractState* pState);
    //novo
    void removeState(const std::string& stateId);
    void removeState(DAbstractState* pState);


U metodama addState() radis proveru kombinacija stanja koje su dozvoljene, odnosno onemogucavas kombinacije koje su nelogicne ili nemoguce.
Mislim da je ovo pravi nacin, jer - sta ako imas kombinaciju (npr.) Attacking + Jumping + CastMagic? Kao iz legendarne UnrealTournament: pod stitom si, skaces i pucas, sve u jedan mah :).

Pozz