Podstawy GDScript – część 3 – obliczenia, operatory, adnotacje i ruchome sprajty (Godot tutorial po polsku)
W poprzednim odcinku…
W poprzednim odcinku wyjaśniłem czym są zmienne w GDScript – jakie są podstawowe typy, jak je zadeklarować i jak ich używać. Były to proste, tekstowe przykłady – dzisiaj pójdziemy dalej i dodamy trochę obliczeń oraz będziemy przemieszczać obiekty w przestrzeni 2D. Przy okazji opowiem też o przydatnych operatorach.
Tradycyjnie do artykułu nagrałem film, w którym pokazuję o czym piszę:
Operatory w GDScript
Operatory możemy podzielić na kilka grup, skupię się jednak na dwóch podstawowych (pełną listę znajdziesz tutaj):
- Operatory matematyczne – kolejność wykonywania obliczeń tak jak w szkole uczono (z uwzględnieniem pierwszeństwa tego, co w nawiasach;) Wynik jest wyliczany za pomocą działania na liczbach x i y jak w przykładach poniżej:
- potęgowanie: x ** y (x do potęgi y)
- mnożenie: x * y
- dzielenie: x / y
- reszta z dzielenia: x % y (tzw. modulo; znak % ma jeszcze zastosowanie przy formatowaniu łańcuchów znaków, ale o tym przy okazji łańcuchów. Jak masz kombinację liczb i zmiennych z % pomiędzy, to na pewno chodzi o resztę z dzielenia). Działa tylko dla liczb całkowitch!
- dodawanie: x + y
- odejmowanie: x – y
- Operatory przypisania – wynik jest zapisywany do zmiennej po lewej (x). Czy w przypadku x += y – komputer weźmie x, doda do niego y i całość zapisze do x (tracimy oryginalną wartość x w tym przypadku!):
- x = y
- x **= y (x = x ** y)
- x += y (x = x + y)
- x -= y (x = x – y)
- i dalej tym samym kluczem:
- x *= y
- x /= y
- x %= y
- Operatory logiczne
- osobny typ operatorów dla zmiennych logicznych (bool). Opowiem o nich w następnych odcinkach. Tutaj nam się jeszcze nie przydadzą.
Test operatorów
Przetestujmy teraz poznane operatory. Utwórz nowy projekt z głównym węzłem typu Node i dodaj do niego nowy węzeł Sprite2D (jeżeli nie pamiętasz, to tutaj pokazuję jak to zrobić). Dodajemy też do niego skrypt, w którym tworzymy zmienne a i b. Później po kolei wykonujemy kilka działań i wyświetlamy wyniki. Podmień kod w nowo utworzonym skrypcie kod na poniższy:
extends Sprite2D
var a: float
var b: float
func _ready() -> void:
a = 10
b = 2
print(a + b)
print(a - b)
print(a ** b)
a += 10
print(a)
b *= 5
print(b)
Wyniki jakie otrzymałem:
12.0
8.0
100.0
20.0
10.0
Przeanalizuj przykładowe obliczenia, podstaw inne operatory i liczby, sprawdź wyniki.
Obracanie Sprite2D
Doszliśmy do miejsca, w którym wreszcie możemy sprawdzić wiedzę z tego i poprzedniego odcinka kursu Godota w praktyce. W pierwszej kolejności dodajemy do sceny nowy node typu Sprite2D (jeżeli nie wiesz lub nie pamiętasz jak to zrobić – pisałem i mówiłem o tym w Sprite2D i Godot).
Klikamy w oknie Scene prawym przyciskiem myszy na Sprite2D i dodajemy skrypt (Attach script). Tworzymy skrypt na domyślnych ustawieniach. Obrazek możemy dodać własny w inspektorze w polu Texture lub po prostu przeciągnąć tam plik icon.svg z okna Resources (domyślna ikonka projektu). Powinniśmy mieć mniej więcej taki projekt:

Na początku ustawimy sobie pozycję naszego sprajta dalej od rogu ekranu, żeby go lepiej widzieć – po 200 punktów w prawo i w dół (o układzie współrzędnych też było w podlinkowanym wcześniej odcinku tutoriala). Skoro pozycję ustawiamy zmieniając parametry position, to obrót pewnie będzie rotation. Sprawdźmy;) Zacznijmy od 90 stopni – dodaj te zmiany w _ready().
func _ready() -> void:
position.x = 200
position.y = 200
rotation = 90
I uruchamiamy (F6 lub Cmd+R):

Coś krzywo, prawda? Spróbuj w takim razie w kodzie zmienić 90 na 0, może obrazek jest krzywy?;)
I jak? Teraz jest dobrze, prawda? To znaczy, że coś nie tak jest z tymi 90 stopniami. Bo to nie jest parametr określany stopniami! Najedź kursorem nad rotation i zaczekaj chwilę, wyskoczy taka podpowiedź:

