game maker
Gebruikersnaam:
Wachtwoord:
Home Info Forums Help
Welkom, Gast. Alsjeblieft inloggen of registreren.
+  Forums
|-+  Werken met Game Maker
| |-+  Tutorials en Uitbreidingen (Moderator: Maarten Baert)
| | |-+  [tut] Studio: Asynchrone functies
Pagina's: [1]
« vorige volgende »
Print
Advertenties

Florian van Strien
Jurylid


Offline Offline

Berichten: 2420


« Gepost op: 24 Januari 2013, 20:04:51 »

Asynchrone functies in GameMaker: Studio

GameMaker: Studio bevat veel nieuwe functies. Een aantal van deze nieuwe functies doet dingen terwijl je spel gewoon blijft werken. Dit zijn de asynchrone ("asynchronous") functies. In deze tutorial zal ik de belangrijkste van deze functies behandelen, samen met het nieuwe event (inclusief subevents) dat bij die functies hoort.

GM-versie: Game Maker Studio
Studio-versie: De meeste functies zijn alleen beschikbaar voor Standard en hoger, andere zijn ook beschikbaar in Free.
Niveau: Gemiddeld. Je moet wel een aardige kennis van GML hebben, want al deze functies gaan via GML. Ook is het handig als je weet hoe je met ds_maps moet werken.
Opmerking: Veel functies in deze tutorial hebben in dit forum geen syntax-coloring, maar ze bestaan wel (ze zijn alleen nieuw, en nog niet toegevoegd aan het syntax-colorstript).

Inhoud
-De basis
-Dialoogvensters
-Afbeeldingen en geluid van internet laden
-HTTP
-Slot

De basis
Asynchrone events maken het mogelijk iets te doen terwijl je spel voor de rest gewoon blijft werken. Zo kun je een plaatje van internet laden terwijl je spel gewoon blijft werken. Ook kun je dialoogvensters laten zien zonder de runner te blokkeren. Voor elke actie is er een verschillende functie, maar het gebruik van de functies lijkt wel op elkaar. Natuurlijk roep je elke functie eerst aan. Later kun je in een speciaal event dan het resultaat opvragen. Soms zul je meerdere asynchrone functies achter elkaar gebruiken. Het is dan handig om te weten voor welke functie je het resultaat terugkrijgt. Hiervoor geven alle asynchrone functies een zogenaamde handle terug. Je kunt in het asynchronous event dan kijken van welke functie je het resultaat terugkrijgt, door die handle te vergelijken met het id van het asynchronous event.
Laten we de functie get_string_async() als voorbeeld gebruiken. Deze functie geeft de speler de mogelijkheid een tekst in te voeren (het is simpelweg de asynchrone versie van get_string()). Je kunt deze functie als volgt aanroepen:
GML:
msghandle=get_string_async("Wat is je naam?","")
De handle wordt nu opgeslagen in de variabele msghandle. Merk op dat het spel na het uitvoeren van deze functie gewoon blijft draaien. Nu willen we weten wanneer de gebruiker het venster sluit en de naam opslaan in een variabele. Om te kijken wanneer de functie klaar is kunnen we een asynchronous event gebruiken. Zo'n event wordt uitgevoerd wanneer een asynchrone functie klaar is. Het wordt uitgevoerd in alle instances die het hebben. Het event is hier te vinden in het event schermpje:

Als je op dit event klikt zal er een menuutje weergeven worden:

