Podstawy GDScript – część 7 – obsługa klawiatury i pada (Input)
W tej części tutoriala skupimy się na tym, co najważniejsze dla każdej gry — sterowaniu. Zamiast zagłębiać się w długie teoretyczne wyjaśnienia, przejdziemy od razu do konkretów. Pokażę Ci, jak szybko i sprawnie obsłużyć wejścia z klawiatury oraz pada, tak aby Twoja gra była responsywna i przyjemna w odbiorze.
Zaczniemy od prostych przykładów, które możesz od razu przetestować w swoim projekcie. Dowiesz się:
- jak użyć wbudowanych akcji wejścia
- jak skonfigurować własne akcje wejścia w edytorze
- jak reagować na naciśnięcia klawiszy i przycisków,
- jak obsłużyć pada
Ale zanim przejdziemy do konkretów utworzymy nowy projekt – główny węzeł niech będzie typu Node2D i podrzędny Sprite2D. Do Node2D dodajemy nowy skrypt, a w tym skrypcie…
Ustawiamy sprite na środku ekranu
Ale skąd mam wiedzieć gdzie jest środek ekranu? Ekranu gry – precyzyjniej mówiąc – okna, w którym jest wyświetlana gra. Posłużymy się nową funkcją wbudowaną Godota – get_viewport() która zwraca rozmiar tego właśnie okna. Będzie to rzecz, którą ustawimy na samym początku działania programu, a więc ląduje w funkcji _ready(). Początek naszego skryptu będzie wyglądał tak:
extends Node2D
func _ready() -> void:
position.x = float(DisplayServer.window_get_size().x) / 2
position.y = float(DisplayServer.window_get_size().y) / 2Funkcja ta zwraca rozmiar ekranu w typie Vector2i, a position mamy float – stąd całość konwertujemy na float, inaczej edytor będzie straszył ostrzeżeniami o konwersji typów. Rozmiar x i y dzielimy przez 2, żeby umieścić nasz obiekt dokładnie w połowie ekranu.
Żeby sprawdzić czy działa przydałoby się jeszcze sprajta zobaczyć. Tym razem niech będzie to czołg:)

Ot taki, pixel artowy czołg. Rozmiaru 32×32 piksele. Można pobrać, można samemu narysować;) Wrzucamy plik do projektu z menadżerze plików lub przeciągamy na pole FileSystem w Godocie. Następnie przeciągamy na pole Texture w naszym Sprite2D.
W oknie edytora powinno wszystko wyglądać mniej więcej tak (na czerwono zaznaczyłem istotne rzeczy):

Po uruchomieniu na środku ekranu powinien być czołg. Jeżeli piksele czołgu są rozmyte – sprawdź ustawienie Filter w Sprite2D->CanvasItem->Texture. Powinno być ustawione na Nearest. Filtrowanie tekstur pozwala na ich wygładzanie itd. W pixel arcie jest to niepotrzebne i psuje efekt, dlatego ustawiamy metodę nearest. Jeżeli sprite będzie skalowany, to nie będzie wyliczać kolorów tekstury na przejściach (co właśnie skutkuje rozmyciem) tylko weźmie kolor najbliższego sąsiedniego piksela.

Nazywamy czołg
Drobna rzecz do zrobienia – w oknie Scene kliknij prawym na Node2D i zmień nazwę na Czolg. Dzieki temu będzie łatwiej zauważyć, że operujemy na całym tym node, nie na samym Sprite2D.
Poznajemy InputMap
Zacznijmy od domyślnego mapowania klawiszy i pada – w menu edytora kliknij Project->Project Settings
->InputMap i zaznacz po prawej Show Built-in Actions.

Akcje wbudowane
Możemy tutaj podejrzeć domyślnie zaprogramowane mapowania klawiszy i nazwy podpiętych do nich akcji. Znajdź na przykład ui_left oraz ui_right – to są akcje, które domyślnie obsługują kierunki lewy i prawy.

Widać tutaj, że pod każdą akcję są po 3 opcje podpięte – klawisz strzałki, przycisk D-pada oraz gałka pada. Liczba na prawo od nazwy akcji to tak zwany deadzone – można to nazwać progiem czułości w przypadku analogowych kontrolerów. Gdyby było 0, to przy najmniejszym drgnięciu gałki pada (albo dryfujący analog) byłaby rejestrowana akcja, co nie jest pożądane. Domyślnie zakres jest ustawiony tak, żeby reakcja była od połowy możliwego ruchu (0.5 przy zakresie 0.0-1.0).
Akcje domyślne można rozszerzyć – klikając + na końcu wiersza z nazwą akcji – wyskoczy okno gdzie możemy wybrać wejście lub po prostu nacisnąć klawisz/ruszyć padem – i akcja zostanie odczytana:

Dodawanie własnych akcji
Do obsługi kierunków użyjemy wbudowanych akcji, ale żeby pokazać jak dodać własną akcję stworzymy jedną własną.
Na górze okna z Input Map kliknij w pole Add New Action i wpisz w nim koniec. Zostanie utworzona nowa akcja – znajdź ją na liście i kliknij + obok niej. Wyskoczy okienko w którym wciśniesz Escape:

