Poruszanie klawiaturą - top down

Czwartek, 05 Października 2023, 18:22
Czas czytania 4 minuty, 56 sekund
Zgodne z GM: gms2 gms1
Przykłady najprostszego sterowania w grze.
W tym kursie chciałbym wam przedstawić różne podejścia do sterowania postacią w grze typu top-down (z widokiem z góry).

Stwórzcie nowy projekt, a w nim dwa sprite'y, o rozmiarach 32x32. Ja skorzystałem z gotowej paczki z kenney.nl. Jeśli używacie grafik w innym rozmiarze, warto je przeskalować - założeniem tego artykułu jest korzystanie z domyślnej gamemakerowej siatki 32x32 do ustawiania obiektów, gdyż jest to też artykuł wyjściowy dla kolejnego wpisu, dotyczącego wyrównywania do siatki.

Tworzymy dwa obiekty:
- obj_player
- obj_wall, któremu zaznaczamy "solid".

Grafika: /upload/ajax/20231005_9c8a01d98d249e60d170533911a27b1d.png

W naszej grze chcemy umożliwić ruch w poziomie i w pionie, ale jeśli gracz zmienia oba kierunki, dopuszczamy ruch po skosie - który będzie po prostu sumą obu przesunięć.

Jest wiele sposobów na to, aby sprawdzić, w którą stronę porusza się gracz. Sporo osób sprawdza po kolei każdy z klawiszy góra/dół/lewo/prawo i tworzy odpowiednie warunki dla każdego z nich. Nie bez powodu wspomniałem jednak o poruszaniu w pionie i w poziomie, gdyż pozwala to na pewne uproszczenie kodu.

Wiemy bowiem, że poruszając się w poziomie, poruszamy się na osi x - w lewo odejmujemy od obecnej pozycji, a w prawo dodajemy. Nie ważna jaka będzie prędkość postaci, możemy użyć uogólnienia, że ruch w lewo to ruch ujemny, a ruch w prawo - dodatni. Jeśli więc nasza postać porusza się z prędkością A, to w lewo poruszy się z prędkością A * -1, a w prawo z prędkością A (lub... A*1).

Ponieważ funkcje sprawdzające, czy klawisz jest wciśnięty zwracają wartość true/false (inaczej 1/0), możemy skorzystać z matematyki, aby połączyć tę wcześniejszą wiedzę. Możemy bowiem sprawdzenie tego, czy klawisz w lewo i w prawo są wciśnięte przemnożyć przez liczby -1 i 1. Dzięki temu:
- jeśli nie jest wciśnięty żaden przycisk, otrzymamy 0
- jeśli wciskamy "lewo", otrzymamy -1
- jeśli wciskamy "prawo", otrzymamy 1
- jeśli wciskamy na raz lewo+prawo, otrzymamy... 0 (bo -1 + 1 = 0) i postać nie ruszy się.

Do sprawdzenia, czy przycisk został wciśnięty, służy funkcja keyboard_check().
Wskazówka:
keyboard_check_pressed() pozwala sprawdzić, czy w obecnej klatce nastąpiło pierwsze wciśnięcie klawisza (tzn. przejście ze stanu niewciśniętego do wciśniętego), a keyboard_check_released() czy klawisz został zwolniony (czyli na odwrót). keyboard_check() zwraca true/1 tak długo, jak klawisz jest przytrzymywany.

Dodajemy event step w obj_player.

kodvar hor = -keyboard_check(vk_left) + keyboard_check(vk_right);
var ver = -keyboard_check(vk_up) + keyboard_check(vk_down);

Teraz w zmiennej tymczasowej "hor" mamy informację o tym, czy powinien nastąpić ruch poziomy (horyzontalny), a "ver", czy pionowy (vertical).

Chcielibyśmy jednak, aby nasza postać poruszała się szybciej, niż 1/-1 piksel na klatkę obrazu.
Dodajemy więc nową zmienną, spd, oraz przemnażamy przez nią wcześniejsze wartości:

kodvar sp = 3;
hor *= sp;
ver *= sp

Dzięki temu wiemy już, ile nasza postać mogłaby ruszyć się w tej klatce obrazu w pionie i w poziomie.

Trzeba jednak sprawdzić, czy nie zachodzi kolizja. GM ma wbudowaną bardzo prostą funkcję, która pozwala sprawdzić, czy gdyby nasz obiekt przesunął się na daną pozycję, nie zachodzi kolizja z obiektem z zaznaczoną flagą solid. Ta funkcja to place_free.

