Skocz do zawartości

System delegacji


Rekomendowane odpowiedzi

  • Filar Społeczności

Jako, że każdy ostatnio zakłada temat dla własnego przykładu, to ja tez nie będę sobie żałował. :)

 

https://gmclan.org/index.php?plik=107

 

Jest to system delegacji dla GM'a. Czegoś takiego mi zawsze brakowało, a już zwłaszcza po obcowaniu z C#, więc się sprężyłem i stworzyłem DODATEK. Tak jest, to nie przykład lecz dodatek. Przetestowałem wszystkie funkcje na różne sposby i błędów nie stwierdziłem, więc jeśli ktoś takowy znajdzie, to proszę poinformować.

 

Kawalek pliku czytajto.txt, bo nie mam zamiaru się powtarzać. :)

 

    Opis:
    System delegacji dla GM, to system niejawnego wywolywania skryptow i zdarzen obiektow trzecich.
    Wbudowany system wywolywania zdarzen niestety pozwala wywolac tylko jedno zdarzenie na raz.
    Ten dodatek eliminuje ta niedogonosc, a ponadto pozwala na niejawne wiazanie relacji miedzy roznymi obiektami,
    a takze przekazywanie parametrow podczas wywolywania zdarzen oraz pozwala na identyfikacje obiektu wywolujacego.

    Skrypty:

    DelegateCreate()
        Tworzy nowa delegacje (kontener / zasobnik dla zdarzen zwanych delegatami). Zwraca id delegacji.

    DelegateAddScript( id delegacji, id skryptu, id obiektu wlasciciela )
        Do delegacji podanej jako pierwszy argument zostaje dodane nowe zdarzenie (delegat). Jest nim okreslony
        skrypt (argument 2). Skrypt ten bedzie wywolywany przez obiekt podany w argumencie trzecim.
        Zamiast id obiektu mozna dodawac typy obiektow, wtedy takie zdarzenie wiaze ze soba wszystkie obiektu danego typu.
        Funkcja zwraca false gdy danej delegacji nie ma lub unikatowe ID zdarzenia (delegata).

    DelegateAddEvent( id delegacji, numer eventa event_user, id obiektu )
        Procz skryptow mozna rejestrowac takze eventy typu event_user (Game Maker oferuje ich 15).
        Funkcja dziala analogicznie jak poprzednia. Rejestrujemy okreslony event_user obiektu z trzeciego argumentu.

    DelegateSize( id delegacji )
        Zwraca liczbe zdarzen (delegatow) zarejestrowanych w delegacji.

    DelegateCall( id delegacji, argument1, argument2 ... )
        Wywoluje wszystkie zdarzenia (delegaty), ktore sa zarejestrowane w danej delegacji.
        Jesli okreslony delegat to skrypt, zostana mu przekazane wszystkie parametry procz pierwszego (id delegacji)
        Ponadto wywolywane zdarzenie (event_user lub skrypt) moze odwolac sie do 2 zmiennych globalnych:
            global.DL_Sender - id obiektu, ktory wywolal delegacje
            global.DL_Params - tablica parametrow przekazana podczas wywolywania delegacji
        Uwaga! Nie modyfikuj tych zmiennych, traktuj je jako tylko do odczytu, gdyz ustawianie sa one tylko raz
        przed wywolaniem zdarzen danej delegacji. Po ich wywolaniu zmienne te sa resetowane!

    DelegateDelete( ID delegata )
        Funkcja, ktora usuwa delegata o ID, ktora zwrocila wczesniej funkcja DelegateAddEvent / DelegateAddScript
        Nie trzeba podawac ID delegacji, gdyz funkcja jest inteligenta i wie w jakiej delegacji siedzi delegat. :)
        Zwraca false, gdy nie znaleziono delegata o podanym ID

    DelegateDeleteAll( ID obiektu )
        Funkcja usuwa wszystkie zdarzenia (delegaty) ze wszystkich delegacji w systemie,
        ktorych wlascicielem jest obiekt podany w argumencie pierwszym lub typ obiektu.
        Uwaga! Gdy odrejestrujemy okreslony obiekt, to i tak beda mu wywolywane
        zdarzenia, ktore zostaly zarejestrowane ogolnie dla typu obiektu!
        
        Uwaga:
            Funkcja ta przydatna gdy niszczymy obiekt, ktory mial zarejestrowane zdarzenia w jakichs delegacjach,
            gdyz system nie obserwuje czy dany obiekt jeszcze istnieje!

    DelegateClear( ID delegacji )
        Funkcja usuwa z delegacji wszystkie zdarzenia (delegatow).
        Zwraca false gdy nie ma zadanej delegacji.

    DelegateDestroy( ID delegacji )
        Funkcja czysci dana delegacje z delegatow, a nastepnie calkowicie usuwa delegacje,
        ktora zostala utworzona przy pomocy DelegateCreate.
        
        Uwaga:
            Zawsze usuwaj delegacje gdy juz jej nie uzywasz (Game Maker nie ma "Garbage Collectora").

    DelegateDrawDebugger()
        Rysuje prosty debugger calego systemu delegacji. Najwazniejsza jest ostatnia struktura. :P

    Szybki sposob uzycia:
    1) Tworzymy nowa delegacje:
        D = DelegateCreate();

    2) Rejestrujemy zdarzenie event_user_3 oraz skrypt Testowy obiektowi Test.
        DelegateAddEvent(  D, 3, Test );
        DelegateAddScript( D, Testowy, Test );

    3) Wywolujemy delegacje (i powyzsze zdarzenia) razem z 3 testowymi parametrami:
        DelegateCall( D, "a", "b", "c" );

    4) I to wszystko! :D Obiektowi Test zostanie wywolany event_user_3 oraz skrypt Testowy.



    Aby system delegacji dzialal bezkolizyjnie, nie uzywaj ponizszych nazw:
        global.DL_Initiated, global.DL_EventId, global.DL_EventDelegate, global.DL_ObjectDelegates,
        global.DL_Delegates, global.DL_ID, global.DL_VID, global.DL_Sender, global.DL_Params

    W skryptach sa uzywane zmienne tymczasowe, ktore sa nazywane konwencja:
        _nazwa_zmiennej
    Poprzedzaj zmienne tymczasowe podkreslnikiem. To dobry zwyczaj, ktory powoduje bezkolizyjnosc skryptow.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

