Auf der unteren Plattform weiterlaufen

  • GM 8
  • MewX schrieb:

    Ich habe collision_rectangle tatsächlich komplett außer Acht gelassen. Entsprechend haben meine Aussagen weiter oben nur bedingt Bestand.

    Du hast mit collision_rectangle zwei Möglichkeiten:
    Entweder, du behälst die größte Kollisionsmaske für den Spieler und machst mit collision_rectangle die nachträglichen Einschränkungen, oder du lagerst einen Teil ins Step- oder End-Step-Event aus. Letzteres lassen wir jetzt mal sein, auch wenn es wohlmöglich effizienter wäre.

    Die erste Möglichkeit bringt uns wieder zu dem Modell aus meinen ersten Antworten zurück (aus dem Kollisionsevent der Spielfigur mit der Wand):

    GML-Quellcode

    1. if (bbox_bottom <= other.bbox_bottom) {
    2. // Kollisionscode
    3. }

    Dies können wir korrigieren zu:

    GML-Quellcode

    1. if (collision_rectangle(bbox_left, bbox_bottom-8, bbox_right, bbox_bottom, other.object_index, true, true)) {
    2. // Kollisionscode
    3. }

    Ich habe das jetzt einfach so aus dem Kopf geschrieben, aber eigentlich sollte das funktionieren. Wichtig ist, dass das prec-Parameter auf true gesetzt ist.
    Es funktioniert leider immernoch nicht. Er bewegt sich immernoch Richtung obere Plattform, nur hört er jetzt damit auf wenn die collision_rectangle nicht mehr vorliegt, also wenn er quasi 8 pixel über dem Boden steht.
  • MewX schrieb:


    Ich weiß nicht, ob collision_rectangle auch Instanzen akzeptiert... probier also mal statt other.object_index nur other.
    Wenn ich nur other angebe dann macht er garnichts mehr, daran scheint´s also nicht zu liegen.

    In der Game Maker Hilfe steht das collision_rectangle die instance id wiedergibt wenn die collision zustande kommt und einen negativen Wert wenn sie nicht zustande kommt.

    Muss ich dann nicht abfragen ob collision_rectangle(...)>0 ist?

    GML-Quellcode

    1. if (collision_rectangle(bbox_left, bbox_bottom-8, bbox_right, bbox_bottom, other.object_index, true, true)>0) {// Kollisionscode
    2. }


    Und woran liegts eigentlich dass er sich nach oben bewegt?

    an

    y=-speed

    oder an

    move_to_contact?
  • Aaah, okay. Jetzt weiß ich auch wieder, warum ich die Funktion nicht so gerne mag.

    Die einfache Methode: if (collision_rec..(...) == other).
    Falls das nicht reicht, müsste man dies in eine Schleife packen. Ist die wiedergegebene Instanz nicht "other", wird diese deaktiviert und in einer Liste gespeichert. Nachdem die andere Instanz dann gefunden wurde oder keine Kollision mehr zustande kommt, werden wieder alle deaktivierten aus der Liste aktiviert.
  • MewX schrieb:

    Die einfache Methode: if (collision_rec..(...) == other).
    Das funktioniert leider nicht, jetzt führt er den Kollisionsevent garnicht mehr aus.

    MewX schrieb:

    Falls das nicht reicht, müsste man dies in eine Schleife packen. Ist die wiedergegebene Instanz nicht "other", wird diese deaktiviert und in einer Liste gespeichert. Nachdem die andere Instanz dann gefunden wurde oder keine Kollision mehr zustande kommt, werden wieder alle deaktivierten aus der Liste aktiviert.
    Und das versteh ich nicht, hab noch nie mit Schleifen oder Listen gearbeitet... :(

    Kann ich nicht statt "other.object_instanz" den Namen der Plattform angeben und ">0" abfragen?
  • Letzteres wird nicht funktionieren, sofern meine Vermutung stimmt. Meine Vermutung ist, dass sich die Spielfigur im Step-Event bereits in den Boden "reingräbt" (das ist nicht unbedingt schlimm, das ist nur eine nüchterne Feststellung). Wenn nun aber zuerst das Kollisionsevent der oberen Plattform ausgeführt wird, dann gibt die Abfrage unter Umständen die Instanz des Bodens zurück => Deine Unterscheidung funktioniert wieder nicht.
    Ich muss leider gleich weg, aber jemand anders sollte in der Lage sein, die Schleife mit meiner Anleitung oben zu schreiben.
  • MewX schrieb:


    Wenn nun aber zuerst das Kollisionsevent der oberen Plattform ausgeführt wird, dann gibt die Abfrage unter Umständen die Instanz des Bodens zurück => Deine Unterscheidung funktioniert wieder nicht.
    Untere und obere Plattform liegen in EINEM Sprite und somit in EINEM Objekt und haben also nur EINE Instanz-ID. Eine Unterscheidung ist also nicht möglich.

    Ich verstehe einfach nicht warum der Player immernoch eine Collision mit der oberen Plattform berücksichtigt, obwohl ich dies mit einer collision_rectangle Abfrage unter den Füßen des Players eigentlich ausgeschlossen habe?!

    Das steht im collision event des Players mit der Plattform:

    {
    if (collision_rectangle(x-5,y+18,x+5,y+22,obj_rund_plattform,true,true)>0)
    {
    y+=-speed;
    script_execute(move_to_contact_with,270,-1,obj_rund_plattform)
    }
    }


    Warum führt er y+=-speed immernoch aus wenn er die obere Plattform berührt, obwohl das Rechteck (collision_rectangle) die obere Plattform garnicht berührt?! ?(




    Hier ist nochmal die Datei, vielleicht kann sich das ja nochmal jemand ansehen?

    Jump N Run Template - platform problem.gm81.zip

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von Pascal2851981 ()

  • Hi Pascal

    Das liegt einfach daran, weil der Game Maker immer noch die Mask vom Sprite als erstes abfragt und dann die collision_rectangle - Funktion.
    Also wenn du jetzt deine Mask auf left = 14, right = 30, top = 29, botton = 42, bei den Laufsprites einstellst , hast du dein Problem gelöst.

    Pascal wenn du keine registrierte Version vom Gamer Maker besitzt, konnte die Befehlsfolge von MewX nichts bewirken, weil das nur bei der registrierte Version geht.
    if (collision_rectangle(bbox_left, bbox_bottom-8, bbox_right, bbox_bottom, other.object_index, true, true)>0) {// Kollisionscode
    }
    Und wenn du doch eine registrierte Version besitzen sollst, dann mach es erkenntlich. Weil in dein Profil Game Maker light steht, und das deutet darauf hin das du keine registrierte Version hast.

    Gruss Drachen :)
  • Hallo Drachen, danke für Deine Antwort!

    Drachen schrieb:

    Das liegt einfach daran, weil der Game Maker immer noch die Mask vom Sprite als erstes abfragt und dann die collision_rectangle - Funktion.
    Aber das Problem tritt auch auf wenn ich das folgende ins Step-Event schreibe. Und da spielt doch die Mask des Player Sprites überhaupt keine Rolle, oder?

    {
    if (collision_rectangle(x-5,y+18,x+5,y+22,obj_rund_plattform,true,true)>0)
    {
    y+=-speed;
    script_execute(move_to_contact_with,270,-1,obj_rund_plattform)
    }
    }



    Drachen schrieb:

    Also wenn du jetzt deine Mask auf left = 14, right = 30, top = 29, botton = 42, bei den Laufsprites einstellst , hast du dein Problem gelöst.
    Ja das Problem ist dann gelöst. Nur hab ich dann das Problem dass ich z.B. nicht mehr von Schüssen des Gegner am Kopf getroffen werden kann und keine Gegenstände mehr mit dem Kopf einsammeln kann, da dort keine Collision Mask mehr ist. Und die Lösung von MewX mit dem unsichtbaren Spielerobjekt haut mir alles durcheinander...

    Drachen schrieb:

    Pascal wenn du keine registrierte Version vom Gamer Maker besitzt, konnte die Befehlsfolge von MewX nichts bewirken, weil das nur bei der registrierte Version geht.
    Zitat
    if (collision_rectangle(bbox_left, bbox_bottom-8, bbox_right, bbox_bottom, other.object_index, true, true)>0) {// Kollisionscode
    }
    Und wenn du doch eine registrierte Version besitzen sollst, dann mach es erkenntlich. Weil in dein Profil Game Maker light steht, und das deutet darauf hin das du keine registrierte Version hast.
    Ja ich besitze nur die Light Version. Aber ich habe die Collision_rectangle Abfrage ja an x und y Koordinaten abgefragt (was im Endeffekt das gleiche ist wie die bbox abzufragen, oder?).
    Funktionieren tut es trotzdem nicht!
  • So, ich habe mir dein Spiel jetzt mal etwas ausführlicher angeschaut. Deine Engine ist eine Katastrophe. Ohne da ordentlich aufzuräumen, wirst du dieses Problem nie lösen, ohne nicht an anderer Stelle sofort ein neues zu erzeugen. Ich rate dir daher dringend, dich nochmal im stillen Kämmerlein einzuschließen und das von Grundauf neu hochzuziehen. Zwischenzeitlich solltest du natürlich immer gucken, ob du dich auf dem richtigem Weg befindest und nachfragen.

    Ich handle das mal stichpunktartig ab:
    • Deine Engine braucht eine Logik, die den Rahmen von D&D sprengt. Steig auf GML um.
    • Benutze der Übersicht wegen nur noch "Execute a script" und weder D&D noch "Execute a piece of code". Nenne diese Scripts dann z.B. "obj_player_end_step" oder so. Ohne einen schnellen Zugriff verliert man schnell die Übersicht.
    • Du benutzt oft speed, wenn du eigentlich hspeed oder vspeed meinst. Mach dir bitte klar, wo dort die Unterschiede liegen.
    • Du hast eine Funktion, die das "am Boden haften bleiben" regelt. Die rufst du allerdings mal hier, mal da auf (Kollisionsevents, End-Step-Event...). Mach dir Gedanken, wie man diese Bodenhaftung zentral an einer Stelle lösen kann.
    • Du hast willkürlich zwischen "Air" und "Land" getrennt, handelst aber viele andere Sachen intern mit Zustandsvariablen ab. Vereinige die beiden Spielerobjekte am besten zu einem. Das erspart Ärger durch Parents und doppelte Events.
    • Mach dir bewusst, was die Trennungen zwischen Begin-, Normal- und End-Step-Event im Detail bedeuten (siehe "Order of Events" in der Hilfe).
    • Schreibe dir Code, der optional die Maske der Spielifgur am Ende des Draw-Events zeichnet (als Rechteck). Sowas hilft ungemein.
    • Trenne Masken von Sprites. Der Game Maker bietet dir zwar dieses tolle Maskenfeature an, aber bei vielen Sprites passieren schnell Fehler und Korrekturen dauern lange. Mach einfach einen Sprite, der nur einen schwarzen Kasten beinhaltet und verwende ihn als Maske. Dann kannst du auch einfach den zeichnen lassen anstelle des Rechtecks, das ich oben vorgeschlagen habe.
    • Es spricht zwar von der Spiellogik her nicht soviel dagegen, den ganzen Level in einen Sprite zu packen, allerdings wird dein Spiel dadurch sehr groß werden. Überleg dir lieber, ob sich das nicht sinnvoll trennen lässt.


    Die zentralen Fragen bei so einer Engine sind erstmal "Wie bleibe ich auf dem Boden?", "Wann fange ich an zu fallen?" und "Wie verhalte ich mich bei Kollisionen?". Die Antwort von einer Frage beeinflusst schon die der anderen. Du kannst z.B. sagen, dass man immer fällt - und dafür halt in jedem Step auch wieder aus der Plattform rausgedrückt wird. Spiele verschiedene Szenarien durch, bis du glaubst, alles so einfach, zentral und funktional wie nur möglich zu haben.

    Was ich von dir hier fordere ist nicht wenig, aber Jump'n'Runs gehören zu den schwersten Einsteigerprojekten überhaupt. Mach dir keinen Kopf, dass es auf Anhieb nicht geklappt hat. Es gibt hier genug Leute, die dir an vielen Stellen wieder weiterhelfen können. Jetzt ist es aber meiner Meinung nach Zeit, dass du nochmal ein bisschen zurückruderst. Denn selbst wenn du dieses Problem jetzt IRGENDWIE lösen solltest, wird das nächste Problem noch schlimmer.
  • Hi MewX,

    erstmal vielen Dank dass Du Dir die Mühe gemacht hast mein Spiel durchzuschauen und auch noch so ausführlich zu kommentieren!

    MewX schrieb:

    Deine Engine braucht eine Logik, die den Rahmen von D&D sprengt. Steig auf GML um.
    Ok, werde ich tun! Gibt es irgendwo eine Liste wo alle GML Funktionen und Variablen drin sind? Das würd mir glaub ich helfen.

    MewX schrieb:

    Mach dir bewusst, was die Trennungen zwischen Begin-, Normal- und End-Step-Event im Detail bedeuten (siehe "Order of Events" in der Hilfe).
    Ja die Unterschiede hab ich tatsächlich noch nicht verstanden, werd mich dann mal schlau machen ;)

    MewX schrieb:

    Schreibe dir Code, der optional die Maske der Spielifgur am Ende des Draw-Events zeichnet (als Rechteck). Sowas hilft ungemein.
    Was genau bringt das?

    MewX schrieb:

    Trenne Masken von Sprites. Der Game Maker bietet dir zwar dieses tolle Maskenfeature an, aber bei vielen Sprites passieren schnell Fehler und Korrekturen dauern lange. Mach einfach einen Sprite, der nur einen schwarzen Kasten beinhaltet und verwende ihn als Maske. Dann kannst du auch einfach den zeichnen lassen anstelle des Rechtecks, das ich oben vorgeschlagen habe.
    Ok werde ich tun!

    MewX schrieb:

    Es spricht zwar von der Spiellogik her nicht soviel dagegen, den ganzen Level in einen Sprite zu packen, allerdings wird dein Spiel dadurch sehr groß werden. Überleg dir lieber, ob sich das nicht sinnvoll trennen lässt.
    Ich sehe derzeit keine Alternative dazu. Das hängt mit der Art und Weise zusammen wie ich später die Levels erstelle. Das "obj_rund_plattform" dient nur dazu einen Boden zu erzeugen, es ist später unsichtbar. Darunter kommt dann noch die Spielgrafik (ebenfalls in einem Sprite...)

    MewX schrieb:

    Du benutzt oft speed, wenn du eigentlich hspeed oder vspeed meinst. Mach dir bitte klar, wo dort die Unterschiede liegen.
    Du hast eine Funktion, die das "am Boden haften bleiben" regelt. Die rufst du allerdings mal hier, mal da auf (Kollisionsevents, End-Step-Event...). Mach dir Gedanken, wie man diese Bodenhaftung zentral an einer Stelle lösen kann.
    Du hast willkürlich zwischen "Air" und "Land" getrennt, handelst aber viele andere Sachen intern mit Zustandsvariablen ab. Vereinige die beiden Spielerobjekte am besten zu einem. Das erspart Ärger durch Parents und doppelte Events.
    Das habe ich alles aus dem Tutorial "Zool" aus dem Buch "Game Maker´s Companion". Dort gab es sogar 6 oder 7 verschiedene Spielerobjekte. Daher wundert es mich jetzt ein wenig dass das falsch ist. Aber ich glaub dir mal und werd es ändern ;)

    MewX schrieb:

    Benutze der Übersicht wegen nur noch "Execute a script" und weder D&D noch "Execute a piece of code". Nenne diese Scripts dann z.B. "obj_player_end_step" oder so. Ohne einen schnellen Zugriff verliert man schnell die Übersicht.
    Ich denke für mich persönlich ist es mit "Execute a code" übersichtlicher. Das ist aber nur Geschmackssache, oder wo genau liegen die Unterschiede?


    Ok, dann mach ich mich mal ans Werk *Ärmelhochkrempel*

    Hoffe das Problem wird dann dadurch gelöst.

    nochmals vielen Dank für Deine Hilfe!

    Gruß,
    Pascal

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Pascal2851981 ()

  • Pascal2851981 schrieb:

    Ok, werde ich tun! Gibt es irgendwo eine Liste wo alle GML Funktionen und Variablen drin sind? Das würd mir glaub ich helfen.
    Du kannst über F1 die Hilfe aufrufen und rech bequem darin suchen.

    Pascal2851981 schrieb:

    Was genau bringt [es, die Maske zu zeichnen]?
    Die Maske zu zeichnen kann beim Debugging sehr hilfreich sein, da du das Verhalten deiner Engine damit "sichtbarer" machen kannst.

    Pascal2851981 schrieb:

    Ich sehe derzeit keine Alternative dazu. Das hängt mit der Art und Weise zusammen wie ich später die Levels erstelle. Das "obj_rund_plattform" dient nur dazu einen Boden zu erzeugen, es ist später unsichtbar. Darunter kommt dann noch die Spielgrafik (ebenfalls in einem Sprite...)
    Viele Spiele verwenden stattdessen Tilesets. Wenn du grafisch aber etwas zaubern willst, das sich nicht aus sich wiederholenden Bausteinen zusammensetzt, läuft es wohl auf deine Methode hinaus. Bei langen Leveln wäre es aber evtl. trotzdem ratsam, den Riesen-Sprite in Teile zu hacken.

    Pascal2851981 schrieb:

    Das habe ich alles aus dem Tutorial "Zool" aus dem Buch "Game Maker´s Companion". Dort gab es sogar 6 oder 7 verschiedene Spielerobjekte. Daher wundert es mich jetzt ein wenig dass das falsch ist. Aber ich glaub dir mal und werd es ändern ;)
    Sinnvolle Zustandsunterscheidungen und die Hierarchie, die sich aus ihnen ergibt, sind wieder eine Wissenschaft für sich. Als Amateur wirst du aber oft, so wie jetzt, diese ändern müssen und das ist einfacher, wenn du die Zustände durch Variablen und If-Abfragen trennst und nicht durch Objekte und deren eigenen Events. Eine Zustandstrennung durch Objekte hat auch ihre Vorteile, aber von deinem Standpunkt aus bringen sie dir, denke ich, eher mehr Arbeit als Nutzen.
    Ansonsten gilt für so eine doch sehr zustandsorientierte Programmierung aus Amateursicht (der Profi würde das im Vorfeld genau durchplanen): Halte deine Hierarchien halbwegs flach. Lagere doppelten Code, der sich trotz Hierarchie nicht vermeiden lässt, in Scripts aus. Vermeide unter allen Umständen Code, der bereits ausgeführten Code wieder rückgängig macht. Ordne in letzterem Fall lieber die Hierarchie neu.
    Es braucht viel Übung und Erfahrung, bis du für so eine Hierarchie das richtige Gefühl hast.

    Pascal2851981 schrieb:

    Ich denke für mich persönlich ist es mit "Execute a code" übersichtlicher. Das ist aber nur Geschmackssache, oder wo genau liegen die Unterschiede?
    Man kann u.a. durch Parents sehr einfach Code verstecken. Das führt aber dazu, dass man schnell die Übersicht verliert. Auch wenn bei mir der Spieler aus mehreren Objekten besteht, so sehe ich ihn doch als eine Entität und würde auch gerne allen Code schnell auf einem Blick haben anstatt ihn mir zusammensuchen zu müssen. Da ist auch viel Geschmackssache bei, aber spätestens wenn du feststellst, dass man nur ein "Execute a piece of Code"-Fenster gleichzeitig offen haben kann, wirst du die Scripts diesen vorziehen.
  • Benutzer online 3

    3 Besucher