GM 2023+: Singleton w GM

Poniedziałek, 13 Lutego 2023, 23:52
Czas czytania 3 minuty, 23 sekundy
Zgodne z GM: gms2
GM 2023 wprowadza nową składnię, która pozwala pobierać statyczne wartości konstruktorów za pomocą prostszej składni.
GameMaker w wersjach 2023+ (od 2023.1) wprowadza nowe funkcje - static_get() i static_set(), które pozwalają pobrać "statyczną" część funkcji, struktur i konstruktorów, lub nadpisać tę przypisaną do jakiegoś obiektu.

Wskazówka:
Zwykła struktura domyślnie nie ma statycznej części, jedynie te utworzone przez = new nazwa_konstruktora();, lub takie, na których użyto static_set()

Ot, załóżmy, że mamy taki kod:

kodfunction add_points(_score = 0) {
static points = 0;
points = points + _score;
return points;
}

Dzięki zastosowaniu "static", zmienna "score" jest na stałe przypisana do funkcji "add_score" i nie znika pomiędzy jej wywołaniami (wszystkie inne zmienne, jeśli nie są poprzedzone var, będą odczytywać/zapisywać zmienną o danej nazwie w obecnym kontekście, najczęściej w obiekcie).

Takie statyczne, są tak naprawdę strukturą "ukrytą" w zakamarkach GMa (mona założyć, że funkcja/struktura sprawdzając swoje zmienne, najpierw sprawdza, czy ma swoją lokalną wersję, potem czy ma statyczną, a dopiero gdy nie znajdzie obu rzuca błędem o nieznanej zmiennej) i funkcja static_get pozwala nam dostać bezpośrednią referencję do tej normalnie ukrytej struktury. Możemy wtedy zmienić jej wartości spoza danej funkcji, czy nawet dodać/usunąć wartości. Dzięki static_set możemy je nawet podmienić - i coś, co było wcześniej instancją jednej klasy, nagle stanie się instancją innej.

Twócy GMa postanowili, że pozwolą się dobrać się do tej struktury w jeszcze prostszy sposób, dzięki czemu dostaliśmy w GMie

Singleton
W przypadku funkcji, które zawierają jakiś static, jeśli te statyczne wartości zostały zainicjowane pierwszy raz, możemy pisać teraz:
kodnazwa_funkcji.wartosc;
Wskazówka:
W momencie kompilacji, GM widząc nazwa_funkcji.cokolwiek, przerabia kod na static_get(nazwa_funkcji).cokolwiek

W ten sposób można odnosić się czy do funkcji, czy do konstruktorów - trzeba jednak pamiętać, aby chociaż raz je zainicjować.

kodenum diff {
easy, medium, hadrd
}

function Game() constructor {
static difficulty = diff.easy;
static points = 0;
static hp = 100;
}

Game(); // inicjalizacja pierwszy raz, może być w globalnym skrypcie, zaraz za definicją
show_debug_message(Game.hp); // zwraca: 100

Uwaga!
Warto jednak pamiętać, że skoro tak naprawdę używamy "static_get", dostając strukturę która zawiera nasze statyczne dane, wykonując funkcje z tej struktury, ich kontekst wykonania zmienia się, na obecny (bo wyciągamy funkcję na zewnątrz i tam uruchamiamy). Wszelkie zmienne nadpiszą więc te w obecnym kontekście (globalny, instancja), a nie te w tej strukturze!

Co to oznacza? Załóżmy, że dodamy do naszego konstruktora funkcję "leczącą":
kodfunction Game() constructor {
static hp = 10;

// nowa funkcja
static heal = function() {
hp = 100; // ! tu kryje się błąd !
}
}

Pisząc

kodGame.heal();
Wyobraźmy sobie, że tak naprawdę napisaliśmy:

kodvar a = static_get(Game).heal; // dostajemy referencję na funkcję, nie całą strukturę
a(); // odpala się w obecnym kontekście, nie wewnątrz struktury static_get(Game)

Wskazówka:
Wbrew pozorom, nie wykonamy with(static_get(Game)) {hp = 100;} - co jest prawidłową składnią GMową i wykonałoby się w kontekście struktury statycznej. Jest prostsza opcja.

Funkcja "heal" wykona się więc w obecnym kontekście - jeśli jest to skrypt (poza funkcjami), to ustawimy zmienną global.hp = 100;. Jeśli instancja, to jej zmienna "hp" ustali się na 100 (jeśli instancja tej zmiennej nie miała - no to już ją ma...).

Od wersji 2023.1 GameMaker pozwala już jednak zmieniać wartości używając podobnej składni:

kodfunction Game() constructor {
static hp = 10;

static heal = function() {
Game.hp = 100; // można by też napisać static_get(Game).hp = 100;
}
}

Game();

show_debug_message(Game.hp); // zwróci 10
Game.heal();
show_debug_message(Game.hp); // zwróci 100

Grafika: /upload/ajax/20230213_9377dd8f120eeddc57c2ab4fc79b1a45.png
Komentarze (łącznie 2):
gnysek (Wto., 14 Lut. 23, 11:56)
#1

Russell potwierdził na Discordzie, że brak opcji zapisu (np. Game.hp = 100) to bug i w 2023.2 powinni to naprawić - do tego jednak czasu nie aktualizuję artykułu :)

gnysek (Pon., 27 Lut. 23, 17:30)
#2

Ok, sprawdziłem, w wersji 2023.2 jest to już naprawione i można pisać "Game.hp = <cos>".

Najnowsze wersje GameMakera:

Stabilna
2024.11.0.179 • 2024.11.0.227
wydana 38 dni temu
LTS
2022.0.3.85 • 2022.0.3.99
wydana 54 dni temu
Beta
2024.1300.0.720 •
2024.1300.0.733
 0.14.0

wydana 10 dni temu
= IDE, = Runtime, = GMRT
Użytkownicy online
1 użytkownik aktywny:
gości: 1,
(~ostatnie 15 minut)
Discord
41 użytkowników online na discordzie:
Kysiu, 🧁Cupcake🧁, Alice, LeD, Nitro Slav, Tymon, Carl-bot, lethian, Grela, Wielki Druid, Alkapivo, Kowu, GMRussell, OdrzuconyKrakers, fervi, Dod, antek, HappyOrange, LolikZabijaka, Pako, Arrekin, RogerDodg3r, Domeen0, Dyno, 🆅🅸🆃🅾74🅼, szmalu, Morro, ZYGZAK, Voytec, Ulti, bagno, Sporek, Danieo, Kandif, l..., s..., d..., h..., Shockah, PeekoHiko, xVANiLL
Shoutbox
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
Chell (20:40, 08.11.24)
tylko? :O 4tk ma 15
Starsze wpisy znajdziesz w Archiwum.
Ankieta
Ile zarobiłeś do tej pory na grach stworzonych w GM?