Tymon:

Miałem wolne popołudnie, to napisałem. Większej liczby czasu nie zużyłem. :] Ogólnie jest to dodatek typu ułatwiacz coś jak te uniwersalne listy w "projekcie", którymi łatwiej manipulować. System delegacji wbrew pozorom jest ciekawym dodatkiem, gdyż ułatwia w znacznym stopniu zaprojektować logikę gry / programu.

 

Przykładowo mamy huda, który składa się z wielu elementów: paska energii, liczby żyć, licznika punktów, ekwipunku itd. Po zmianie rozdzielczości autor może zapragnąć zmieniać kontrolkom huda design na lepszy dla niskiej rozdzielczości. I teraz jak powiązać te kontrolki odpowiednim zdarzeniem z jakimś guzikiem? Można kontrolkom np. dać sprawdzanie jakiejś zmiennej globalnej czy sprawdzanie rozdzielczości lub dać im jako parent obiekt uniwersalny, potem wywoływać event_user obiektowi uniwersalnemu, który wywołuje inny event_user obiektom podrzędnym. itd., itp. Możliwości jest wiele, ale jest jedna tego wada. To są wiązania jawne i projektujesz je za każdym razem tworząc nowę grę, ponadto musisz dokładnie znać stan dwóch stron. System delegacji pozwala właśnie na elastyczne niejawne łączenie zdarzeń, bo możemy rejestrować zdarzenia od stron ywywołującego zdarzenie (np. guzik) czy też obiektu, któremu wywołane zdarzenie chcemy wywołać. Pełna wygoda. Ba, system delegacji nie jest wybredny i dopuszcza każdy typ obiektu czy skrypt. Musisz tylko dwóch rzeczy przestrzegać: delegat typu skrypt - skrypt musi istniec oraz wlasciciel delegata tez musi istniec, a jak jest niszczony to DelegateDeleteAll i gotowe. :)

 

Tak więc rozwiążanie powyższego problemu jest proste, stworzyć nową delegację i przypisać tą delegację do zmiennej globalnej, następnie przy klikaniu na jakiś guzik ją wywoływać. Natomiast w create kontrolek huda dajemy skrypt dodawania własnego zdarzenia np. event_user0 do wczesniej wymienionej delegacji przy pomocy DelegateAddEvent, no i w event_user0 dajemy skrypt dostosowujacy wyglada, ktory jest unikatowy dla kazdej kontrolki, bo one sie roznia.

 

