Stałe i enumeratory (constants, macros, enums)

Wtorek, 27 Lipca 2021, 15:55
Czas czytania 3 minuty, 55 sekund
Zgodne z GM: gms1 gms2
Jak korzystać z definicji która podmieni wybrany przez nas identyfikator na konkretną stałą wartość (aby nie korzystać ze zmiennych), oraz jak stworzyć zmienne które pomogą nam w grupowaniu czy odróżnianiu stanów/flag zachowań w grze.
GameMaker jeszcze w zamierzchłych czasach wprowadził zmienne zwane stałymi. Na pewnym jednak etapie YoYoGames postanowiło zmienić im nazwę na macros (makra), głównie z powodu ich faktycznego działania.

Makra (constants, macros)
W przeciwieństwie do prawdziwych stałych, które są w innych językach programowania i są dostępne jako identyfikatory z wartością w czasie działania, makra działają podobnie do chociażby dyrektywy #define z C/C++ i są jedynie definicją stworzoną przez programistę, informującą kompilator, które miejsce kodu należy zwyczajnie zastąpić podaną przez nas wartością.

Po usunięciu dedykowanego okienka znanego z GM i GMS 1.x, stałe definiuje się obecnie w dowolnym miejscu kodu, za pomocą prefiksu #macro, następnie nazwy i wartości, np.:
kod#macro nazwa_makra 15
Potem wystarczy użyć identyfikatora nazwa_macra w dowolnym miejscu kodu, a w momencie kompilacji zostanie ona podmieniona na wybraną przez nas wartość, np.:

kod#macro szerokosc_etapu 2000
if (x > szerokosc_etapu) {
...
Warto dodać, że po definicji makra nie dajemy średnika, gdyż wszystko co znajduje się po pierwszej spacji za jego nazwą, zostanie podmienione i mogłoby powodować błędy składni. Powyższy fragment jeszcze przed odpaleniem gry, w trakcie kompilowania zmieniony zostanie na:
kodif (x > 2000) {
...
a w samej grze po naszej definicji nie zostanie ślad. Działa to więc trochę tak, jakby edytor za nas wykonywał funkcję "Znajdź i zamień" za każdym razem, gdy testujemy/kompilujemy grę.

Makra można oczywiście wykorzystać w bardziej kreatywny sposób, nie tylko podając wartości tekstowe/liczbowe ale np. nazwę zasobu czy nawet cały fragment kodu:
kod#macro pink make_color_rgb(255,192,203)
...
draw_set_color(pink);
// powyższy kod w momencie kompilacji da nam:
// draw_set_color(make_color_rgb(255,192,203));
Wskazówka:
Przez to, że GMS nie wykona funkcji w momencie kompilowania zwracając wartość, a robi jedynie znajdź i zamień, warto w przypadku kolorów podawać gotowe wartości HEX (w odwróconej kolejności BBGGRR), np. kolor różowy #FFC0CB w GMS zapiszemy jako $CBC0FF - znak $ oznacza liczby szesnastkowe)

Nic nie stoi też na przeszkodzie, aby napisać:
kod#macro jest_daleko if (x > 20 && zmienna = true)
...
jest_daleko {
// nasz kod
}

W ten sposób można też nadpisać oryginalne funkcje GMowe:
kod#macro show_debug_message moja_funkcja
show_debug_message(value);
Ponieważ wszystko działa na zasadzie "znajdź i zamień", aby nadal móc wykorzystać oryginalną funkcję, wystarczy zdefiniować ją jako kolejne makro linijkę niżej (ważne, aby nie linijkę przed, bo wtedy nasza definicja zastąpi tę sprzed chwili):
kod#macro show_debug_message moja_funkcja
#macro stare_sdb show_debug_message// teraz wszystkie wywołania stare_sdb staną się show_debug_message
Pamiętajmy jednak, że funkcje tak nadpisane muszą mieć tę samą liczbę argumentów, gdyż GM sprawdzi poprawność przed zastąpieniem makra i będzie się burzył :)

Wielolinijkowe makra zapisujemy natomiast tak:
kod#macro hello show_debug_message("Hej " + \
string(player_name) + \
", jak się masz?");