Rotation in radians – obrót jest zapisany w tej zmiennej w radianach. Dla wnikliwych polecam na Wikipedii. Nam wystarczy, żeby pamiętać, że jest różnica. W tym samym okienku mamy tez podpowiedź, że możemy używać właściwości rotation_degrees. Sprawdźmy – zamień rotation na rotation_degrees, 90 zamiast 0 i uruchom ponownie:

Teraz jest ok:) Można też to zrobić innym sposobem – przekonwertować kąt w stopniach na radiany:
func _ready() -> void:
position.x = 200
position.y = 200
rotation = deg_to_rad(90)
Funkcja deg_to_rad() konwertuje wartość w stopniach na radiany. Można też w drugą stronę funkcją rad_to_deg().
Obracanie automagiczne i delta
W tym i poprzednich odcinkach dało się zauważyć parametr delta w funkcji _process. Jest to parametr, którym Godot dzieli się z nami przekazując czas jaki minął od narysowania ostatniej klatki obrazu. Ten czas może się różnić w zależności od prędkości komputera i skomplikowania sceny. Dzięki temu możemy na przykład przesuwać sprajta z jednakową prędkością niezależnie od prędkości komputera. Gdybyśmy na przykład przesuwali sprajta za każdym razem o 100 pikseli, to na jednym komputerze, który generuje 10 klatek na sekundę o 100×10 pikseli. Czyli 1000 pikseli na sekundę. A na komputerze który generuje 120 klatek na sekundę? 100×120 czyli 12000 pikseli w sekundę. Przy ekranie o szerokości 1920 pikseli (Full HD) ledwie byśmy zobaczyli, że coś mignęło na ekranie. I właśnie dlatego używamy delty. Pozwala uzyskać jednakową prędkość animacji niezależnie od prędkości sprzętu – jak coś ma w sekundę przelecieć pół ekranu, to przeleci pół ekranu.
Jak używać delty?
Ot chociażby tak – najprostszy przykład to dodać do aktualnego obrotu czas od ostatniej klatki:
extends Sprite2D
func _ready() -> void:
position.x = 200
position.y = 200
func _process(delta: float) -> void:
print(delta)
rotation = rotation + delta

Zwróć uwagę na zaznaczone na zielono liczby w konsoli – 0.0166666s – tyle czasu mija u mnie między klatkami. Żeby policzyć ile to jest klatek na sekundę wystarczy podzielić 1/tę liczbę – czyli 1/0.01666 w zaokrągleniu da 60. 60 klatek na sekundę – i to się zgadza, bo mam na tyle zablokowane wyświetlanie obrazu (tzw. VSync – odświeżanie pionowe, Godot domyślnie trzyma się wyświetlania ustawionego w systemie – można wyłączyć w Project Settings).
Szybciej, szybciej!
Połączmy teraz wiedzę o zmiennych, delcie i właściwościach sprajta, żeby przyspieszyć jego obrót. W tym celu powinniśmy pomnożyć deltę przez jakąś wartość, żeby np. 20 krotnie przyspieszyć obrót sprajta – mnożymy deltę przez 20. Przy okazji, żeby nie szukać prędkości po całym kodzie zdefiniujemy sobie na początku kodu zmienną predkosc typu float i użyjemy jej do mnożenia delty dalej w kodzie. Zamień kod na poniższy:
extends Sprite2D
var predkosc: float = 20.0
func _ready() -> void:
position.x = 200
position.y = 200
func _process(delta: float) -> void:
print(delta)
rotation = rotation + delta * predkosc
Uruchom i porównaj z poprzednim kodem. A później pobaw się ustawiając różne wartości w predkosc. Podpowiedź – zmniejszenie prędkości uzyskasz przez zmniejszanie tej liczby. Np. zmniejszenie prędkości do połowy delty to 0.5. Ustawienie predkosc na liczbę ujemną spowoduje, że sprajt będzie się obracał w drugą stronę:)
Kierunek obrotu
Jeżeli jeszcze nie wyszło w trakcie powyższych zabaw, to oficjalnie informuję;) Powiększanie parametru rotation powoduje obrót w prawą stronę, zmniejszanie – w lewą. Warto o tym pamiętać! (spróbuj ustawić prędkość na -10).
Anotacje – @export
Adnotacje (annotations) to takie specjalne instrukcje w GDscript – nie mają one jako takie wpływu na kod i obliczenia, ale rozszerzają nam możliwości – na przykład adnotacja @export pozwala używać zmiennych, które określimy w kodzie z poziomu Inspektora. Najlepiej będzie jak pokażę na przykładzie – w miejscu gdzie definiujemy zmienną dodajemy na początku @export. Kod powinien wyglądać teraz tak:
extends Sprite2D
@export var predkosc: float = 20.0
func _ready() -> void:
position.x = 200
position.y = 200
func _process(delta: float) -> void:
print(delta)
rotation = rotation + delta * predkosc
Po tej zmianie kodu zmienna predkosc powinna pojawić się w Inspektorze – zaznaczyłem na żółto na zrzucie ekranu poniżej:

