Ein Step-Event, dass alle Objekte steuert

    • GM 8

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Ein Step-Event, dass alle Objekte steuert

      Hallo Leute!
      Ich beschäftige mich nun schon seit Jahren mit dem Game Maker, habe schon mehrere Spiele entwickelt.
      Im Moment arbeite ich an einem Online-Spiel, welches sich schon in einem fortgeschrittenen Entwicklungsstand befindet.
      In diesem Spiel habe ich mehrere Objekte, die alle ein eigenes Step-Event haben. Ich stelle fest, dass ich dadurch wenig Kontrolle darüber habe, welches Objekt sein Step-Event zuerst ausführt.
      Ich weiß dass Game-Maker alle Step-Events in einer bestimmten Reihenfolge abarbeitet, jedoch würde ich lieber selbst entscheiden, in welcher Reihenfolge die einzelnen Step-Events ausgeführt werden.

      Also habe ich mir überlegt, ein Objekt zu erstellen, welches ein Step-Event besitzt. (Das einzige Step-Event im Spiel)
      In diesem Event werden dann in einer von mir vorgeschriebenen Reihenfolge "User-Events" für alle anderen Objekte ausgeführt. (Spielfiguren, Projektile, Gegner,...)

      Beispiel:

      GML-Quellcode

      1. //Step-Event des Hauptobjektes
      2. //Zuerst Spieler abarbeiten
      3. with (objSpieler)
      4. {
      5. event_user(0); //Was im Step-Event der Spielfiguren stehen würde
      6. }
      7. //Danach Gegner abarbeiten
      8. with (objGegner)
      9. {
      10. event_user(0); //Was im Step-Event der Gegner stehen würde
      11. }
      12. //...und so weiter
      Alles anzeigen


      Theoretisch habe ich dadurch mehr Kontrolle über die Reihenfolge.
      Macht es Sinn, mein Spiel nach dem Prinzip anzupassen? Habe ich dadurch Nachteile? Was haltet ihr davon? Habt ihr vielleicht bessere Vorschläge?

      "Make love, not Warcraft"
    • Die Ausführ-Reihenfolge wird durch die depth bestimmt (kleiner depth -> später ausgeführt).
      Wenn dir das nicht ausreicht, kannst du natürlich auf die Methode von unten zurückgreifen (etwa, wenn du draw- und step event getrennt ausführen willst).

      Um dann die "Kontrolle" darüber zu kriegen, wann ein Step ausgeführt wird, kannst du in jeden Objekt eine variable (z.B. step_depth), die die Reihenfolge der Steps bestimmt, festlegen und im Step event des Controller-Objekt eine ds_map erstellen und das ganze z.B. so machen:
      Spoiler anzeigen

      GML-Quellcode

      1. var ds_map, obj, step_d;
      2. ds_map = ds_map_create(); // Die ds_map wird erstellt (das kann man auch in das Game Start Event schreiben, wäre dann afaik besser; Dann bitte bei dem var ... das ds_map entfernen)
      3. with(all){
      4. if(id == other.id){continue;} // Das Controller hat kein Step (wenn doch, diese Zeile löschen)
      5. if(!variable_local_exists("step_depth")){continue;} // Keine step_depth variable?
      6. ds_map_add(ds_map, step_depth, id); // Das Objekt wird zur Map hinzugefügt
      7. }
      8. if(ds_map_size(ds_map) <= 0){exit;} // Kein Objekt hat ein "Step-Event"
      9. step_d = ds_map_find_first(ds_map); // Finde den ersten Depthwert...
      10. obj = ds_map_find_value(ds_map, step_d); // ... und die zugehörige Objektid
      11. with(obj){
      12. event_perform(ev_other, ev_user0); // Führe das "Step event" aus
      13. }
      14. step_d = ds_map_find_next(ds_map, step_d); // Finde den nächsten Depthwert...
      15. obj = ds_map_find_value(ds_map, step_d); // ... und die zugehörige Objektid
      16. while(step_d > 0){
      17. with(obj){
      18. event_perform(ev_other, ev_user0);// Führe das "Step event" aus
      19. }
      20. step_d = ds_map_find_next(ds_map, step_d); // Finde den nächsten Depthwert...
      21. obj = ds_map_find_value(ds_map, step_d); // ... und die zugehörige Objektid
      22. }
      23. ds_map_clear(ds_map); // Alle Werte werden glöscht.
      24. ds_map_destroy(ds_map); // Die ds_map wird gelöscht (das kann man auch in das Game End Event schreiben, wäre dann afaik besser)
      Alles anzeigen


      Ich hoffe, der Code ist einigermaßen verständlich!

      - Tobi97
    • Außer bei Draw wird meines Wissens die Instance-ID verwendet und nicht die Depth.

      Ferner ist das Abweichen von der GM-Norm recht langsam. Anstatt also alle Instanzen "kontrolliert" auszuführen, solltest du Objekte lieber gruppieren. Dies kannst du über Parents machen, die du selbst nie in einem Raum plazierst. Ansonsten arbeitest du dann auch mit User-Events und with-Statements zur Ausführung.

      Großes Aber:
      Oft braucht es die erzwungene Reihenfolge gar nicht. Versuche dein Spiel so zu designen, dass alles gleichzeitig passieren kann. Die Kollisionsengine des GMs berücksichtigt das (zumindest bin ich mir zu 95% sicher, dass bei einer Kollision zwischen zwei Instanzen immer beide Events ausgeführt werden, selbst wenn eins der beiden die Kollision bereits wieder auflöst. Das solltest du vorher nochmal testen).
      Hier eine kurze Erklärung, die auf dieser Annahme basiert:

      Step Event
      Spiellogik.

      Zwischen Step- und Kollision-Event
      Bewege alle Instanzen um hspeed und vpseed.

      Collision Event
      Prüfe auf Kollisionen und markiere alle betroffenen Objekte.
      Wenn eine der beteiligten Instanzen solid ist, setze die Instanz auf ihre vorherige Position zurück (oder beide?)
      Führe alle Kollision-Events aus.

      End Step
      Evtl. mehr Spiellogik.

      Draw Event
      Zeichnen.


      Dies erklärt auch, warum move_contact_solid in einem Kollisionsevent mit solid Instanzen funktioniert und warum bei non-solids move_outside_all benutzt werden muss.

      Edit: Nur um es deutlich zu machen: Ich vermute, dass der GM so arbeitet. Meine Tests dazu liegen schon etwas zurück und ich hab es mir blöderweise nicht notiert. Idealerweise kontrollierst du diese Annahmen mit ein paar eigenen Tests nochmal.