Voor elk type van asynchrone events is er een ander subevent. get_string_async() weergeeft een dialoogscherm. Deze geven hun resultaat in het 'Dialog' event. We gaan naar het resultaat kijken in dat event.
In alle hier behandelde asynchrone events is een speciale variabele beschikbaar waarmee je het resultaat kunt verkrijgen: async_load. Deze verwijst naar het id van een ds_map. De map bevat altijd de volgende twee items: id en status. Het id kun je vergelijken met een handle om te kijken of je het resultaat van de functie met die handle hebt teruggekregen. Bij het voorbeeld kan dat als volgt:
GML:
if(msghandle==ds_map_find_value(async_load,"id"))
{

}
Daarna gaan we kijken of de actie waar het event voor wordt aangeroepen is gelukt. Daarvoor is de variabele status. Als deze true is, is het gelukt. Als deze false is, is er iets misgegaan. Bij ons voorbeeld bevat status true als er op OK is geklikt, en false als het schermpje is weggeklikt of op een andere manier geanuleerd. Onze code wordt nu:
GML:
if(msghandle==ds_map_find_value(async_load,"id"))
{
    if(ds_map_find_value(async_load,"status")==true)
    {
        //Ok! Het is gelukt! De gebruiker heeft nu zijn naam ingevoerd. Nu nog weten welke naam hij heeft ingevoerd.
    }
    else
    {
        //De gebruiker heeft het schermpje weggeklikt ofzo. Ga hem slaan.
    }
}
Bij veel asynchrone events is er ook nog een bepaald resultaat. Meestal wordt dit opgeslagen in het ds_map item result. Bij het voorbeeld is hier de naam van de speler in opgeslagen. Laten we die opslaan in de variabele 'username', en daarna naar de volgende room gaan. Onze volledige code is nu:
GML:
if(msghandle==ds_map_find_value(async_load,"id"))
{
    if(ds_map_find_value(async_load,"status")==true)
    {
        username=ds_map_find_value(async_load,"result")
        room_goto_next()
    }
    else
    {
        //De gebruiker heeft het schermpje weggeklikt ofzo. Ga hem slaan.
    }
}
Ik heb nu alleen get_string_async() behandeld, maar eigenlijk is de basis van alle asynchrone functies hetzelfde. Wel hebben veel functies een net iets andere async_load ds_map. Ook roep je alle functies natuurlijk op een andere manier aan. In de volgende hoofdstukken zal ik alle asynchrone functies behandelen, te beginnen met de dialoogvensters.

Dialoogvensters
In vorige versies van GameMaker blokkeerden dialogen altijd je spel. Nu is dat niet meer zo: je spel gaat gewoon door (op de achtergrond) terwijl het bericht wordt weergegeven. Veel mobiele systemen staan het namelijk niet toe de 'runner' te blokkeren. Voor de rest lijken de functies erg op de oude functies, ze geven alleen niet direct een resultaat, in plaats daarvan kun je dat ophalen in het Async Dialog event. De volgende functies bestaan:
show_message_async(string)
Asynchrone versie van show_message()
De meest simpele functie. Dit laat een bericht zien aan de speler, met een OK-knop. Bij sommige exports kan de speler ook nog annuleren (bijvoorbeeld met het kruisje bij Windows) De ds_map bevat alleen de twee standaarditems: id en status. status geeft hier false als het is geanuleerd of weggeklikt, en true als er op OK is gedrukt.

GML:
show_question_async(string)
Asynchrone versie van show_question()
Hetzelfde als de vorige functie: deze keer zijn er alleen twee knoppen: "Yes" en "No". De status geeft true als de gebruiker op "Yes" heeft gedrukt, en false na een klik op "No" (of als het bericht is weggeklikt).

GML:
get_string_async(string, default)
Asynchrone versie van get_string()
Deze functie vraagt de gebruiker om een string, waarbij je een tekst kunt opgeven om boven het invoervak te zetten en een standaard tekst. Voor de rest van de uitleg: zie hierboven. ;)

GML:
get_integer_async(string, default)
Asynchrone versie van get_integer()
Hetzelfde als get_string_async(), maar dit keer moet de gebruiker een geheel getal invoeren. Het ingevulde resultaat is hier in het map-item value te vinden.

GML:
get_login_async(name, password)
Deze functie vraagt de gebruiker om een gebruikersnaam en een wachtwoord. Je kunt deze functie hetzelfde gebruiken als get_string_async(). Dit keer is de gebruikersnaam opgeslagen in het username item van de async_load ds_map, en het wachtwoord in password. Je kunt bij deze functie ook een standaard naam en wachtwoord opgeven, bijvoorbeeld als je de gebruikersnaam automatisch wilt invullen als de speler er al een keer één had ingevuld. Overigens was dit de eerste async dialog functie in GameMaker; deze bestond al voor alle anderen.