Po prostu Mark Overmars nie pomyślał o implementacji systemu ala delegat, więc zrobiłem to za niego. ;) A np. takie wzorce projektowe? Nie po to zostały wymyślone, by mieć czego się dodatkowego uczyć, ale głównie mają służyć odciążeniu pracy i dostarczać odpowiedzi na powszechnie napotykane problemy. :)

 

 

EDIT:

A sam se dopisz sprawdzanie. Mi się już nie chce. :P Tak trudno w event destroy dac DelegateDeleteAll( id ); ?

Odnośnik do komentarza
Udostępnij na innych stronach

Rozumiem rozumiem. Po przeczytaniu n razy "czytajto.txt" trudno nie zrozumieć. Jednak mi się to wydaje nieprzydate, sam nie wiem dlaczego (tak jak kiedyś obiekty i klasy w PHP, głupota nie? ;P). Nie widzę praktycznego zastosowania ale widać muszę do tego "dorosnąć", albo przejść na C#.

 

EDIT

Up. Po co, skoro może to zrobić skrypt? :P

 

EDIT 2

Ty leń jesteś, dodać tylko 2 linijki do dwóch funkcji xP

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
Rozumiem rozumiem. Po przeczytaniu n razy "czytajto.txt" trudno nie zrozumieć. Jednak mi się to wydaje nieprzydate, sam nie wiem dlaczego (tak jak kiedyś obiekty i klasy w PHP, głupota nie? ;P). Nie widzę praktycznego zastosowania ale widać muszę do tego "dorosnąć", albo przejść na C#.
Prawdę mówiąc tak się zastanawiałem, kto z gmclanowiczów uzna to za przydatne. :]
Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Oj widzę, że muszę dokończyć mój silnik walki RPG bo coraz lepsze przykłady na GMCLANie są :P

Aczkolwiek ja tak samo a nawet bardziej jak Tymon, nie za bardzo kumam do czego można by to użyć... chyba też jestem za młody na takie bajki :D

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
Oj widzę, że muszę dokończyć mój silnik walki RPG bo coraz lepsze przykłady na GMCLANie są :P

Aczkolwiek ja tak samo a nawet bardziej jak Tymon, nie za bardzo kumam do czego można by to użyć... chyba też jestem za młody na takie bajki :D

Do czego użyć? Ano taki przykład: W Harvest Moonie są pory roku, które w czasie gry się zmieniają. Każda pora roku charakteryzuje się innym trybem wegetacji roślin, inną długością dnia no i krajobrazem!

 

global.ZmienPoreRoku = DelegateCreate();

 

Obiekty typu skaly, domki itd. w czasie zimy sa zasniezone. Trzeba im dostosowywac wyglad. Tworzymy tym obiektom event_user0, ktory dostosowuje np image_index. Rejestrujemy zdarzenia:

 

DelegateAddEvent( global.ZmienPoreRoku, 0, Domy );

DelegateAddEvent( global.ZmienPoreRoku, 0, Skaly );

DelegateAddEvent( global.ZmienPoreRoku, 0, Drzewa );

 

 

 

Jako ze temperatura w zimie jest inna, to trzeba losowac stopnie z innego przedzialu niz w lecie. Obiektowi Termometr zmieniamy ten przedzial w event_user0. Rejestrujemy zdarzenia:

 

DelegateAddEvent( global.ZmienPoreRoku, 0, Termometr );

 

 

 

Co by tu jeszcze... A! Czas! Dni w zimie sa znacznie krotsze, wiec powinnismy zmodyfikowac lekko czas wschodu i zachodu slonca. Robimy to w ... event_user0 obiektu SilnikDnia. Rejestrujemy zdarzenie:

 

DelegateAddEvent( global.ZmienPoreRoku, 0, SilnikDnia );

 

 

 

Dodatkowo mozna wprowadzac zmiany do systemu wegetacji roslin, generowania zwierzat w lesie itd. Zalozmy ze juz wszystko zrobilismy.

Teraz wielki final! Zmieniamy pore roku na zime!

 