Można też używać makro dla różnych konfiguracji (Configs - manual.yoyogames.com/.../Configurations.htm ):
kod#macro rozmiar_ekranu 1920
#macro KonfiguracjaAndroid:rozmiar_ekranu 1270

Enumeratory (enum)
Na podobnej zasadzie działają enumeratory. One także zostają zastąpione w momencie kompilacji gry, ale mogą być tylko typu integer. Zaletą jest jednak fakt, że edytor podpowiada ich składnię i wartości, więc są przydatne do definiowania typów przedmiotów, czy flag/stanów jakiegoś zdarzenia (np. czy bohater biegnie czy idzie, albo jakiego typu jest przeciwnik).
Wskazówka:
wartości liczbowe enum nie są tak naprawdę typem real, a int64, w związku z tym funkcja is_real() zwraca dla nich false. Warto używać zamiast tego funkcji is_numeric()
Domyślnie enumeratory, jeśli nie nadano im wartości, są numerowane od 0 do n (0, 1, 2, 3...).
kodenum moj_enum {
czerwony,
zielony,
niebieski,
czarny
}

show_debug_message(moj_enum.czarny); // zwroci 3
// w momencie kompilacji gry tak naprawdę powyższa linijka zmieni się na:
// show_debug_message(3)

Enumeratory nie muszą być jednak numerowane kolejno i tak długo, jak zachowamy warunek, że ich wartości są liczbowe, można nawet używać zdefiniowanych wcześniej (ale nie później) enumeratorów do ustawiania wartości, włącznie z prostymi działaniami:
kod
enum domki {
parterowy = 250,
pietrowy = domki.parterowy * 2,
wiezowiec = $F + 5,
empire_state_pietra = 102,
drapacz_chmur = domki.parterowy * domki.empire_state_pietra
}

show_debug_message(domki.drapacz_chmur); // zwraca 25500
// w momencie kompilacji powyższa linijka zmieni się na:
// show_debug_message(25550);
Komentarze (łącznie 0):
Nie ma jeszcze żadnego komentarza. Czas to zmienić

Najnowsze wersje GameMakera:

Stabilna
2023.8.1.102 • 2023.8.1.148
wydana 13 dni temu
LTS
2022.0.1.31 • 2022.0.1.30
wydana 168 dni temu
Beta
2023.800.0.406 • 2023.800.0.429
wydana 29 dni temu
= IDE, = Runtime
Użytkownicy online
1 użytkownik aktywny:
gości: 1,
(~ostatnie 15 minut)
Discord
9 użytkowników online na discordzie:
ACCESS_ViOLATiON, Carl-bot, PolTomski, Grela, SuperEnduro, LadyLush, szmalu, Tidżi, Dyno
Shoutbox
Adriann (21:06, 14.08.23)
Jest..hoho:D
Adriann (21:04, 14.08.23)
Nie znam tego, poszukam. Nie mówisz mam nadzieję o tej podmiance wewnątrz skryptu?
gnysek (10:38, 14.08.23)
Przecież jest: Search & Replace. Do tego nazwy skryptów i zasobów akurat Feather podmienia praktycznie bez problemów.
Adriann (14:39, 12.08.23)
Przydałaby się opcja do globalnej zmiany nazwy zmiennejobiektu we wszystkich skryptach i obiektach :D Tak to jest dość ciężko zabrać się za sprzątanie
SimianVirus7 (10:39, 12.08.23)
To nie burdel, to nieład artystyczny
exp (00:35, 12.08.23)
Feather nie zrozumiał, że burdel jest elementarną częścią mojego projektu
exp (00:34, 12.08.23)
Miałem to samo, nie tyle otworzyłem stary projekt, co w końcu ściągnąłem aktualizację (bo olewałem ten komunikat od chyba półtora roku)
gnysek (23:48, 10.08.23)
Kolizje tilesetowe rządzą!
gnysek (20:01, 26.07.23)
zobaczycie nowy edytor kodu, powinen wskoczyć do bety w sierpniu...
SimianVirus7 (11:24, 25.07.23)
No dokładnie :D
Starsze wpisy znajdziesz w Archiwum.
Ankieta
Kiedy wyjdzie GameMaker (Studio) 3.0?