Afbeeldingen en geluid van internet laden
Het is al lange tijd mogelijk in GameMaker om afbeeldingen (sprites en backgrounds) en geluid (sounds) van de computer van de speler naar het spel te laden. Dit is nog steeds mogelijk met dezelfde functies als vroeger. Als je van de computer laadt is er ook geen asynchroon event, dit werkt gewoon hetzelfde als in vorige versies. Het is nu echter ook mogelijk afbeeldingen en geluiden van internet te laden. Je moet dan een URL opgeven bij de functies in plaats van een path op de computer van de speler. Voorbeeld:
GML:
spr_header=sprite_add("http://www.game-maker.nl/img/toplogo.png",1,false,false,0,0)
Dit laadt de header van het NGMC in je spel in als een sprite, die één subimage moet bevatten, zonder de achtergrond te verwijderen, zonder te smoothen, en met de orgin op (0,0). Als je deze functie aanroept is de afbeelding nog leeg, en je spel blijft gewoon draaien terwijl de afbeelding geladen wordt. Zodra de afbeelding is geladen, wordt een async 'Image loaded' event getriggerd. De async_load ds_map die je bij de dat event kunt gebruiken, zal zoals normaal de id (de id van het event is hier gelijk aan de index van de sprite) en de status bevatten. Als de status kleiner dan 0 is, is er een error geweest. Als laatste zal de ds_map de filename bevatten. Dit is het pad waarvan je de afbeelding hebt geladen. De code in het asynchrous Image loaded event van het voorbeeld zou er zo uit kunnen zien:
GML:
if(spr_header==ds_map_find_value(async_load,"id"))
{
    if(ds_map_find_value(async_load,"status")>=0)
    {
        //Het is gelukt! Nu slaan we de url voor de grap op in de variable 'url'.
        url=ds_map_find_value(async_load,"filename")
    }
    else
    {
        //Zeg de speler dat het laden mislukt is.
        show_message_async("Het laden van bepaalde afbeeldingen is helaas mislukt. Controleer uw internetverbinding.")
    }
}
Let wel op: op de meeste platforms mogen ingeladen afbeeldingen alleen in png-formaat zijn. Op Windows en Mac is er een kans (dit hangt van het systeem van de gebruiker af) dat ook gif, jpg en/of bmp wordt toegelaten. Op bepaalde platforms zal er een error optreden (waarschijnlijk is dit een bug in GameMaker) als er geen internetverbinding is (dit geldt waarschijnlijk voor alle functies die met internet verbinding maken). Als workaround kun je eerst kijken of er internetverbinding is met de functie:
GML:
os_is_network_connected()
Deze geeft simpelweg een boolean terug of er internetverbinding is.

Bij geluiden is het precies hetzelfde, het event heet dan echter 'Sound loaded'. De ds_map is ook precies hetzelfde. Het geluid kan momenteel in mp3 of wav-formaat zijn, ogg formaat wordt volgens de roadmap in de volgende grotere versie (1.2) van GameMaker: Studio toegevoegd.

Ik zal de functies niet te uitgebreid behandelen, ze zijn namelijk precies hetzelfde als in vorige versies van GameMaker, maar dan met de mogelijkheid een url in te voeren in plaats van een lokaal path. Voor meer informatie over specifieke functies kun je in de handleiding kijken.
GML:
sprite_add(fname, imgnumb, removeback, smooth, xorig, yorig)
Voeg een sprite toe aan je spel. Als fname kun je dus nu ook een webadres opgeven. Voor de rest kun je het aantal images opgeven, of alle pixels met de kleur van de pixel linksonder transparant moeten worden, of de randen gesmooth moeten worden, en de positie van het orgin.