DelegateCall( global.ZmienPoreRoku, "zima" ); //dodajemy opcjonalny parametr.

 

Włala! Wszystkie obiekty, które w jakikolwiek sposób związane są z porami roku zostaną dostosowane do trybu zimowego! We wszystkich powyzszych event_user0 mozemy np. sprawdzac parametr (argument) zerowy przy pomocy switch:

 

switch( DL_Params[0] )

{

case "zima":

...

break;

 

case "wiosna":

...

break;

...

}

 

Widzisz? Proste i przyjemne do użycia. :)

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
To przecież można użyć with :P Efekt ten sam, przynajmniej dla mnie.

 

Ale się dziś czepiam, woho!

Oczywiście, że można użyć with, ale zauważ jedno. Jeżeli dodasz jakiś nowy rodzaj obiektu, to musisz powrócić do tego kawałka skryptu, który te with'e wywołuje i dopisać kod. A w delegacjach obsługę za dostosowanie do zimy zrzucasz na ten nowy obiekt, bo on się sam rejestruje w delegacji trzymanej w zmiennej globalnej. A jak okaże się, że już nie jest potrzebny ten obiekt, to co? Usuniesz with? Zaczniesz sprawdzać czy obiekt istnieje? Będziesz trzymał obiekty na liście? W delegacjach nie musisz, bo usuwając obiekt, usuwasz rejestrację delegata / zdarzenia (jak zwał tak zwał). :]

 

To jest właśnie elastyczność programowania, nie wracasz do jakiegoś kodu by nanieść poprawki. :]

Odnośnik do komentarza
Udostępnij na innych stronach

A po co tak? Ruszam with na wszystkich i sprawdzam object_index. To kwestia dopisania jednej linijki tak jaki i w przypadku delegacji. Prawda? :]

 

EDIT

Ok, to ja rozumiem że jeśli mi tak wygodniej to mam sobie zostać przy moim with xD

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
A po co tak? Ruszam with na wszystkich i sprawdzam object_index. To kwestia dopisania jednej linijki tak jaki i w przypadku delegacji. Prawda? :]
No właśnie! Kwestia dopisania linijki.

 

Tworzysz nowy rodzaj obiektu - dopisujesz linijkę

Tworzysz nowy rodzaj obiektu - dopisujesz linijkę

Tworzysz nowy rodzaj obiektu - dopisujesz linijkę

Usuwasz drugi obiekt, bo jednak niepotrzebny - usuwasz linijkę

Obiekt 1 i 3 jednak mogą być jednym typem obiektu - usuwasz linijkę, usuwasz linijkę, dodajesz linijkę.

Tworzysz nowy rodzaj obiektu - dopisujesz linijkę

Tworzysz nowy rodzaj obiektu - dopisujesz linijkę

Tworzysz nowy rodzaj obiektu - dopisujesz linijkę

 

Wyskakuje ci piękna drabina z ifami sprawdzającymi obiekty. I zawsze tworząc obiekt, musisz wracać do tej pętli. Musisz otworzć skrypt, dopisać, zamknąć skrypt. Skaczesz po skryptach, tracąc niepotrzebnie czas na takie prozaiczne, rutynowe działania.

 

Używając delegacji masz to w tyłku. Nie skaczesz po skryptach i już jesteś 10 linijek powrotu do kodu pętli wprzód (nie licząc otwierania i zamykania kolejnych okien), bo tylko nowo tworzonym obiektem się zajmujesz, a nie petlą w jakimś skrypcie! I nie musisz pamiętać czy już to zrobiłeś, czy tamto zaktualizowałeś, itd., gdyż tak jak pętla jest jawnie zależna od obiektów, tak delegacja nie. Problem dostosowania się nowego obiektu rozwiązujesz od strony tegoż obiektu a nie pętli w innym skrypcie.

 

To już lepiej jakbyś dawał wszystkim "zainteresowanym obiektom" jakis parent, ktory wywolujesz tak:

width ( obiekt_parent )

{

event_user( 0 );

}

 

