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ć. |
Dawidsoni |
» 2012-09-03 17:14:12 Animacja.h: 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: 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: 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: 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: 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. |