GML:
sprite_replace(ind, fname, imgnumb, removeback, smooth, xorig, yorig)
Vervangt de sprite met de index ind door de sprite in fname. Deze functie returnt geen id/handle, hiervoor kun je gewoon het id van de te vervangen sprite gebruiken.

GML:
background_add(fname, removeback, smooth)
Voegt een background toe aan het spel. Returnt de id van de nieuwe background. Als je bij fname een url invoert, moet je wachten tot de background is geladen (en dus een async event is getriggerd) met het drawen, anders heb je kans op errors.

GML:
background_replace(ind, fname, removeback, smooth)
Vervangt de background met de index ind door de background in fname.

GML:
sound_add(fname, kind, preload)
Laadt een sound. De laatste twee argumenten kun je als je het nieuwe audio-systeem gebruikt gewoon op 0 laten staan, deze doen daar niets.

GML:
sound_replace(ind, fname, kind, preload)
Zelfde als sound_add(), maar dit keer wordt een bestaand sound vervangen.

HTTP
Nu komen we bij de twee functies die ik het interessantst vindt van alle async functies: http_get() en http_post_string(). Je kunt echt heel veel met deze twee functies, zo heb ik onder andere Scoreoid en de GameJolt achievement API werkend gekregen in GameMaker: Studio zonder het gebruik van DLL's. Deze functies kunnen namelijk verbinding maken met internet. Je kunt zo informatie naar servers versturen en van servers ophalen. Let wel op: je kunt geen bestanden versturen met deze functies, alleen tekst. Ik zal de basis van deze functies uitleggen aan de hand van http_get().
Deze functie haalt informatie van een bepaalde URL. De functie ziet er zo uit:
GML:
handle=http_get(url)
Dus, er is maar één argument: de url waar je informatie van wilt halen. Deze functie geeft een handle terug. Zodra GM klaar is met het ophalen van je informatie, wordt het async HTTP event getriggerd. Daar kun je zoals bij alle functies de async_load ds_map gebruiken om het resultaat te bekijken. Deze ds_map bevat een hoop informatie:
id: Hetzelfde als bij de andere functies. Dit is erg handig als je een heleboel requests achter elkaar stuurt, zodat je kunt kijken op welke request je antwoord krijgt.
status: Dit is kleiner dan 0 voor een error.
http_status: De http status code als er een error was.
URL: De url waar je de informatie vandaan hebt gehaald.
result: De informatie.
Het leuke van deze functie is, dat je hem ook kunt gebruiken om kleine stukjes informatie naar een server te sturen, en niet alleen om data op te halen. Je kunt namelijk parameters toevoegen. Dus als je een highscore wilt submitten zou je het zo kunnen doen (let wel op dat je/de server hier iets mee moet doen, maar daar gaat deze tutorial niet over):
GML:
handle=http_get("http://example.com/scores?name="+name+"&score="+string(score))
En stel dat je server "SUCCESS" verstuurt als het toevoegen van de score gelukt is, en "FAILURE" als het toevoegen van de score mislukt is, dan kun je de volgende code gebruiken in het async HTTP event:
GML:
if(ds_map_find_value(async_load,"id")==handle)and(ds_map_find_value(async_load,"status")>=0)
{
    if(ds_map_find_value(async_load,"result")=="SUCCESS")
    {
        //Gelukt! :D
    }
    else
    {
        //Mislukt. :(
    }
}
Dan is er ook nog http_post_string(). Deze functie is vergelijkbaar met de vorige, maar dit keer kun je ook nog wat informatie in de vorm van een string meesturen. De functie ziet er zo uit:
GML:
handle=http_post_string(url, string)
Je vraagt de results op dezelfde manier op als bij http_get(), de ds_map ziet er ook hetzelfde uit.

