Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML]Animacja sprita

Ostatnio zmodyfikowano 2012-09-04 18:18
Autor Wiadomość
diego997
Temat założony przez niniejszego użytkownika
[SFML]Animacja sprita
» 2012-09-03 15:17:28
Mam pytanie czy do animacji spait'ow powinienem zrobić osobną klasę czy w każdej klasie w której jest obiekt którym chcę poruszać zrobić metodę np animation().



Jeżeli to jest kolejne z pytań w stylu jak zrobić kolizję to przepraszam ;p
P-64300
m4tx
» 2012-09-03 15:27:02
Ja bym zrobił klasę Animation dziedziczącą od Sprite. W konstruktorze by przyjmowała liczbę klatek i definiowała metody takie jak np. SetSpeed(int), Pause(), Stop(), Start(), czy SetLoop(bool).
P-64301
DejaVu
» 2012-09-03 16:09:00
Ja bym nie radził dziedziczyć. Skoro sf::Sprite jest czarną skrzynką, która działa to co najwyżej bym jej używał jako zmienna w klasie CAnimation.
P-64303
Dawidsoni
» 2012-09-03 16:53:03
Ja zrobiłem właśnie takie klasy w SFML:). Zrobiłem tak: klasa abstrakcyjna animacja, i 3 klasy pochodne od niej: anim_klucz, anim_atlas i anim_tl. W klasie anim_klucz (a w zasadzie w szablonie klas) tworzymy animacje tak: podajemy n klatek(każda klatka to czas do następnej klatki, kolor, obrót, pozycja, skala) oraz obiekt, który mamy animować. Typ, którego jest ten obiekt musi mieć zdefiniowane funkcje: (move(x,y), setscale(x,y), getscale(), rotate(r), setcolor(r,g,b,a)). To najlepszy mój typ do animacji, bo można nim animować wszystko. Anim_atlas wczytuje animacje z pliku. Zakłada on, że w pliku jest n obrazów o jednakowym rozmiarze. Dzięki anim_tl możemy animować obiekty klasy Text. Np. liczbę od 0 do 1000 w 2 sekundy, lub wyświetlenie 5 tekstów w 2 sekundy... Do uruchamiania gotowych animacji mam jeszcze klasę animuj. Jak chcesz, to mogę kod ci przesłać.
P-64304
DejaVu
» 2012-09-03 16:55:57
@up: Możesz wstawić kluczowe fragmenty kodu i też będzie si :)
P-64305
Dawidsoni
» 2012-09-03 17:14:12
Animacja.h:
C/C++
namespace dw {
   
    class animacja
    {
    protected:
        float czas;
        friend extern class animuj;
        int numer;
    public:
        animacja()
            : czas( 0 )
            , numer( - 1 )
        { }
        virtual bool aktualizuj( float czas_klatki ) = 0;
        virtual void od_poczatku() = 0;
        int numer_animacji() { return numer; }
        operator int() {
            return numer;
        }
        virtual ~animacja( void ) { }
    };
   
}


Deklaracja anim_atlas i najważniejsza funkcja:


C/C++
template < class typ_obraz, class typ_sprajt >
class anim_atlas
    : public animacja
{
    typ_obraz * obraz;
    typ_sprajt * sprajt;
    int l_kol, l_wier, nr_klatki;
    float czas_an;
   
public:
    anim_atlas()
        : sprajt( NULL )
        , l_kol( 0 )
        , l_wier( 0 )
        , nr_klatki( 1 )
        , czas_an( 0 )
    { };
    anim_atlas( typ_sprajt * sprajt, typ_obraz * obraz, int l_w, int l_k, float cz_an ) throw( logic_error, invalid_argument );
    bool aktualizuj( float czas_klatki );
    void od_poczatku() { czas = 0; }
    void ustaw_klatke( int nr_klatki );
};