Potem dodaj jeszcze jedną akcję – wybierz tym razem klawisz Q. I już masz swoją własną akcję, której będzie można użyć w kodzie:)
Jak wyjść z programu w Godocie?
To będzie nasza pierwsza opcja – możliwość wyjścia z aplikacji za pomocą zdefiniowanego klawisza. Wyjść z aplikacji chcemy w trakcie jej trwania – czyli kod powinniśmy umieścić w funkcji _process(). Za obsługę wejścia odpowiadają funkcje zawarte w Input, na przykład:
- Input.is_action_just_pressed – czy akcja została właśnie w tej chwili wykonana (czyli np. naciśnięto klawisz, kliknieto myszką itd.)
- Input.is_action_just_released – czy akcja została właśnie przerwana (czyli np. zwolniono klawisz, puszczono luzem gałkę pada itd.)
- Input.is_action_pressed – akcja jest wykonywana cały czas (klawisz jest cały czas wciśnięty, gałka przesunięta itd.)
Nas w tym przypadku interesuje pierwsza opcja – zwyczajne wciśnięcie klawisza podpiętego pod akcję koniec, którą zdefiniowaliśmy w poprzednim akapicie. Dodajemy więc poniższy kod na koniec naszego skryptu:
func _process(delta: float) -> void:
if Input.is_action_just_pressed("koniec"):
get_tree().quit()Ostatni wiersz jest funkcją Godota odpowiedzialną za zakończenie aplikacji. Zostanie ona wywołana tylko w przypadku naciśnięcia klawiszy, które ustawiliśmy pod akcją koniec. Zapisz zmiany w kodzie i przetestuj:)
Obracanie za pomocą strzałek
Mamy już pojazd – teraz czas na kierowanie. Zaczniemy od obracania – odczytujemy czy użytkownik wykonał interesujące nas akcje – ui_left i ui_right. Jeżeli tak, to odpowiednio zmieniamy parametr rotation naszego node. Zmniejszając ten parametr obracamy obiekt w lewo, zwiększając – w prawo (jeżeli nie wiesz dlaczego – poszukaj rotate i rotation w 3 i 4 części tutoriala). Używamy tutaj wbudowanej liczby PI oraz delty (która zawiera czas od poprzedniej klatki, o której też już w poprzednich częściach pisałem).
if Input.is_action_pressed("ui_left"):
rotation -= PI * delta
if Input.is_action_pressed("ui_right"):
rotation += PI * deltaJedziemy w przód i w tył
Tutaj znowu odczytamy akcje użytkownika, ale tym razem będziemy sprawdzać ui_up oraz ui_down:
if Input.is_action_pressed("ui_up"):
position += Vector2.UP.rotated(rotation) * 100 * delta
if Input.is_action_pressed("ui_down"):
position += Vector2.DOWN.rotated(rotation) * 100 * deltaCo tutaj się dzieje? Aktualizujemy pozycję naszego czołgu o wektor w górę lub w dół (Godot ma predefiniowane Vector2.UP oraz Vector2.DOWN) obrócony o kierunek w jakim obrócony jest czołg. I do tego pomnożony o deltę oraz 100 – liczba 100 jest prędkością i można ją sobie zmienić.
Dodam jeszcze dla wyjaśnienia, że nie będę za mocno wnikał w tłumaczenie stojącej za tym matematyki – z założenia miał to być przecież kurs GDScript.
Gotowy kod
Gotowy kod powinien wyglądać tak:
extends Node2D
func _ready() -> void:
position.x = float(DisplayServer.window_get_size().x) / 2
position.y = float(DisplayServer.window_get_size().y) / 2
func _process(delta: float) -> void:
if Input.is_action_just_pressed("koniec"):
get_tree().quit()
if Input.is_action_pressed("ui_left"):
rotation -= PI * delta
if Input.is_action_pressed("ui_right"):
rotation += PI * delta
if Input.is_action_pressed("ui_up"):
position += Vector2.UP.rotated(rotation) * 100 * delta
if Input.is_action_pressed("ui_down"):
position += Vector2.DOWN.rotated(rotation) * 100 * deltaUruchom i przetestuj. Aplikacja powinna reagować na wyjście oraz kierowanie.
Przy okazji – czy widzisz, że czołg nie obraca się dokładnie wokół środka swojego korpusu? Dzieje się tak dlatego, że środek sprajta wypada trochę powyżej i tak domyślnie został ustawiony przy załadowaniu. Wygląda to tak dlatego, że na obrazku mamy jeszcze lufę, ale chcemy żeby obracał się wg środka samego pojazdu, a nie długości z lufą. Wejdź w widok 2D i powiększ, żeby zobaczyć o czym mówię:

Żeby to poprawić zaznacz w Scene naszego sprajta i przesuń go za pomocą myszy w oknie widoku sceny, albo w parametrach Transform->Position. To ważne, żeby położenie samego sprajta zmienić, nie całego czołgu!
Uruchom ponownie projekt – lepiej, prawda?:)

Dlaczego -4px? Można to zrobić na oko, ja po prostu policzyłem o ile środek czołgu jest przesunięty od środka. Cały sprajt ma 32px wysokości, czołg ma 25px wysokości – czyli przesuwamy o około połowę z tej różnicy.
I to już koniec! Poniżej jeszcze materiały dodatkowe – gotowy projekt i film na YT.
Materiały dodatkowe
Gotowy projekt do pobrania tutaj.
A poniżej film na moim kanale:



Opublikuj komentarz