Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Autor: Piotr Szawdyński
Biblioteki C++

Tworzenie i wyświetlanie sprajtów

[lekcja] Rozdział 7. W niniejszym rozdziale: co to jest sprajt w bibliotece SFML oraz jak działa; jak skojarzyć grafikę ze sprajtem oraz jak wyświetlić sprajta. Ponadto w rozdziale zostały omówione ważniejsze metody klasy » SFML 1.6Sprite oraz opisano inne użyteczne zagadnienia związane ze sprajtami.
Rysujmy... Rysujmy. Rysujmy! Tak! Rysujmy, ale nie w paincie i nie kredkami :) W tym rodziale zajmiemy się rysowaniem, malowaniem czy też jak to się przyjęło w świecie programistów wyświetlaniem sprajtów na ekranie :)

Co to jest sprajt i jak on działa w SFML?

Sprajt w bibliotece SFML jest to klasa za pomocą której mamy możliwość rysowania obrazów 2D na ekranie. Sprajt jest klasą 'lekką', czyli taką którą możemy beztrosko tworzyć dla każdego obiektu, który zechcemy wyświetlić bez ponoszenia istotnego kosztu pamięciowego jak również bez istotnej utraty na szybkości aplikacji. Sukces ten zawdzięczamy przede wszystkim konstrukcji klasy » SFML 1.6Sprite, która zamiast kopiować obraz, który będzie wyświetlała - trzyma uchwyt do obrazu. Dzięki temu możliwe jest wielokrotne wyświetlenie tego samego obrazu na scenie minimalnym kosztem pamięciowym.

Tworzenie sprajta

Skoro podstawową wiedzę o sprajtach w SFML już masz to nic nie szkodzi na przeszkodzie aby się nauczyć pracować ze sprajtami. Zacznijmy najpierw od utworzenia pustego sprajta:
C/C++
sf::Sprite naszSprajt;

Obsługa sprajta

Klasa » SFML 1.6Sprite dziedziczy po klasie sf::Drawable, dostarczając tym samym serię metod które warto zapamiętać, bowiem często i gęsto będą się przydawały podczas wytwarzania gier. Metody o których mowa służą bowiem do ustalania położenia sprajta, obrotu, skalowania i innych cudów związanych z przekształcaniem obrazu, który ma być wyświetlany. Przytoczę tu te najczęściej używane, a resztę zawsze możesz doczytać sobie w dokumentacji. Oto one:
Dokumentacja
SetXUstawia nowe położenie sprajta w osi X. (metoda)
SetYUstawia nowe położenie sprajta w osi Y. (metoda)
SetPositionUstawia nowe położenie sprajta. (metoda)
SetRotationUstawia nowy kąt o jaki ma być obrócony obiekt. (metoda)
SetCenterUstawia nową pozycję środka obiektu. (metoda)
SetScaleXUstawia mnożnik przeskalowania sprajta w osi X. (metoda)
SetScaleYUstawia mnożnik przeskalowania sprajta w osi Y. (metoda)
SetScaleUstawia mnożniki przeskalowania obiektu w osiach X i Y. (metoda)
MovePrzesuwa sprajta na nową pozycję względem aktualnego położenia. (metoda)
RotateObraca obiekt o kąt wyrażony w stopniach. (metoda)
Pełną listę metod znajdziesz w dokumentacji klasy » SFML 1.6Sprite. O powyższych funkcjach warto poczytać oczywiście w dokumentacji byś mógł poczuć się w pełni usatysfakcjonowany, niemniej jednak teraz skupmy się na najważniejszym aspekcie, tj. na narysowaniu obrazka na ekranie :)

Skojarzenie grafiki ze sprajtem

Zanim nasz sprajt z obrazkiem zostanie wyświetlony to najpierw wypadałoby skojarzyć jakąś grafikę ze sprajtem. Do tego celu należy wykorzystać metodę » SFML 1.6 » SpriteSetImage należącą do klasy » SFML 1.6Sprite. Za pomocą metody » SFML 1.6 » SpriteSetImage przekazujemy obraz, który ma być skojarzony ze sprajtem.

Pamiętaj, że obraz musi być trzymany w pamięci tak długo jak długo chcemy go wyświetlać.

Rysowanie sprajta