template < class typ_obraz, class typ_sprajt >
bool anim_atlas < typ_obraz, typ_sprajt >::aktualizuj( float czas_klatki ) {
    czas += czas_klatki;
    if( czas > czas_an ) czas = czas_an;
   
    if( czas < 0 ) czas = 0;
   
    float klat = czas / czas_an *( l_wier * l_kol );
    klat =( int ) klat + 1;
    if( klat > l_wier * l_kol ) klat--;
   
    if( klat != nr_klatki ) {
        nr_klatki = klat;
        int od_lewej = nr_klatki % l_wier;
        if( od_lewej == 0 ) od_lewej = l_wier;
       
        int od_gory =( nr_klatki - 1 ) / l_wier + 1;
        float x =( float )( od_lewej - 1 ) / l_wier * obraz->getSize().x, y =( float )( od_gory - 1 ) / l_kol * obraz->getSize().y;
        sprajt->setTextureRect( IntRect( x, y,( float )( od_lewej ) / l_wier * obraz->getSize().x - x,
        ( float )( od_gory ) / l_kol * obraz->getSize().y - y ) );
    }
    if( czas == 0 || czas == czas_an ) return true;
   
    return false;
}

Klatka.h:
C/C++
class klatka
{
public:
    bool czy_a, czy_r, czy_g, czy_b;
    float poz_x, poz_y, rozmiar_x, rozmiar_y, obrot, czas_od, k_r, k_g, k_b, k_a;
    klatka( float czas = 0, float x = stale::poprzednia, float y = stale::poprzednia, float r_x = stale::poprzednia, float r_y = stale::poprzednia,
    float o = stale::poprzednia, float kr = stale::poprzednia, float kg = stale::poprzednia, float kb = stale::poprzednia,
    float ka = stale::poprzednia )
        : czas_od( czas )
        , poz_x( x )
        , poz_y( y )
        , rozmiar_x( r_x )
        , rozmiar_y( r_y )
        , obrot( o )
        , k_r( kr )
        , k_g( kg )
        , k_b( kb )
        , k_a( ka )
        , czy_a( false )
        , czy_r( false )
        , czy_g( false )
        , czy_b( false )
    {
        if( czas < 0 )
             throw liczba_ujemna( "CZAS OD POPRZEDNIEJ KLATKI MNIEJSZY OD 0", czas, zmienna( czas ) );
       
    }
    friend ostream & operator <<( ostream & strum, klatka & kl ) {
        strum << kl.czas_od << " " << kl.poz_x << " " << kl.poz_y << " " << kl.rozmiar_x << " " << kl.rozmiar_y << " " << kl.obrot << " "
        << kl.k_r << " " << kl.k_g << " " << kl.k_b << " " << kl.k_a << endl;
        return strum;
    }
    friend istream & operator >>( istream & strum, klatka & kl ) {
        strum >> kl.czas_od >> kl.poz_x >> kl.poz_y >> kl.rozmiar_x >> kl.rozmiar_y >> kl.obrot >> kl.k_r >> kl.k_g >> kl.k_b
        >> kl.k_a;
        return strum;
    }
};


Fragmenty anim_klucz:
C/C++
template < class typ > class anim_klucz
    : public animacja
{
    vector < klatka > wek;
    int ostatnia_klatka;
    typ * obiekt;
    float ps_x, ps_y, czas_k, czas_klatki, odstep_klatki;
    void zastap( int i, float klatka::* wsk ) {
        if( wek[ i + 1 ].* wsk == stale::poprzednia ) wek[ i + 1 ].* wsk = wek[ i ].* wsk;
       
    }
    bool czy_wykonac( float klatka::* wsk ) {
        return wek[ ostatnia_klatka ].* wsk != wek[ ostatnia_klatka + 1 ].* wsk;
    }
    int kolor( float klatka::* wsk, float czas ) {
        return wek[ ostatnia_klatka ].* wsk +( czas / wek[ ostatnia_klatka + 1 ].czas_od *( wek[ ostatnia_klatka + 1 ].* wsk - wek[ ostatnia_klatka ].* wsk ) );
    }
    Color pocz_kolor;
public:
    friend ostream & operator <<( ostream & strum, anim_klucz & anim );
    friend istream & operator >>( istream & strum, anim_klucz & anim );
    void ustaw_obiekt( typ * wsk, Color poczatek_kolor );
    void od_poczatku() {
        czas_k = czas = ostatnia_klatka = 0;
    }
    anim_klucz()
        : czas_k( 0 )
        , ostatnia_klatka( 0 )
        , obiekt( NULL )
        , czas_klatki( 0 )
        , odstep_klatki( 0 )
        , pocz_kolor( 255, 255, 255, 255 )
    { };
    template < class typ_i > anim_klucz( typ_i it_b, int ile, int liczba_klatek, typ * ob = NULL, Color poczatek_kolor = Color( 255, 255, 255 ) );
    bool aktualizuj( float czas_klatki );
};