Slot
Naast de async functies die ik in deze tutorial heb behandeld zijn er nog twee (momenteel): IAP en Cloud. Omdat ik deze niet goed ken en ze maar voor bepaalde exports werken heb ik besloten ze niet in deze tutorial op te nemen. De IAP functies hebben te maken met In App Purchases (het kopen van dingen in je spel voor echt geld), voor meer informatie over deze functies en het bijbehorende event kun je in de help-index zoeken naar 'IAP event'. De Cloud functies hebben te maken met opslaan in de Cloud, maar werken momenteel alleen met Amazon WhisperSync. Voor meer informatie over deze functies kun je in de handleiding (Index) zoeken op 'Cloud Services'.

Deze tutorial is nu ten einde, ik hoop dat jullie er iets aan hebben! Gemoedelijk

« Laatste verandering: 28 Januari 2013, 17:27:31 door flori9 »

Mijn spellen: Swapblocks, circloO, BLcGR, 80 Seconds Cave, TRrBL, The Contact Machine
Ik heb meegewerkt aan: Lines (WP, iOS)
Tutorials: Shaders - de basis, Asynchrone functies

Mijn oude forumnaam was flori9.
Naar boven Gelogd

timo777
Gebruiker

Offline Offline

Berichten: 284

GML-HTML-CSS-AJAX-PHP-C++-C-Java-D-Git-Make


« Antwoord #1 Gepost op: 25 Januari 2013, 18:48:34 »

Handige tutorial voor asynchrone funties, oftwel non-blocking funties, vooral omdat ik het niet erg intuitief vind werken. Maar dat is mijn persoonlijke mening.  Knipoog

Ik gebruik zelf niet de laatste versie (i.v.m. bugs e.d.) maar ik weet dat het handig is.


Wat zou hier moeten staan?
Naar boven Gelogd

StefanJanssen
Gebruiker


Offline Offline

Berichten: 5211

Was StefannafetS


WWW
« Antwoord #2 Gepost op: 25 Januari 2013, 21:53:29 »

is de cloud een iCloud iets? ik zie hem ook niet in de afbeelding staan met de soorten asynchrone events.

Ik kijk morgen even goed naar de tutorial (nu even globaal gelezen)

EDIT: niet goed gelezen zie ik Gemoedelijk is met amazone cloud ding


Begrijp je iets niet in een uitleg van een gebruiker? Bekijk eerst de helpfile voor je iets vraagt
Naar boven Gelogd

arie2002
Gebruiker


Offline Offline

Berichten: 719

Logo gemaakt door jmaster2710


« Antwoord #3 Gepost op: 26 Januari 2013, 06:37:14 »

Bij Game Maker Studio heb ik die event niet? Twijfelachtig


Spellen
Gestopte Projecten: Tijdmachine - Shoot Them All!

Naar boven Gelogd

timo777
Gebruiker

Offline Offline

Berichten: 284

GML-HTML-CSS-AJAX-PHP-C++-C-Java-D-Git-Make


« Antwoord #4 Gepost op: 26 Januari 2013, 11:00:58 »

Je hebt het alleen in bepaalde versies waarschijnlijk. Ik zou niet weten welke...


Wat zou hier moeten staan?
Naar boven Gelogd

dvdtv
Wedstrijdleider


Offline Offline

Berichten: 4789

Eigenaar van het bedrijf: Meester Dennis.


WWW
« Antwoord #5 Gepost op: 22 Mei 2013, 11:05:36 »

Hij geeft bij mij steeds mislukt terug...

bij de http:
GML:
if(ds_map_find_value(async_load,"id")==tekst)and(ds_map_find_value(async_load,"status")>=0)
{
    if(ds_map_find_value(async_load,"result")=="SUCCESS")
    {
       show_message("Gelukt") //Gelukt! :D
    }
    else
    {
        show_message("Mislukt") //Mislukt. :(
    }
}

create:
GML:
tekst = http_get("//staatinpm")

draw:
GML:
draw_text(0,0,string(tekst))


Naar boven Gelogd

Florian van Strien
Jurylid


Offline Offline

Berichten: 2420


« Antwoord #6 Gepost op: 22 Mei 2013, 17:06:00 »

Hij geeft bij mij steeds mislukt terug...

