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/Settings/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
2024.11.0.179 • 2024.11.0.227
wydana 65 dni temu
LTS
2022.0.3.85 • 2022.0.3.99
wydana 81 dni temu
Beta
2024.1300.0.743 •
2024.1300.0.753
 0.15.4

wydana 10 dni temu
= IDE, = Runtime, = GMRT
Użytkownicy online
2 użytkowników aktywnych:
gości: 1, userów: 1
 Adriann
(~ostatnie 15 minut)
Discord
38 użytkowników online na discordzie:
Draczeq, Alice, LeD, Nitro Slav, Carl-bot, lethian, TobiasM (Morgo), Kysiu, Kowu, Kuzyn, GMRussell, OdrzuconyKrakers, fervi, 𝕳𝖚𝖌𝖔 𝕲𝖔𝖓𝖝𝖆𝖑𝖊𝖝, r..., Cysior, Pako, m..., firemark, MagnusArias, Domeen0, LadyLush, Dyno, szmalu, Morro, Miłosz, sutikku, Ulti, bagno, Tidżi, Danieo, g..., Huder, l..., s..., Add92, h..., Shockah
Shoutbox
gnysek (10:35, 18.02.25)
W ciągu 10 dni mają wyjść w końcu Layery UI :D
Wojo (10:25, 27.12.24)
Jak tworzyłeś* ah ta niecną autokorekta (kiedyś też stworzyłem apki na androida w sumie)
Wojo (10:23, 27.12.24)
O siemka baca, czasami myślę o tobie w kontekście tego jak tworzyłem apki na androida. Swoją drogą czasami zapominam, że forum istnieje bo cały ruch teraz utrzymuje się na discordzie, ale pora to zmienić!
Uzjel (20:17, 10.12.24)
Cały ruch przeniósł się na Discorda.
MagnusArias (17:43, 01.12.24)
O matko... a ja tutaj jestem od ponad 15 lat i czasami zaglądam... biernie bo biernie, ale czasem wpadnę
gnysek (11:46, 17.11.24)
Witamy, witamy!
baca (12:22, 16.11.24)
To już 25 lat.. Witam po paru latach nieobecności.
gnysek (11:05, 15.11.24)
Natomiast obecne forum istnieje od 2004, jak z iglu.cz na gmclan.org przeszliśmy i od tego czasu nie było resetów danych.
gnysek (12:35, 13.11.24)
Ogólnie GMCLAN istnieje 22 lata, ale na to trofeum nie zrobiłem (jeszcze xD)
Chell (20:41, 08.11.24)
wow, ta emotka w ogóle nie wygląda jak : O xD
Starsze wpisy znajdziesz w Archiwum.
Ankieta
Ile zarobiłeś do tej pory na grach stworzonych w GM?