vertex-shapes

Projektowanie własnych „jednostek” przy pomocy VertexArray

Wstęp


Jeżeli poszukujesz klasy która pozwoli ci w nieco bardziej rozbudowany sposób urozmaicić kształty w SFML lub chcesz stworzyć swoje własne figury to ten tutorial jest dla ciebie.

Zadajmy sobie pytanie czym jest Vertex Array? Z angielskiego wiemy, że to po prostu tablica wierzchołków. Vertex jest najmniejszą dostępną jednostką jaką możemy manipulować. Posiada pozycję (x,y lub x,y,z), a także kolor i parę współrzędnych tekstury.

Wierzchołki pojedynczo nie robią wiele, dlatego łączy się je w prymitywy: 1 wierzchołek tworzy punkt, 2 tworzą linię, 3 – trójkąt, 4 -czworokąt. Gdy połączysz 1 lub więcej wierzchołków razem otrzymasz geometryczną reprezentację figury.

 

VertexArray


Na początku przyjrzyjmy się strukturze sf::Vertex, która przechowuje 3 publiczne elementy: pozycję (position), kolor (color), teksturę (texCoords). Przy tworzeniu musisz się zdecydować czy wybierasz użycie koloru, czy tekstury. Możesz te elementy uzupełnić poprzez wywołanie je jak w każdej standardowej klasie:

lub możesz uzupełnić je używając konstruktora:

Teraz sprawmy aby wierzchołki utworzyły nam typ prymitywny. Pamiętamy przy tym, że aby stworzyć typ prymitywny musimy użyć kilku wierzchołków, czyli potrzebujemy na nie tablicy sf::VertexArray. Jest to typ danych podobnych do std::vector i jego użycie jest analogiczne.

Nasz trójkąt jest już gotowy, jak zauważyłeś użyliśmy 3 różnych kolorów, narysujmy to i zobaczmy jak to się prezentuje.

W ten sposób możesz tworzyć m.in. gradienty.

Zauważ, że nie musisz korzystać z VertexArray, możesz równie dobrze posłużyć się wcześniej wspomnianym std::vector, wtedy rysowanie wygląda w trochę inny sposób.

Możesz też użyć tradycyjnych tablic:

 

Rodzaje prymitywów


Najwyższa pora to poznania rodzajów prymitywów jakie możesz spotkać w SFML.

sf::Points

Jest to zbiór niepołączonych ze sobą punktów, punkty nie mają swojej grubości, zawsze są o wielkości 1 piksela, niezależnie od przekształceń i view (klasa w SFML).

sf::Lines

Zbiór niepołączonych ze sobą linii, są zawsze grubości 1 piksela, niezależnie od przekształceń i użycia view.

sf::LinesStrip

Zbiór połączonych ze sobą linii, ostatni wierzchołek jest łączony z pierwszym wierzchołkiem i tworzy figurę zamkniętą.

sf::Triangles

Zbiór niepołączonych ze sobą trójkątów.

sf::TrianglesStrip

Zbiór połączonych ze sobą trójkątów, każdy trójkąt udostępnia 2 ostatnie wierzchołki następnemu trójkątowi.

sf::TrianglesFan

Zbiór połączonych trójkątów połączonych z 1 centralnym punktem. Pierwszy wierzchołek jest centralnym punktem, każdy nowy vertex tworzy nowy trójkąt, używając środek i poprzedni vertex.

sf::Quads

Zbiór niepołączonych ze sobą kwadratów. Każde z 4 wierzchołków muszą być zdefiniowane w kolejności zgodnej lub przeciwnej do wskazówek zegara.

 

Nadawanie tekstur (texturing)


Tak jak reszta obiektów w SFML tak i Vertex może być teksturowany. Aby to zrobić musisz użyć texCoords, ta zmienna definiuje który piksel tekstury ma być mapowany do Vertex‚a.

Współrzędne tekstury są w pikselach i nie są normalizowane (nie mają wartości pomiędzy 0, a 1), tak jak osoby piszące w openGL mogłyby się spodziewać.

VertexArray to nisko poziomowy typ, a więc nie przechowują one tekstury. Aby narysować je z teksturą należy ją dostarczyć bezpośrednio do funkcji draw.

To jest ta prostsza wersja, jednak gdybyś potrzebował użyć render states (przekształceń lub blend mode) to możesz użyć rozszerzonej wersji używającej sf::RenderStates.

 

Przekształcenia VertexArray


VertexArray ulega przekształceniom w podobny sposób jak w przypadku teksturowania.

Lub:

Aby wiedzieć o samej klasie sf::Tranform przeczytaj kurs o Przekształceniach.

 

Tworzenie „SFML-like” jednostek


Jeżeli twoim zdaniem pokazane wcześniej klasy są dla ciebie niewystarczające to za pomocą sf::Drawable oraz sf::Transformable. Te dwie klasy są bazą dla klas takich jak sf::Sprite, sf::Text, czy sf::Shape.

sf::Drawable to interfejs, ta funkcja jedynie deklaruje pustą wirtualną funkcję draw, której dziedziczenie pozwoli ci użyć funkcji draw to narysowania obiektów.

Zauważ że funkcja draw wykonana przez ciebie jest uruchamiana wewnątrz window.draw. W ten sposób kod wygląda przejrzyściej i ładniej.

Kolejną klasą jest sf::Transformable, która nie ma funkcji wirtualnych. Dziedziczenie po niej daje ci automatycznie standardowe dla tej klasy metody (obracanie, ustawianie pozycji, itd.).

Standardowa klasa graficzna w SFML wygląda w ten sposób:

Możesz także korzystać z wbudowanych w SFML klas:

 

Przykład: mapa kafelkowa


Wykorzystajmy to co widzieliśmy powyżej, cała mapa będzie zawarta w pojedynczym VertexArray, dzięki temu będzie rysowana bardzo szybko. Zauważ, że w tym przykładzie pobieramy kafelki zakładając, że wszystkie tektury kafelków są w 1 pliku (tileset).

A także użycie tego przez program:

 

Przykład: system cząsteczek


Drugim przykładem będzie system cząsteczek, będzie to o tyle prostsze, że nie będziemy musieli używać tekstur. Jeżeli chcesz wiedzieć na jakiej zasadzie działają systemy cząsteczek odsyłam cię do strony Nature of Code.

Oraz sposób użycia:

Oryginalny artykuł