matrix

Pozycja, rotacja, skalowanie: przekształcanie obiektów

Przekształcenia


Wszystkie obiekty, które można przekształcać (transform) dziedziczą po klasie sf::Transformable, to ona pozwala im na te wszystkie czynności.

Ta klasa ma 4 właściwości: pozycję (position), rotację(rotation), skalę (scale) oraz origin. Ich użycie jest bardzo proste i intuicyjne.

Pozycja

Pozycja, to po prostu pozycja obiektu na scenie 2D, każdy kto miał do czynienia z układem współrzędnych wie o co chodzi 🙂

Standardowo obiekty porusza się względem punktu, który leży w lewym górnym rogu obiektu, można to zmienić, ale o tym później.

 

Rotacja

Jest to po prostu obracanie obiektów, jest ona definiowana w stopniach zgodnie z ruchem wskazówek zegara.

Zauważ że pobierana rotacja zawsze zawiera się w przedziale [0,360]. Tak jak w przypadku pozycji, tak samo rotacja jest dokonywana względem standardowo lewego górnego rogu.

 

Skala

Czyli faktor, który wskazuje zmianę rozmiaru obiektu. Jeżeli jest większy niż 1 to wiem że obiekt został powiększony, mniejszy od 1 pokazuje że obiekt został pomniejszony, a równy 1 mówi że obiekt jest nieskalowany.

 

Origin

Jest to punkt, wg którego wykonywane są operacje typu: przesuwanie, obracanie obiekt, itp. Standardowo jest on ustawiany na lewy górny róg obiektu. Jeżeli chcesz go zmienić to nie ma problemu, można w bardzo łatwy sposób go zmienić.

Zauważ, że po zmianie punktu origin, zmianie także ulega wizualna pozycja obiektu.

 

Przekształcanie (transformowanie) własnej klasy


sf::Transfromable możesz dziedziczyć, dzięki czemu możesz uzyskać jej właściwości w twojej klasie.

Aby użyć ostatecznie właściwości Transformable musisz użyć getTransform (zazwyczaj podczas wykonywania draw), poniżej nieco bardziej to wyjaśnię.

Jeżeli nie chcesz korzystać z całej funkcjonalności tej klasy, to możesz użyć jej po prostu jako członka swojej klasy, a funkcje możesz albo pozostawić w obecnej formie, albo możesz napisać własne przez zasłonięcie tych z tej klasy.

 

Rozszerzanie możliwości Transformable


Klasa Transformable jest łatwa w użyciu, ale jednocześnie bardzo ograniczona. Może się zdarzyć, że będziesz potrzebował więcej możliwości, typu łączenie kilku przekształceń w  jedno itp. Jeżeli tak jest w twoim przypadku, to jest nisko poziomowa klasa sf::Transform, która jest 3×3 matrix’em, dzięki czemu może być reprezentowana przez przekształcenia w świecie 2D.

Jest wiele sposobów na użycie sf::Transform:

  • przez użycie predefiniowanych funkcji dla najczęściej spotykanych transformacji (translacja, skala, rotacja)
  • przez połączenie dwóch transformacji
  • przez bezpośrednie określenie 9 elementów.

Kilka przykładów:

Możesz oczywiście wszystkie transformacje zawrzeć w jednej:

Aby wykorzystać te transformacje musisz:

Forma powyżej jest krótszą wersją:

 

Bounding boxes


Po wykonaniu  transformacji być może chciałbyś wykonać jakieś obliczenia na nich, np do sprawdzenia kolizji.

Obiekty w SFML mogą podać ci tzw bounding box, czyli najmniejszy prostokąt potrzebny do zamknięcia obiektu w prostpkącie.

Bounding box może być przydatny w sprawdzaniu kolizji i można go pobrać bardzo szybko.

Funkcja getGlobalBounds pobiera bounding box z uwzględnieniem transformacji (rotacja itp), getLocalBounds nie bierze tych zmian pod uwagę.

Jednak może się okazać, że ten rodzaj kolizji nie będzie dla ciebie odpowiednio dokładny, możliwe że przyda ci się to co przekazałem w moim kursie Piszemy grę w SFML w lekcji o kolizjach.

 

Hierarchia obiektów


Dzięki temu co napisaliśmy wcześniej możemy w łatwy sposób napisać klasę, która będzie decydowała o hierarchii obiektów, gdzie potomkowie danych obiektów (children) będą transformowane zgodnie z ich rodzicami (parents). Wszystko co musisz zrobić to przekazanie połączenia przekształcenia z rodzica na dzieci podczas ich rysowania.

Oryginalny artykuł


  • pw1602

    W bounding boxes jest błąd:

    „(…), getGlobalBounds nie bierze tych zmian pod uwagę.”

    Powinno być getLocalBounds.