W celu wyświetlenia przygotowanego wcześniej sprajta na ekranie należy wywołać metodę Draw należącą do klasy sf::RenderWindow. Metoda Draw przyjmuje jako argument obiekt typu sf::Drawable, a ponieważ klasa » SFML 1.6Sprite dziedziczy właśnie po klasie sf::Drawable to możliwe jest (i jest jak najbardziej prawidłowe) przekazanie obiektu typu » SFML 1.6Sprite jako argument do metody Draw. Wyświetlenie sprajta będzie więc wyglądało tak:
C/C++
sf::Sprite naszSprajt;
//...
oknoAplikacji.Draw( naszSprajt );

Przykład

Podsumujmy wiedzę, którą zebraliśmy do tej pory na temat sprajtów i zobaczmy jak będzie wyglądał przykład wyświetlający sprajta na ekranie:
C/C++
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow oknoAplikacji( sf::VideoMode( 800, 600, 32 ), "Kurs SFML - http://cpp0x.pl" );
    sf::Image obrazek;
    obrazek.LoadFromFile( "ludek.png" );
   
    sf::Sprite naszSprajt;
    naszSprajt.SetImage( obrazek );
    naszSprajt.SetPosition( 400, 300 );
    naszSprajt.SetScale( 5, 5 );
   
    while( oknoAplikacji.IsOpened() )
    {
        sf::Event zdarzenie;
        while( oknoAplikacji.GetEvent( zdarzenie ) )
        {
            if( zdarzenie.Type == sf::Event::Closed )
                 oknoAplikacji.Close();
           
        }
       
        const sf::Input & sterowanie = oknoAplikacji.GetInput();
        if( sterowanie.IsKeyDown( sf::Key::Left ) )
             naszSprajt.Move( - 0.2, 0 );
       
        if( sterowanie.IsKeyDown( sf::Key::Right ) )
             naszSprajt.Move( + 0.2, 0 );
       
        if( sterowanie.IsKeyDown( sf::Key::Up ) )
             naszSprajt.Move( 0, - 0.2 );
       
        if( sterowanie.IsKeyDown( sf::Key::Down ) )
             naszSprajt.Move( 0, + 0.2 );
       
        oknoAplikacji.Clear( sf::Color( 255, 0, 0 ) );
        oknoAplikacji.Draw( naszSprajt );
        oknoAplikacji.Display();
    }
    return 0;
}

Trochę więcej o sprajcie

Skoro mamy już jakieś podstawy na temat sprajtów i udało nam się wyświetlić obraz na ekranie to nie oznacza to wcale, że możemy zakończyć już naszą edukację na temat sprajtów w SFML. Warto bowiem poświęcić jeszcze trochę czasu aby zgłębić lepiej tajniki klasy » SFML 1.6Sprite. Klasa ta jest bowiem naszym panaceum na wszelkie ewentualne problemy związane z wyświetlaniem grafiki.

Barwy i przeźroczystość sprajta

Jeżeli masz potrzebę zmienić sposób wyświetlania barw sprajta, bądź zmienić poziom jego przeźroczystości to z pomocą przyjdzie Ci metoda » SFML 1.6 » SpriteSetColor. Umożliwia ona bowiem zmianę natężenia barw renderowanego sprajta jak również zmianę jego poziomu przeźroczystości. Dokumentacja, która jest dostępna na łamach niniejszego serwisu wyjaśnia wyczerpująco działanie metody » SFML 1.6 » SpriteSetColor dlatego też pozwolę sobie w tym miejscu zakończyć jej opisywanie :)

Rzeczywista pozycja sprajta