Wskazówka:
- funkcje z prefixem position_ sprawdzają, czy na pikselu na pozycji x,y nie zachodzi kolizja (uwzględniając maski obiektów na pozycji x,y)
- funkcje z prefixem place_ sprawdzają, czy nie zachodzi kolizja, gdyby obecny obiekt przesunął się na pozycję x,y (dokładniej - jego maska).
Różnica polega na tym, że gdy bierzemy pod uwagę całą maskę, pod uwagę brane są wszystkie przykryte piksele, a nie tylko 1x1.
- funkcje z sufiksem _free sprawdzają kolizje z obiektami solid, a _empty sprawdzają z każdym.

Sprawdzamy więc, czy można poruszyć się pionowo i osobno czy poziomo (nie wstawiamy tutaj słowa else, gdyż niemożliwość ruchu w jednej płaszczyźnie, nie wyklucza ruchu w drugiej; dodatkowo brak else pozwala poruszać się po skosie).

kod if place_free(x+hor, y) {
x += hor;
}
if place_free(x, y+ver) {
y += ver;
}

To wszystko. Pierwszy warunek sprawdza czy możliwy jest ruch poziomo o tyle pikseli ile wynosi nasz spd (wartość będzie ujemna jeśli w lewo, dodatnia jeśli w prawo). Podobnie w pionie (ujemna w górę, dodatnia w dół).

GM oferuje też inne sposoby na taki ruch. Jedną z funkcji dodanych w 2023 roku jest move_and_collide.

Wystarczy zamienić oba warunki "if place free" na:
kodmove_and_collide(hor * sp, ver * sp, obj_wall);i uzyskamy dokładnie taki sam rodzaj ruchu.

Wskazówka:
Jeśli chcemy więcej niż jeden typ obiektu który jest przeszkodą, wystarczy stworzyć obiekt "rodzica" (jeśli chcemy go używać w roomie, musi mieć sprite i zaznaczoną flagę solid), a potem każdy inny obiekt z którym też ma zachodzić kolizja, ustawić jako jego rodzic (parent). Sprawdzanie kolizji z "rodzicem" będzie zwracać też kolizję dla "dzieci" (o ile mają ustawioną flagę solid, oraz ustawiony sprite).

Teraz wystarczy dodać 1 instancję obiektu gracza w room editorze, oraz kilka "ścian", np. tak:

Grafika: /upload/ajax/20231005_8cb247f169b68c406fe86f9904f8ea10.png

Proste sterowanie z góry działa :)
Komentarze (łącznie 0):
Nie ma jeszcze żadnego komentarza. Czas to zmienić

Najnowsze wersje GameMakera:

Stabilna
2024.2.0.132 • 2024.2.0.163
wydana 54 dni temu
LTS
2022.0.2.51 • 2022.0.2.49
wydana 193 dni temu
Beta
2024.400.0.549 • 2024.400.0.567
wydana  4 dni temu
= IDE, = Runtime
Użytkownicy online
1 użytkownik aktywny:
gości: 1,
(~ostatnie 15 minut)
Discord
Shoutbox
gnysek (20:44, 11.04.24)
Niektórzy dlatego wybierają GMEdit. Ale ja liczę na Code Editor 2, tylko na razie zbyt zbugowany jest.
Tymon (16:11, 11.04.24)
Stitch dla mnie osobiście jest lepszy bo nie musze kopać się z interfejsem GMa i mogę tylko pisać kod.
Tymon (16:05, 11.04.24)
Yes. Obecny nie jest taki zły, jak zainstalowałem najnowszą stabilną to w porównaniu z tym czego używałem... 10 lat temu...? Wszystko wydaje się lepsze.
gnysek (22:48, 10.04.24)
bscotch/stitch ? Ja czekam na fixy do nowego edytora, bo wszystko wydaje się dziś lepsze od tego obecnego :D
Tymon (19:54, 10.04.24)
Hm, Stitch okazuje się całkiem dobrą alternatywą dla wbudowanego edytora
Wojo (22:16, 08.04.24)
siemano huder myślałem, że zniknąłeś całkiem z gmclanu bo na discordzie cie nie ma :D
I am Lord (00:37, 05.04.24)
O dzięki :D
gnysek (09:58, 02.04.24)
Znalazłem na podstawie jego postów: youtube.com/@Jakim_
I am Lord (20:16, 01.04.24)
Ktoś ogarnia jakie konto miał Jakim na YT?
gnysek (16:07, 29.03.24)
Nowy Edytor kodu jednak po świętach
Starsze wpisy znajdziesz w Archiwum.
Ankieta
Ile zarobiłeś do tej pory na grach stworzonych w GM?