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)
| | |-+  [Scr] Vind de instantie met de hoogste waarde van variabele
Pagina's: [1]
« vorige volgende »
Print
Advertenties

Erik Leppen
Forumbeheerder


Offline Offline

Berichten: 9655


WWW
« Gepost op: 6 Mei 2013, 09:40:49 »

GM-versie: Game Maker 7 GameMaker 8 Game Maker Studio
Pro vereist: Nee
Niveau: Gemiddeld

Er wordt heel vaak gevraagd naar een script om van alle instanties van een bepaald object obj die instantie te vinden met de hoogste waarde van een bepaalde variabele variable. Logisch, want dat kun je voor heel veel dingen gebruiken:


Toepassingen
  • AI-beestjes kunnen op zoek naar healthpacks met de grootste healthwaarde.
  • AI-beestjes kunnen op zoek naar vijanden met de minste hitpoints.
  • AI-beestjes kunnen op zoek naar healthpacks met de grootste waarde voor (healthwaarde / afstand).
  • In een torenbouwspel is de instantie die je score bepaalt diegene die het hoogst ligt; dat is de instantie met de kleinste waarde van y.
  • De oudste instantie is die met de laagste waarde van id. GameMaker 8
  • De oudste instantie is die met de laagste waarde van het creatietijdstip, of de hoogste waarde van je leeftijdsvariabele.
  • Als je instanties bijhoudt voor geluiden, kun je als dat nodig is het geluid met het laagste volume stoppen.
  • Als je instanties bijhoudt voor plaatjes, kun je als dat nodig is het plaatje met de laagste alpha-waarde weghalen.
  • Als je van NPC's bijhoudt hoe veel ze gesproken hebben, kun je de NPC die het minst gesproken heeft iets laten doen.
  • Je kan soms een spel spannender maken door de speler met de minste punten een kleine beloning te geven.
  • Als inventory-items een gewicht hebben kun je het zwaarste item vinden.
  • Als shop-items een prijs hebben kun je het goedkoopste item vinden.
  • Je kan de speler met de hoogste score apart weergeven.
  • Als je alle blokken netjes op het scherm wil laten passen, vind de laagste en hoogste x- en y-waardes van alle blokken en stel je de view daar op af.
Zoals je ziet zijn er genoeg toepassingen te bedenken.



Hieronder vind je onder andere dit script, maar ook een heleboel andere handige kleine scriptjes voor het werken met instanties:


Scripts

Vind die instantie van een opgegeven object met hoogste waarde van variabele v, manier 1.
Dit script gaat simpelweg alle instanties af en controleert of v groter is dan de grootste tot nog toe gevonden waarde, zo ja, bewaart de id. Verder wat voorzorgsmaatregelen als er geen instantie bestaat.
GML:
//instance_maximize(obj) geeft de id van de instantie van object obj
//met de hoogste waarde van v; noone als er geen instanties van obj zijn.
var best_instance, best_value, obj;
obj = argument0;
if not instance_exists(obj) {return noone;}

best_instance = obj.id;
best_value = best_instance.v;

with obj {
  if v > best_value {
    best_value = v;
    best_instance = id;
  }
}
return best_instance;
Edit 3 augustus 2014: bugfix

Vind die instantie van een opgegeven object met hoogste waarde van variabele v, manier 2.
Verschil met manier 1 is dat manier 2 begint met een andere beginwaarde voor maxv; die je zelf opgeeft. Die waarde moet een ondergrens zijn, zodat alle instanties altijd een grotere v-waarde hebben dan die beginwaarde en dus opgemerkt worden. De reden dat deze er bij staat is omdat dit script makkelijker aan te passen is naar scripts hier verder onder. Het voordeel van deze aanpak is dat je geen instance_exists test meer nodig hebt, omdat het automatisch zo is dat als er geen instanties van het opgegeven object zijn, dat dan noone wordt teruggegeven (beginwaarde van maxinst). Dit hebben we straks nodig voor de aangepaste scripts.
GML:
//instance_maximize_alt(obj, v_lower_limit) geeft de id van de instantie van object obj
//met de hoogste waarde van v; noone als er geen instanties van obj zijn.
var maxinst, maxv;

maxinst = noone
maxv = argument1

with argument0 {
  if v > maxv {
    maxv = v
    maxinst = id
  }
}
return maxinst
Als je de minimale waarde van v zoekt, vervang dan ">" door "<".