Uwaga: zmienne wyświetlane tutaj są „upiększane” – dodawana jest wielka litera, podkreślenie zamienione na spację etc. Tak dla lepszej czytelności. W kodzie dalej jest jak było.
Dodatkowo – co czasem jest bardzo przydatne – możemy z Inspektora zmieniać wartość zmiennej w czasie działania programu i obserwować skutki. Spróbuj uruchomić scenę i zmieniać wartość zmiennej predkosc w Inspektorze.
Uwaga: jeżeli używamy anotacji @export, to możemy:
- podać nazwę i typ zmiennej tylko w kodzie (w tym przypadku typ jest wymagany!) – zostanie ustawiona na 0, 0.0, false, „” – czyli domyślną wartość w zależności od typu zmiennej
- nie podawać wartości zmiennej – a ustawić ją tylko w Inspektorze
- podać ją w kodzie i w Inspektorze – ta podana w Inspektorze będzie użyta domyślnie.
Jeżeli zastanawiasz się jaki sens ma ostatnia opcja, to już tłumaczę. Otóż może się okazać, że chcemy mieć 3 kręcące się z różną prędkością sprajty. Co możemy zrobić? Utworzyć 3 sprajty, 3 zmienne prędkości, 3 skrypty osobno?
Niekoniecznie – możemy zduplikować naszego sprajta i po ustawiać w inspektorze osobne prędkości oraz pozycje. Wtedy nawet jak w kodzie będziemy obracać sprajta, to każdy będzie używał swojej własnej zmiennej predkosc.
Żeby to przetestować musimy dokonać małej zmiany w kodzie – żebyśmy mogli oprócz prędkości obrotu ustawić także pozycję każdego ze sprajtów dodamy zmienne pozycji poz_x i poz_y:
extends Sprite2D
@export var predkosc: float
@export var poz_x: int
@export var poz_y: int
func _ready() -> void:
position.x = poz_x
position.y = poz_y
func _process(delta: float) -> void:
print(delta)
rotation = rotation + delta * predkosc
Teraz duplikujemy nasz Sprite2D w oknie Scene dwa razy – dla przypomnienia klik prawym na obiekt, który chcemy zduplikować i Duplicate LUB zaznaczamy tylko Sprite2D klikając lewym i naciskamy kombinację CTRL+D.
Zaznaczamy pierwszy sprajt i w Inspektorze ustawiamy:
- Predkosc = 0.0
- Poz X = 100
- Poz Y = 100
Zaznaczamy drugi sprajt i ustawiamy:
- Predkosc = 10.0
- Poz X = 200
- Poz Y = 200
I na koniec trzeci:
- Predkosc = 20.0
- Poz X = 300
- Poz Y = 300
Po uruchomieniu powinny się pojawić 3 sprajty – jeden nieruchomy i dwa obracające się z różną prędkością:

Możesz w trakcie pracy tej animacji pozmieniać pozycję i prędkość każdego z tych sprajtów i sprawdzić co się będzie działo – w tym celu ustaw okno animacji i Godota obok siebie lub na różnych monitorach.
Uwaga: dlaczego osobne zmienne do ustawiania pozycji dodałem, skoro każdy obiekt ma swoją pozycję w sekcji Transform?
- żeby bez zbędnego zamętu pokazać działanie @export na większej ilości zmiennych
- gdybyśmy chcieli poruszać sprajtami na boki, to możemy operować na ich pozycji operując position.x i position.y, ale w poz_x i poz_y zawsze mamy zapisaną pozycję startową i możemy do niej wrócić jak nam np. sprite wyleci poza ekran;)
Projekt do pobrania
Zapisałem projekt (wersja Godot 4.4), który powstał przy okazji tego odcinka – jest do pobrania tutaj obracanie sprite w GDScript. W międzyczasie wyszedł Godot 4.5 – jeżeli masz nowszą wersję zostanie Ci zaproponowana automatyczna konwersja, nie powinno być z tym żadnego problemu.
Co dalej?
W najbliższych częściach opowiem o pętlach oraz instrukcjach warunkowych – a przy okazji o operatorach logicznych, bo przydają się w jednym i drugim;)
Miłego eksperymentowania!
Opublikuj komentarz