Tylko, ze to wywazanie okna zamiast wchodzenie przez drzwi, bo masz juz niepotrzebny nowy obiekt i zaleznosci typu parent - child oraz przymus stosowania event_user0 na starcie (a chyba wogdniej jest wskazac event_user lub skrypt, ktory chcemy wywolac?). :]

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
Alternatywa - użyć listy obiektów i pętli for w with :P
Ale to już jest rozwiązanie ściśle powiązane z określonym problemem i nie wszędzie zda egzamin. Delegacje są uniwersalne. :] Poza tym w liście trzymasz tylko jedną zmienną, a nie np. parę kluczy, czyli możesz trzymać tylko id tych obiektów. I w ten sposób znowu musisz sobie coś ustalić: "Aha, dla dostosowywania obiektów do zimy, będę wykorzystywał zawsze event_user0 w tych obiektach". No i widzisz co narobiłeś? Znowu z góry ustaliłeś jakiś przymus tymże obiektom od strony pętli w innym kodzie. Ubezwłasnowolniłeś je miast dać im swobodę wyboru tegoż event_usera. Próbuj dalej. :]
Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
Mogę "wpakować" parę zmiennych do jednej i je późnije odczytać. No i zawsze pozostaje mi wykonanie scripta zamiast event_userX. Ale skończmy tą dyskusję, to bez sensu :D
Skrypta, którego będziesz musiał nadzorować i edytować przy każdej zmianie struktury obiektów w grze. A co do wpakowania paru zmiennych do jednej. Musisz pisać specjalne skrypty, operacje na stringach do najszybszyc nie naleza i musisz wprowadzic porzadna obsluge seperatora by skrypt byl uniwersalny. Tablicy też nie możesz dac, bo GM nie obsluguje czegos takiego. Podpowiem tylko ze delegacja przeze mnie stworzona to specjalna lista list by wlasnie uniknac stringow...

 

A teraz zobacz ile alternatywnych rozwiazan juz podales (juz nie liczac, ze ja drugie podalem ;P ):

- with z if'ami

- obiekt parent

- lista z petla i zserializowanymi zmiennymi

- specjalny, osobny skrypt do zarzadzania

 

A ja mam na to prosta odpowiedz:

- delegacje

 

Popatrz uwaznie i zastanow sie czy warto zaprzatac sobie glowe tymi pierwszymi technikami, ktore trzeba na nowo dostosowywac do kazdego projektu i skakac z kodu na kod czy ... po prostu zaoszczedzic sobie klopotow uzywajac delegacji. Wybor nalezy do Ciebie. :]

 

EDIT: Znam rysunek, ale wbrew pozorom taka dyskusja ma sens, bo ma na celu pokazać w czym delegacje pomagają*. :) Nawet jest odpowiedni temat poświęcony metodologii obsługi zdarzeń (której jednym z wcieleń sa delegacje). http://pl.wikipedia.org/wiki/Programowanie...ane_zdarzeniami

 

*A pomagaja w szczegolnosci tam gdzie nie uswiadczysz with'y czy event_performow.

Odnośnik do komentarza
Udostępnij na innych stronach

Przeczytałem sobie jeszcze to na Wiki i mogę powiedzieć że delegacje naprawdę się mogą przydać, szkoda że nie są wbudowane już w język skryptowy GMa. No i patrz, jednak nauka drogą prób i błędów ma swoje plusy :P

 

Widze już zastosowanie tego w grach multiplayer.

 

No i oczywiśczie Ranmie należy się pochwała!

 

*Pochwała* :3

 

EDIT

A ja już mam problem. Chcę usunąć delegaty z obiektów o nazwie "obiekt" to wpisuje DelegateDeleteAll( obiekt ); i ciach! Nie działa! To próbuje po DelegateDeleteAll( obiekt.object_index ) i ciach! Nie działa, dlaczego? Bo szuka tylko po ID obiektów nie wliczając jego typu.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
Widze już zastosowanie tego w grach multiplayer.
Szczerze mówiąc to ja jeszcze tego nie widzę, bo nie rozmyślałem nad tym. Jakiś przykład? :)

 

A ja już mam problem. Chcę usunąć delegaty z obiektów o nazwie "obiekt" to wpisuje DelegateDeleteAll( obiekt ); i ciach! Nie działa! To próbuje po DelegateDeleteAll( obiekt.object_index ) i ciach! Nie działa, dlaczego? Bo szuka tylko po ID obiektów nie wliczając jego typu.
Nie wiem czy dobrze zrozumiałem, ale typy tylko i wyłącznie tak się obsługuje:
eLeftPressed = DelegateCreate();
DelegateAddEvent( eLeftPressed, 3, Lampa );
DelegateDeleteAll( Lampa );