Vind die instantie van een opgegeven object met hoogste waarde van variabele v, manier 3.
Hier nog een iets anders opgebouwde manier:
GML:
//instance_maximize_alt2(obj) geeft de id van de instantie van object obj
//met de hoogste waarde van v; noone als er geen instanties van obj zijn.
var Q;
Q = ds_priority_create()

  with argument0 {
    ds_priority_add(Q, id)
  }
  if ds_priority_empty(Q) {choice = noone}
  else {choice = ds_priority_find_max(Q)}
ds_priority_destroy(Q)
return choice
Als je de minimale waarde van v zoekt, vervang dan "max" door "min".


Vind die hoogste waarde van v voor alle instanties van een opgegeven object.
Het enige wat ik veranderd heb aan manier 1 hierboven is dat ik niet maxinst, maar maxv als returnwaarde geef. Deze truc werkt voor alle scripts, als je niet de instantie nodig hebt maar de relevante v-waarde.
GML:
//instance_maximize(obj) geeft de id van de instantie van object obj
//met de hoogste waarde van v; noone als er geen instanties van obj zijn.
var maxinst, maxv;

if not instance_exists(argument0) {return noone}

maxinst = obj.id
maxv = inst.v

with argument0 {
  if v > maxv {
    maxv = v
    maxinst = id
  }
}
return maxv



Vind die instantie van een opgegeven object die voldoet aan voorwaarde X, met de hoogste waarde van variabele v van alle instanties van dit object die voldoen aan voorwaarde X.
Het enige verschil mer manier 2 van het originele script hierboven, is de extra voorwaarde if X. Net als manier 2 geeft het script dus automatisch noone als er geen instanties van het opgegeven object bestaan die voldoen aan X. We kunnen hier nu niet meer zomaar instance_exists voor gebruiken. Vandaar dat we manier 2 nodig hadden. Je kan manier 3 op dezelfde manier aanpassen.
GML:
//instance_maximize_if_x(obj, v_lower_limit) geeft de id van de instantie van object obj
//die voldoet aan X, met de hoogste waarde van v van alle instanties van object obj
//die voldoen aan X; noone als er geen instanties van obj zijn die voldoen aan [i]X[/i].
var maxinst, maxv;

maxinst = noone
maxv = argument1

with argument0 {
  if X {
    if v > maxv {
      maxv = v
      maxinst = id
    }
  }
}
return maxinst
Als je de minimale waarde van v zoekt, vervang ">" door "<", en vervang v_lower_limit door v_upper_limit, oftewel, geef een bovengrens op als beginwaarde.

Vind die instantie van een opgegeven object waarvoor script S "waar" geeft, met de hoogste waarde van variabele v van alle instanties van dit object waarvoor script S "waar" geeft.
Het enige verschil met bovenstaande is dat het script nu een argument geworden is.
GML:
//instance_maximize_if_script(obj, v_lower_limit, filtering_script)
//geeft de id van de instantie van object obj waarvoor filtering_script() waar is,
//met de hoogste waarde van v van alle instanties van object obj waarvoor filtering_script() waar is;
//noone als er geen instanties van obj zijn waarvoor filtering_script() waar is.
var maxinst, maxv;

maxinst = noone
maxv = argument1

with argument0 {
  if script_execute(argument2) {
    if v > maxv {
      maxv = v
      maxinst = id
    }
  }
}
return maxinst

Geef of er instanties bestaan van een opgegeven object die voldoen aan voorwaarde X.
Doordat het return-statement het script afbreekt wordt bij de eerste instantie die voldoet aan X, het script meteen gestaakt. Het script kost dus alleen veel rekentijd als er veel instanties zijn die niet voldoen aan X.
GML:
//instance_exists_where_x(obj) geeft een instantie van object obj die voldoet
//aan X; noone als geen enkele instantie van object obj voldoet aan X.
with argument0 {
  if X {
    return true
  }
}
return false

Geef een instantie van een opgegeven object die voldoet aan voorwaarde X.
GML:
//instance_find_where_x(obj) geeft een instantie van object obj
//die voldoet aan X; noone als geen enkele instantie van object obj voldoet aan X
with argument0 {
  if X {
    return id
  }
}
return noone

Geef een willekeurige instantie van een opgegeven object die voldoet aan voorwaarde X.
Om willekeurig te laten zijn zul je alle instanties moeten afgaan die voldoen aan X.
GML:
//instance_choose_where_x(obj)
var li, choice;
li = ds_lists_create()
  with argument0 {
    if X {
      ds_list_add(li, id)
    }
  }
  if ds_list_empty(li) {choice = noone}
  else {choice = ds_list_choose(li)}
ds_list_destroy(li)
return choice
Zie Randomscripts voor ds_list_choose.