bij de http:
GML:
if(ds_map_find_value(async_load,"id")==tekst)and(ds_map_find_value(async_load,"status")>=0)
{
    if(ds_map_find_value(async_load,"result")=="SUCCESS")
    {
       show_message("Gelukt") //Gelukt! :D
    }
    else
    {
        show_message("Mislukt") //Mislukt. :(
    }
}

create:
GML:
tekst = http_get("//staatinpm")

draw:
GML:
draw_text(0,0,string(tekst))
Probeer het is met een andere URL?
Edit: Nee, wacht, ik zie toch een probleempje met je code. Deze examplecode gaat ervan uit dat de server "SUCCESS" verstuurt als een actie (bijvoorbeeld het toevoegen van een score) gelukt is. Dat staat er ook bij. Bij jouw gaat het echter om ontvangen van data. Je kunt dan de waarde van de 'ds_map_find_value(async_load,"result")' ergens anders voor gebruiken dan de simpele controle die ik hier met een if-statement heb gedaan, bijvoorbeeld in een variabele stoppen.

« Laatste verandering: 22 Mei 2013, 17:12:22 door flori9 »

Mijn spellen: Swapblocks, circloO, BLcGR, 80 Seconds Cave, TRrBL, The Contact Machine
Ik heb meegewerkt aan: Lines (WP, iOS)
Tutorials: Shaders - de basis, Asynchrone functies

Mijn oude forumnaam was flori9.
Naar boven Gelogd

Ceymoonie
Gebruiker


Offline Offline

Berichten: 4839


WWW
« Antwoord #7 Gepost op: 19 Juli 2013, 16:51:52 »

Mooie tut!  =)
Ik snap alleen niet hoe het werkt met het ID van http_get
Zou je daar wat meer uitleg over willen geven hoe je een specifiek resultaat per http_get krijgt?

-C

Naar boven Gelogd

Florian van Strien
Jurylid


Offline Offline

Berichten: 2420


« Antwoord #8 Gepost op: 19 Juli 2013, 17:04:59 »

Mooie tut!  =)
Ik snap alleen niet hoe het werkt met het ID van http_get
Zou je daar wat meer uitleg over willen geven hoe je een specifiek resultaat per http_get krijgt?

-C
Nou, http_get geeft een ID terug. Dat kun je opslaan in een variable. Dus zo:
GML:
myvar=http_get(iets);
En later kun je dan opvragen of het id wat je terugkrijgt gelijk is (async event):
GML:
if(myvar==ds_map_find_value(async_load,"id"))

Het werkt hetzelfde met meerdere requests. Bijv.:
GML:
myvar=http_get(iets);
myvar2=http_get(iets_anders);
En dan kun je kijken of het id gelijk is aan de ene variable of aan de andere (async event):
GML:
var hetid=ds_map_find_value(async_load,"id");
if(myvar==hetid)
{
    //Antwoord op iets
}
else if(myvar2==hetid)
{
    //Antwoord op iets_anders
}


Mijn spellen: Swapblocks, circloO, BLcGR, 80 Seconds Cave, TRrBL, The Contact Machine
Ik heb meegewerkt aan: Lines (WP, iOS)
Tutorials: Shaders - de basis, Asynchrone functies

Mijn oude forumnaam was flori9.
Naar boven Gelogd

Ceymoonie
Gebruiker


Offline Offline

Berichten: 4839


WWW
« Antwoord #9 Gepost op: 19 Juli 2013, 17:09:39 »

Nou, http_get geeft een ID terug. Dat kun je opslaan in een variable. Dus zo:
[Snip]
Bedankt!

-C

Naar boven Gelogd

Advertenties
« vorige volgende »
Pagina's: [1]
Print


Topic Informatie
0 geregistreerde leden en 1 gast bekijken dit topic.

Ga naar:  

Powered by SMF 1.1.21 | SMF © 2006-2007, Simple Machines
www.game-maker.nl © 2003-2020 Nederlandse Game Maker Community