lub:

eLeftPressed = DelegateCreate();
DelegateAddEvent( eLeftPressed, 3, 100001 );
DelegateDeleteAll( 100001 );

 

Chyba, że chodzi Ci o ten fragment manuala:

Uwaga! Gdy odrejestrujemy okreslony obiekt, to i tak beda mu wywolywane

zdarzenia, ktore zostaly zarejestrowane ogolnie dla typu obiektu!

I to działa także na odwrót czyli nie odrejestrujesz zdarzenia, którego właścicielem jest konkretny obiekt (id), za pomocą odrejestrowania typu tego obiektu. O takie coś chodzi?

 

Swoją drogą chyba wprowadzę tą poprawkę sprawdzającą czy obiekt właściciel zdarzenia istneje (w DelegateCall) i jeśli nie, to usuwa wszystkie jego delegaty za pomoca funkcji DelegateDeleteAll.

Odnośnik do komentarza
Udostępnij na innych stronach

I to działa także na odwrót czyli nie odrejestrujesz zdarzenia, którego właścicielem jest konkretny obiekt (id), za pomocą odrejestrowania typu tego obiektu. O takie coś chodzi?
Dokładnie o coś takiego. Ale to chyba dodam sobię we własnym zakresie :)

Szczerze mówiąc to ja jeszcze tego nie widzę, bo nie rozmyślałem nad tym. Jakiś przykład?
Serwer odbiera wiadomość od jednego z klientów, teraz rozpoznaje jej identyfikator i gracza który wysyłał wiadomość, na podstawie tego wysyła odpowiednie rozkazy do innych graczy. Nie muszę robić listy graczy etc. bo mogę sobie za pomocą dedykacji uzyskać informacje na temat nicka, pozycji, portu, ip oraz ewentualnie zmienić ich wartość. Mogę też wywołać jedną instrukcją np. wysłanie pozycji wybranego gracza do innchy.

 

Trochę naciągany przykład, wiem :P

 

EDIT

Mam pomysł jak kasować automatycznie delegacje po zniszczeniu obiektu. Dodać to w DelegateAddEvent i DelegateAddScript tuż przed return:

/*
* Automatczne kasowanie delegata w przypadku zniszczenia obiektu
*/
    object_event_add( _id.object_index, ev_destroy, 0, 'DelegateDeleteAll( id );');

Nie najlepszy pomysł ale skuteczny.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

Ja tylko jeszcze dodam:

 

Przeczytałem sobie jeszcze to na Wiki i mogę powiedzieć że delegacje naprawdę się mogą przydać, szkoda że nie są wbudowane już w język skryptowy GMa.
Dlatego trzeba czekać na GM7 i zobaczyć jaką formę będą miały rozszerzenia.
Odnośnik do komentarza
Udostępnij na innych stronach

Programowanie sterowane zdarzeniami jest metodą tworzenia programów w środowiskach wieloprocesowych i pseudowieloprocesowych, które ma zapewnić możliwość jednoczesnej pracy wielu programów w jednej instancji systemu operacyjnego. Polega na przechodzeniu do wykonywania poszczególnych bloków asynchronicznie (niezależnie od czasu, jaki upłynął od zakończenia pracy poprzedniego modułu)
Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

Marmot, akurat to nienajlepszy cytat, bo GM nie jest środowiskiem wieloprocesowym, więc te delegacje co zrobiłem są synchronicznie wywołane (zresztą tak jak domyślnie i C#, ale tam można też właśnie asynchronicznie wywoływać).

Odnośnik do komentarza
Udostępnij na innych stronach

No i proszę. Z Ranmusa zrobił się już programista :D Co Ty właściwie jeszcze robisz w GM - po tym dodatku i jego kodzie myślę, że byłbyś w stanie napisać własny program do konstruowania gier :lol:

Sam dodatek jest wspaniały. Tyle pracy można nim zaoszczędzić. Ciekawe czemu Mark o tym nie pomyślał? Może uznał, że tak wygodne sterowanie zdarzeniami nie bedzie potrzebne albo jeszcze nie wiedział o tym sposobie. Ciekawe czy to się zmieni w nowej wersji GM. A wysyłałeś to na główne forum (nie zaglądam tam często)?

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...