Biblioteka SFML - o ile do tej pory zachwycała swoimi wyrafinowanymi rozwiązaniami o tyle niniejszy rozdział trochę Twój entuzjazm ostudzi. Zanim jednak popadniesz z euforii w jakiś przygnębiający stan pomyśl sobie tak: prymitywów często wyświetlać nie będziesz, a sprajty są bardzo wygodne, więc co by się nie działo to z niektórymi niedociągnięciami można się przemęczyć. Oczywiście to co zostało zrobione w bibliotece SFML z prymitywami na swój sposób się broni, niemniej jednak mogli nieco bardziej się postarać nad tą częścią biblioteki.
Skoro już wiesz, że praca z prymitywami w bibliotece SFML nie zapowiada się zbyt optymistycznie to mogę z czystym sumieniem przejść do ich omawiania.
Tworzymy kształt
W bibliotece SFML każdy prymityw jest nazywany kształtem. Do tego celu powołano do życia klasę
sf::Shape. Klasa
sf::Shape dziedziczy po klasie
sf::Drawable, a ponadto oferuje nam kilka własnych metod, które w tym rozdziale zostaną omówione. Zacznijmy jednak od rzeczy nam znanych, czyli od utworzenia obiektu i jego wyświetlenia:
sf::Shape naszKsztalt;
oknoAplikacji.Draw( naszKsztalt );
Jeżeli uzupełnisz kod swojej aplikacji SFML o powyższe linijki, po czym skompilujesz go i uruchomisz to zaobserwujesz, że na ekranie nie zaszły żadne zmiany. Wszystko będzie oczywiście w najlepszym porządku bowiem obiekt
naszKsztalt nie zawiera żadnych wierzchołków, które miały by być narysowane, a co za tym idzie nic nowego nie zostanie wyświetlone ekranie.
Dodawanie wierzchołków
Klasa
sf::Shape dostarcza metodę
AddPoint, która dodaje nowe wierzchołki do kształtu. Każdy wierzchołek posiada współrzędne X, Y i uwaga:
dwa kolory :) Kolor pierwszy to kolor punktu, natomiast drugi to kolor ewentualnego obramowania figury, która powstanie w wyniku połączenia wszystkich dodanych wierzchołków. Tworzone figury powinny być tworzone tak by wierzchołki były ułożone zgodnie ze wskazówkami zegara, bądź w kierunku odwrotnym do kierunku wskazówek zegara. Jeżeli się do tego nie dostosujesz Twój kształt może zostać źle wyświetlony.
Utrudnienia związane z kolejnością wierzchołków wynikają tylko i wyłącznie z zasad, które zostały ustanowione przez producentów kart graficznych. Wymuszenie kolejności wierzchołków umożliwa producentom kart graficznych optymalizowanie mechanizmów renderujących scenę. Wchodzi w to również kilka innych bardzo istotnych aspektów związanych np. z obliczaniem normalnych do powierzchni, świateł itd. Szczegółowe informacje na ten temat nie będą Ci raczej potrzebne tak długo jak długo nie będziesz używał bezpośrednich wstawek OpenGL'a do swojego kodu. Szczegółowe zasady funkcjonowania maszyny stanów OpenGL są opisane w książkach na temat wspomnianej biblioteki i wykraczają poza zakres omawiania biblioteki SFML. |
Skoro trochę teorii już znamy, zobaczmy jak będzie wyglądało w praktyce wyświetlenie figury:
sf::Shape naszKsztalt;
naszKsztalt.AddPoint( 100, 100, sf::Color::White, sf::Color::Red );
naszKsztalt.AddPoint( 100, 200, sf::Color::White, sf::Color::Red );
naszKsztalt.AddPoint( 200, 200, sf::Color::White, sf::Color::Red );
oknoAplikacji.Draw( naszKsztalt );
Powyższy kod wyświetli nam biały i jednocześnie wypełniony trójkąt na ekranie, bez żadnego obramowania. To czy kształt będzie posiadał obramowanie oraz jakiej grubości konfiguruje się dodatkowymi metodami klasy
sf::Shape. Ponadto możliwe jest ustalenie czy renderowana figura ma być wypełniona czy też nie. Zanim jednak do tego przejdziemy zatrzymajmy się na chwilę przy kolorach, a dokładniej przy znaczeniu koloru wierzchołka.
Kolory wierzchołków
Zobaczmy teraz następujący kod:
sf::Shape naszKsztalt;
naszKsztalt.AddPoint( 100, 100, sf::Color::Red );
naszKsztalt.AddPoint( 100, 200, sf::Color::Green );
naszKsztalt.AddPoint( 200, 200, sf::Color::Blue );
oknoAplikacji.Draw( naszKsztalt );
Jeżeli wkleisz powyższy kod do swojej aplikacji to zobaczysz na ekranie trójkąt, który posiada płynne przejścia kolorów między wierzchołkami oraz płynnie przechodzące barwy wypełniające rysowaną figurę. Efekt ten cieszy zapewne Twoje oko i w sumie dostajesz go za darmo ze wsparciem sprzętowym karty graficznej. No i to by było na tyle na temat kolorów wierzchołków :)
Wypełnienie
Wypełnienie figury można włączyć jak również wyłączyć za pomocą metody
EnableFill. Przykładowo aby wyłączyć wypełnienie wystarczy napisać:
naszKsztalt.EnableFill( false );
Analogicznie będzie wyglądało ponowne jego włączenie tyle, że argumentem metody będzie wartość
true.
Obramowanie kształtów
Jeżeli chcemy aby obramowanie naszego kształtu zostało wyświetlone to musymy zadbać o następujące rzeczy - po pierwsze: musimy mieć włączony tryb wyświetlania obramowania. Do tego celu służy metoda
EnableOutline, która działa analogicznie do metody
EnableFill. Przykład:
naszKsztalt.EnableOutline( true );
Kolejną rzeczą o którą musimy zadbać to ustalenie grubości obramowania. Do tego celu wykorzystujemy kolejną metodę i jest nią
SetOutlineWidth do której jako argument przekazujemy grubość linii wyrażonej w pikselach. Kolor obramowania jak już zapewne wiesz podajesz przy dodawaniu wierzchołków do kształtu poprzez ostatni argument metody
AddPoint. Kod, który wyświetli nam trójkąt z kolorowym obramowaniem bez wypełnienia będzie więc wyglądał tak:
sf::Shape naszKsztalt;
naszKsztalt.AddPoint( 100, 100, sf::Color::White, sf::Color::Red );
naszKsztalt.AddPoint( 100, 200, sf::Color::White, sf::Color::Green );
naszKsztalt.AddPoint( 200, 200, sf::Color::White, sf::Color::Blue );
naszKsztalt.EnableFill( false );
naszKsztalt.EnableOutline( true );
naszKsztalt.SetOutlineWidth( 50 );
oknoAplikacji.Draw( naszKsztalt );
Jeżeli uruchomisz swój program po wprowadzeniu powyższego kodu to zapewne zauważysz, że efekt opisany został uzyskany. Należy jednak zauważyć, że ramka otacza figurę utworzoną w wyniku połączenia wierzchołków. Innymi słowy ramka nie ingeruje w obszar, który leży wewnątrz figury utworzonej przez wierzchołki.
Przekształcenia kształtów
Przekształcenia kształtów dokonujemy za pomocą dobrze nam już znanych metod np.
Move,
Scale czy też
Rotate. Argumenty metod są dokładnie takie same jak dla omawianej wcześniej klasy
sf::Sprite dlatego też nie będą tu ponownie przytaczane.
Odczytywanie informacji o kształcie
Klasa
sf::Shape posiada szereg metod, które umożliwiają odczytanie informacji o obecnym kształcie. Za pomocą metody
GetNbPoints możemy pobrać liczbę wierzchołków z których składa się figura. Atrybuty wierzchołków możemy pobrać za pomocą następujących metod:
sf::Vector2f polozenie = Polygon.GetPointPosition( 2 );
sf::Color kolorPunktu = Polygon.GetPointColor( 2 );
sf::Color kolorObramowania = Polygon.GetPointOutlineColor( 2 );
Numerowanie wierzchołków zaczyna się od zera tak więc wartość 2 oznacza w rzeczywistości trzeci wierzchołek. W C++ taka numeracja jest na porządku dziennym i nie powinna nikogo dziwić :)
Modyfikowanie kształtu
Tak samo jak w przypadku odczytywania, SFML dostarcza metody do modyfikowania atrybutów wybranych wierzchołków. Bez zbędnych słów zobaczmy jak to wygląda w praktyce:
naszKsztalt.SetPointPosition( 1, sf::Vector2f( 55, 77 ) );
naszKsztalt.SetPointColor( 1, sf::Color::Black );
naszKsztalt.SetPointOutlineColor( 1, sf::Color( 0, 128, 128 ) );
Kształty predefiniowane
Biblioteka SFML posiada kilka kształtów prefefiniowanych i są to: linia, okrąg i prostokąt. Żeby za bardzo nie przynudzać o rzeczach prostych zamieszczam tylko i wyłącznie przykład prezentujący sposób korzystania ze wspomnianych kształtów. Argumenty ujęte w nawiasy kwadratowe są parametrami opcjonalnymi. Oto kod:
sf::Shape linia = sf::Shape::Line(
X1, Y1, X2, Y2,
GruboscLinii, Kolor,
[ GruboscObramowaniaLinii ],[ KolorObramowaniaLinii ]
);
sf::Shape okrag = sf::Shape::Circle(
X, Y,
Promien, KolorWypelnienia,
[ GruboscObramowaniaOkregu ],[ KolorObramowaniaOkregu ]
);
sf::Shape prostkat = sf::Shape::Rectangle(
X1, Y1, X2, Y2, Kolor,
[ GruboscObramowaniaProstokata ],
[ KolorObramowaniaProstokata ]
);
Rysowanie elipsy
Biblioteka SFML nie wspiera rysowania elipsy. Możliwe jest jednak jej uzyskanie poprzez przeskalowanie wybranej osi kształtu.
Wnioski końcowe
Dotarliśmy do końca omawiania prymitywów w bibliotece SFML. O ile interfejs do zarządzania kształtem jest wygodny (jak można było się domyślić) to jak zapewne zauważysz wkrótce będzie on nieco męczący przy rysowaniu chociażby ramek wprowadzających estetykę do Twojej aplikacji. Do każdego kształtu będziesz bowiem zmuszony utworzyć nową zmienną tylko po to by wyrenderować obramowanie. Alternatywą jest wielokrotne wykorzystywanie tej samej zmiennej. Na szczęście w większości przypadków wystarczą kształty predefiniowane, które można renderować z pominięciem tworzenia zmiennej nazwanej. Przykładowo linię możesz narysować tak:
oknoAplikacji.Draw( sf::Shape::Line( 500, 500, 600, 600, 5, sf::Color::Red ) );
Tym optymistycznym akcentem pozwolę zakończyć sobie niniejszy rozdział :)