template < class typ > bool anim_klucz < typ >::aktualizuj( float czas_klat ) {
    czas_klatki += czas_klat;
    if(( czas_klatki > odstep_klatki && czas_klat > 0 ) ||( czas_klatki <- odstep_klatki && czas_klat < 0 ) ) {
        float roznica = 0;
        czas_k += czas_klatki;
        if( czas_k > wek[ ostatnia_klatka + 1 ].czas_od ) {
            roznica = czas_k - wek[ ostatnia_klatka + 1 ].czas_od;
            czas_klatki = czas_klatki -( czas_k - wek[ ostatnia_klatka + 1 ].czas_od );
            czas_k = wek[ ostatnia_klatka + 1 ].czas_od;
        } else if( czas_k < 0 ) {
            roznica = - czas_k;
            czas_klatki = czas_klatki - czas_k;
            czas_k = 0;
        }
        czas += czas_klatki;
        float o_ile = czas_klatki / wek[ ostatnia_klatka + 1 ].czas_od;
        if( czy_wykonac( & klatka::poz_x ) )
             obiekt->move( o_ile *( wek[ ostatnia_klatka + 1 ].poz_x - wek[ ostatnia_klatka ].poz_x ), 0 );
       
        if( czy_wykonac( & klatka::poz_y ) )
             obiekt->move( 0, o_ile *( wek[ ostatnia_klatka + 1 ].poz_y - wek[ ostatnia_klatka ].poz_y ) );
       
        if( czy_wykonac( & klatka::obrot ) )
             obiekt->rotate( o_ile *( wek[ ostatnia_klatka + 1 ].obrot - wek[ ostatnia_klatka ].obrot ) );
       
        if( czy_wykonac( & klatka::rozmiar_x ) )
             obiekt->setScale( obiekt->getScale().x + ps_x *( o_ile *( wek[ ostatnia_klatka + 1 ].rozmiar_x - wek[ ostatnia_klatka ].rozmiar_x ) ), obiekt->getScale().y );
       
        if( czy_wykonac( & klatka::rozmiar_y ) )
             obiekt->setScale( obiekt->getScale().x, obiekt->getScale().y + ps_y *( o_ile *( wek[ ostatnia_klatka + 1 ].rozmiar_y - wek[ ostatnia_klatka ].rozmiar_y ) ) );
       
        if( czy_wykonac( & klatka::k_r ) || czy_wykonac( & klatka::k_g ) || czy_wykonac( & klatka::k_b ) || czy_wykonac( & klatka::k_a ) )
             obiekt->setColor( Color( kolor( & klatka::k_r, czas_k ), kolor( & klatka::k_g, czas_k ), kolor( & klatka::k_b, czas_k ), kolor( & klatka::k_a, czas_k ) ) );
       
        if( czas_k == wek[ ostatnia_klatka + 1 ].czas_od ) {
            if( ostatnia_klatka + 2 == wek.size() )
                 return true;
           
            ostatnia_klatka++;
            czas_k = 0;
            aktualizuj( roznica );
        } else if( czas_k == 0 ) {
            if( ostatnia_klatka == 0 )
                 return true;
           
            ostatnia_klatka--;
            czas_k = wek[ ostatnia_klatka + 1 ].czas_od;
            aktualizuj( - roznica );
        }
        czas_klatki = 0;
    }
    return false;
}