Tel het aantal instanties van een opgegeven object die voldoen aan voorwaarde X.
Om te kunnen tellen zul je de voorwaarde op alle instanties moeten toetsen. Er is geen kortere weg.
GML:
//instance_count_where_x(obj)
var count;
count = 0
with argument0 {
  if X {
    count += 1
  }
}
return count

Bereken de som van alle waardes van v van alle instanties van een opgegeven object.
Ook hier moet je alle instanties afgaan, want je hebt ze allemaal nodig.
GML:
//instance_sum_v(obj)
var sum;
sum = 0
with argument0 {
  sum += v
}
return sum


Opmerkingen

Voor het argument obj kun je een objectnaam opgeven, of het gereserveerde woord all, als je alle objecten wil testen.

Als je een objectnaam opgeeft, worden van alle kindobjecten van dat object ook alle instanties afgegaan. Als je bijvoorbeeld alle vijanden wil afgaan, maak dan een nieuw vijandouderobject en geef al je vijandobjecten dat vijandouderobject als ouder (parent). Wil je van een geretourneerde instantie weten van welk objecttype die is, gebruik dan de variabele object_index.

Laatst bijgewerkt 14 mei: script toegevoegd dat instanties telt die voldoen aan een voorwaarde en dat een variabele uit meerdere instanties optelt

« Laatste verandering: 13 Augustus 2014, 17:13:21 door Erik Leppen »

Naar boven Gelogd

Maarten Baert
Forumbeheerder


Offline Offline

Berichten: 4942

Gelieve quote te gebruiken als je PMs beantwoordt.


WWW
« Antwoord #1 Gepost op: 6 Mei 2013, 16:36:31 »

Ik vermoed dat die versie met priority queues en lists best traag zullen worden voor grote aantallen instanties. Heb je toevallig metingen gedaan om te zien welke van deze versies het snelst is? Misschien nuttig om te weten Gemoedelijk.


Naar boven Gelogd

Martin Beentjes
Gebruiker


Offline Offline

Berichten: 2332

Gelieve quotes gebruiken bij PB's.


« Antwoord #2 Gepost op: 7 Mei 2013, 09:37:38 »

Leuke en handige tutorial. Zeker bij het schrijven van AI's is dit heel handig.

Misschien dat ik na mijn examens nog eens met GameMaker ga werken en dat ik dit misschien wel eens kan gebruiken. We zullen zien. Gemoedelijk

Naar boven Gelogd

Erik Leppen
Forumbeheerder


Offline Offline

Berichten: 9655


WWW
« Antwoord #3 Gepost op: 7 Mei 2013, 13:42:19 »

Heb je toevallig metingen gedaan om te zien welke van deze versies het snelst is?
Nee Gemoedelijk


Maar het doel van mijn tutorial is ook niet om mensen de snelste code te geven. Het is om een aantal manieren te laten zien hoe je een computer vertelt hoe die "de X met de grootste Y" kan vinden, aangezien sommige mensen moeite lijken te hebben die taalconstructie te vertalen naar computertaal.


Naar boven Gelogd

Perry26
Gebruiker


Offline Offline

Berichten: 1054

Vragen over GM bij mij WEL via pm :p


« Antwoord #4 Gepost op: 7 Mei 2013, 14:23:53 »

Ja, maar ik denk alsnog dat het haniger is als iemand dit meet, daarom zal ik het misschien morgen nog doen (als ik tijd heb.)

Naar boven Gelogd

Maarten Baert
Forumbeheerder


Offline Offline

Berichten: 4942

Gelieve quote te gebruiken als je PMs beantwoordt.


WWW
« Antwoord #5 Gepost op: 7 Mei 2013, 14:37:02 »

Maar het doel van mijn tutorial is ook niet om mensen de snelste code te geven. Het is om een aantal manieren te laten zien hoe je een computer vertelt hoe die "de X met de grootste Y" kan vinden, aangezien sommige mensen moeite lijken te hebben die taalconstructie te vertalen naar computertaal.
Kan zijn, maar als je een O(n) constructie samen met een O(n*log(n)) (en dat is optimistisch) constructie in dezelfde tutorial vermeld als gelijkwaardige alternatieven, lijkt het me ook niet slecht om dat verschil even te vermelden Knipoog.


Naar boven Gelogd

Flumble
Gebruiker


Offline Offline

Berichten: 2019


« Antwoord #6 Gepost op: 13 Augustus 2014, 12:13:33 »

Er is in dit bericht verwarring ontstaan doordat in een paar blokken code obj voorkomt in plaats van argument0.
Is het de bedoeling dat overal argument0 staat of dat er voor meer duidelijkheid een tijdelijke variabele obj=argument0 in hoort?

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-2021 Nederlandse Game Maker Community