Sprajt od chwili jego utworzenia do wyświetlenia ulega licznym transformacjom. Tymi transformacjami mogą być np. skala, położenie, zmiana punktu centralnego sprajta wokół którego dokonujemy jego obrotu czy też sam obrót. O ile takie zachowanie jest dla nas naturalne i oczekiwane to czasem zachodzi potrzeba ustalenia czy np. kursor myszy znajduje się nad obracanym obiektem czy też nie. Samodzielne obliczanie pozycji faktycznej pozycji sprajta byłoby uciążliwe i z pewnością mało praktyczne. Twórcy biblioteki SFML przewidzieli to i utworzyli do tego celu metody, które dokonają takich obliczeń za nas. Tymi metodami są:
Dokumentacja
TransformToGlobalKonwertuje lokalne współrzędne do golbalnych współrzędnych. (metoda)
TransformToLocalKonwertuje globalne współrzędne do lokalnych współrzędnych. (metoda)
Jeżeli będziemy chcieli ustalić czy nad sprajtem znajduje się kursor myszy to wystarczy, że dokonamy odpowiedniej transformacji za pomocą jednej z powyższych metod. Przykładowy kod może wyglądać tak:
C/C++
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow oknoAplikacji( sf::VideoMode( 800, 600, 32 ), "Kurs SFML - http://cpp0x.pl" );
   
    //Utworzenie białego obrazka i wykonanie przekształceń na sprajcie
    sf::Image obrazek;
    obrazek.Create( 30, 60, sf::Color::White );
    sf::Sprite naszSprajt;
    naszSprajt.SetImage( obrazek );
    naszSprajt.SetPosition( 400, 300 );
    naszSprajt.SetScale( 5, 5 );
    naszSprajt.SetCenter( obrazek.GetWidth() / 2.0f, obrazek.GetHeight() / 2.0f );
    naszSprajt.SetColor( sf::Color( 0x00, 0xff, 0x00, 0x80 ) );
   
    while( oknoAplikacji.IsOpened() )
    {
        sf::Event zdarzenie;
        while( oknoAplikacji.GetEvent( zdarzenie ) )
        {
            if( zdarzenie.Type == sf::Event::Closed )
                 oknoAplikacji.Close();
           
        } //while
       
        oknoAplikacji.Clear( sf::Color::Black );
        naszSprajt.Rotate( 0.01f );
       
        //Tu sprawdzanie czy mysz jest nad sprajtem czy nie oraz modyfikowanie jego koloru
        const sf::Input & sterowanie = oknoAplikacji.GetInput();
        sf::Vector2f punkt = naszSprajt.TransformToLocal( sf::Vector2f(( float ) sterowanie.GetMouseX(),( float ) sterowanie.GetMouseY() ) );
        bool bCzyZaznaczony =( punkt.x >= 0 && punkt.y >= 0 && punkt.x <= obrazek.GetWidth() && punkt.y <= obrazek.GetHeight() );
        naszSprajt.SetColor( bCzyZaznaczony ? sf::Color::Green: sf::Color::Red );
       
        oknoAplikacji.Draw( naszSprajt );
        oknoAplikacji.Display();
    } //while
    return 0;
}

Rzeczywista pozycja myszki

Jeżeli uruchomiłeś wcześniejszy program demonstrujący działanie metody » SFML 1.6 » SpriteTransformToLocal to zapewne zauważyłeś, że wszystko zadziałało tak jak chcieliśmy - po najechaniu myszką na prostokąt zmienił on swój kolor. Problem się pojawi jednak gdy zmienisz rozmiar okna - wówczas pozycja myszki zacznie się 'rozjeżdżać' z obrazem, w wyniku czego program zacznie działać po prostu źle. Rozwiązaniem tego problemu jest metoda ConvertCords, która należy do klasy sf::RenderWindow. Metoda ConvertCords konwertuje współrzędne ze 'świata rzeczywistego' na ekran, czyli np. położenie myszki znajdującej się w oknie do położenia myszki umieszczonej na buforze ekranu. Oto fragment kodu, który należy zmodyfikować by prawidłowo obsługiwać współrzędne myszy na ekranie:
C/C++
const sf::Input & sterowanie = oknoAplikacji.GetInput();
sf::Vector2f mysz = oknoAplikacji.ConvertCoords( sterowanie.GetMouseX(), sterowanie.GetMouseY() ); //nowe
sf::Vector2f punkt = naszSprajt.TransformToLocal( mysz ); //zmodyfikowane
bool bCzyZaznaczony =( punkt.x >= 0 && punkt.y >= 0 && punkt.x <= obrazek.GetWidth() && punkt.y <= obrazek.GetHeight() );
naszSprajt.SetColor( bCzyZaznaczony ? sf::Color::Green: sf::Color::Red );

Pozostałe informacje

To by było na tyle na chwilę obecną o możliwościach klasy » SFML 1.6Sprite. Jak widzisz biblioteka SFML jest bardzo wygodna w użyciu i posiada wystarczająco dużo udogodnień by można było poważnie myśleć o wykorzystaniu jej do tworzenia własnych gier :)
Poprzedni dokument Następny dokument
Wczytywanie i zapisywanie plików graficznych Wyświetlanie prymitywów