Fragment animuj:
C/C++
class animuj
{
    struct sposob_an {
        sposob_an( int & war )
            : numer( war )
        { }
        mutable animacja * anim;
        mutable float wsp_czas;
        mutable bool ostatnia, czy_zatrzymana, czy_na_poczatek, czy_minus;
        mutable int ile_razy, ile_juz;
        const int numer;
        sposob_an( animacja * an, float ws, bool ost, int ile, int num, bool czy_na )
            : numer( num )
            , anim( an )
            , wsp_czas( ws )
            , ostatnia( ost )
            , ile_razy( ile )
            , ile_juz( 0 )
            , czy_zatrzymana( false )
            , czy_na_poczatek( czy_na )
            , czy_minus( false )
        { }
        friend bool operator <( const sposob_an & lewy, const sposob_an & prawy ) {
            if( lewy.numer < prawy.numer )
                 return true;
           
            return false;
        }
    };
    set < sposob_an > lista;
    Clock zegar;
    int licz_num;
    set < sposob_an >::iterator ustaw_ob( int numer ) {
        if( lista.size() == 0 )
             throw liczba_mniejsza_lub_rowna_0( "LISTA JEST PUSTA W ANIMUJ W USTAWIANIU OBIEKTU DO WYKONANIA OPERACJI NA ANIMACJI", lista.size(), zmienna( lista.size() ) );
       
        set < sposob_an >::iterator it = lista.find( numer );
        if( it == lista.end() )
             throw zly_zakres( "ZLY NUMER ANIMACJI PODANY W USTAWIANIU OBIEKTU DO WYKONYWANIA OPERACJI NA ANIMACJI", numer, zmienna( numer ) );
       
        return it;
    }
    void akt( set < sposob_an >::iterator & it, float czas );
public:
    animuj()
        : licz_num( 0 )
    { }
    static const int nieskonczonosc = - 1;
    void uruchom_animacje( animacja * wsk, float wsp_czas = 1, int ile_razy = 1, bool czy_na_poczatek = true );
    void aktualizuj( float czas );
    void aktualizuj() {
        aktualizuj( zegar.getElapsedTime().asSeconds() );
    }
    void zatrzymaj( int numer ) throw( out_of_range );
    void kontynuuj( int numer ) throw( out_of_range );
    void dalej_lub_stop( int numer ) throw( out_of_range );
    void ustaw_wspolczynnik_czasu( float wsp, int numer ) throw( out_of_range );
    void usun( int numer ) throw( out_of_range );
    void ustaw_ile_razy( int ile, int numer ) throw( out_of_range );
    void ustaw_czas_na( float czas, int numer ) throw( out_of_range );
    void ustaw_na_poczatek_jak_nowy( bool czy, int numer ) throw( out_of_range );
   
};

Mam jeszcze 3 klasy (rzadziej przydatne), ale tyle kodu już zamieściłem, że i tak chyba wszystkiego nie przeczytasz. Gdybyś jednak chciał fragmenty tych klas, to pisz.

Wszystkie klasy to szablony, żeby nadawały się do innych bibliotek niż SFML 2.0. W samym SFML 1.6 mamy już inne nazwy funkcji i niektórych typów, dlatego takie rozwiązanie.

P-64307
waxx
» 2012-09-03 18:05:56
szczerze to wklejony kod to takie spaghetti ze gratuluje jak dziala
raczej przekombinowane do tego co chcesz osiagnac, animacja spritow != interpolacja miedzy danymi / tweenowanie
P-64309
diego997
Temat założony przez niniejszego użytkownika
» 2012-09-03 18:26:52
@Dawidsoni dzięki ale kurcze nie potrafię się jeszcze swobodnie posługiwać klasami abstrakcyjnymi i szablonami więc będę coś kombinować bez używania tego.




@Dejavu Czyli w klasie player ma być sama mechanika poruszania sprit'a bez jego rysowania ? Natomiast obiekt klasy CAnimation ma przejmować referencje do obiektu klasy player ?
P-64311
« 1 » 2
  Strona 1 z 2 Następna strona