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

Wyświetlanie prymitywów

[lekcja] Rozdział 8. Niniejszy rozdział opisuje w jaki sposób można wyświetlać proste kształty w bibliotece SFML. Do prostych kształtów zaliczamy: linię, prostokąt, okrąg oraz figury zbudowane z połączonych ze sobą punktów.
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:
C/C++
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:
C/C++
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:
C/C++
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ć:
C/C++
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:
C/C++
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:
C/C++
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:
C/C++
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:
C/C++
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:
C/C++
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:
C/C++
oknoAplikacji.Draw( sf::Shape::Line( 500, 500, 600, 600, 5, sf::Color::Red ) );
Tym optymistycznym akcentem pozwolę zakończyć sobie niniejszy rozdział :)
Poprzedni dokument Następny dokument
Tworzenie i wyświetlanie sprajtów Wyświetlanie tekstu