3D -Kollissionen in Z Ebene

  • GM 8

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

  • 3D -Kollissionen in Z Ebene

    Hallo Leute!

    Also... ich habe mir das 3D Tutorial für Kollissionen von Moolt angeschaut.
    In Punkto kollissionen bin ich auch sehr weit gekommen. XD
    Das Problem ist aber die Z-Achse. Ich habe mehrere "Blöcke" die übereinander in einem Bestimmten abstand stehen.
    Mein Wunsch wäre es, nun abzufragen ob sich unter dem Spieler ein "obj_block" befindet. Jedoch gibt es in dieser Hinsicht mir keine bekannte möglickeit wo ich direkt in einem 3D Raum die Kollission mit einem Objekt prüfen könnte. (wie z.B: place_free oder Place_meeting, nur halt für 3D)

    Moolts tutorial baut ja darauf auf, dass jeder Block den Kollissionsscript für den Spieler bei sich trägt. (ist glaub ich performance lastig, darum habe ich ihn zur sicherheit auf den Spieler portiert.) funktioniert recht gut. ^^

    Das Problem ist nur das die GM- "Standart" Kollission nur auf die x und Y ebene zugreift. Die Z-Ebene müsste ich selber abfragen. Jedoch, kann ich nicht mit "other" auf eine Kollission die auf x und Y Ebene besteht zugreifen, da sich mehrere Blöcke in unterschiedlichen Höhen auf den gleichen X und Y koordinaten befinden.

    Versteht ihr mein debakel? Wie könnte man das lösen? Ich scheitere daran kläglich. X(
  • Ich glaub, das größte Problem ist, dass bei place_free und ähnlichen Funktionen nur die oberste Instanz geliefert wird.
    Mir fällt spontan nur ein, das man in einem ds_grid arrays mit allen Blöcken schreiben könnte. (oder gibt es auch 3d arrays?)
  • "oder gibt es auch 3d arrays?"
    You can use 1- and 2-dimensional arrays in GML.

    aus der Game Maker Hilfe
    Mir fällt spontan nur ein, das man in einem ds_grid arrays mit allen Blöcken schreiben könnte.

    Du wiedersprichst dir in diesem Punkt selbst. Zuerst sagst du, dass das Problem ist, das eine Array nur 2-Dimensional ist (was richtig ist) und dann sagst du aber, mit ds_grid könnte man dies machen, was auch nur ein 2-Dimensionales Raster ist?


    Edit: Wer lesen kann ist klar im Vorteil - in einer ds_grid arrays alles klar habs falsch verstanden ^^

    Zum Problem:
    Also ich weiß nicht ob es Funktionieren würde, aber mein Lösungsvorschlag wäre, ein Objekt "oCheckZ" zu errichten. Dieses nimmt zu allererst alle x/y Werte in einer ds_grid auf. Dies kann zumbeispiel so passieren, das in jedem Create Event eines Blocks (oder deren Parent) einmal oCheckZ die X und Y variable übergeben wird, und dann dessen event_user(0) Event aufgerufen wird.

    Beispielcode (create/block):

    GML-Quellcode

    1. // Dein Code . . . .
    2. // Gebe an oCheckZ die aktuellen Koordinaten
    3. oCheckZ._x = x/Blockweite;
    4. oCheckZ._y = y/Blockhöhe;
    5. oCheckZ._id = id;
    6. // Rufe den User Event 0 auf
    7. with(oCheckZ) event_user(0);


    Nun kannst du im User Event 0 eine ds_grid anfertigen, die du vorher im Create event des oCheckZ Objektes deklariert, und alle Felder mit 0 initialisiert hast (bin mir grade nicht sicher ob das nicht sogar automatisch geschiet).
    Im User Event 0 überprüfst du nun, ist an der stelle X/Y schon eine Instanz? Wenn nein, so schreibe an dieser stelle eine 1. Sollte an der stelle X/Y in der ds_grid jedoch schon eine 1 sein, so fange eine ds_grid an, welche als value eine ds_list hat. Diese ds_list kriegt dann die einzelnen Instanz-ID'n.
    Bei einer Kollision (normales Game Maker Kollisions Event) guckst du nun auf der ds_map, ob dort eine 1 ist, so brauchst du nichts weiter machen und es dürfte vernünftig sofort laufen, oder ob dort etwas höres als 1 ist (da IDen ja immer >=100000 sind soweit ich weiß), sollte dies so sein, brauchst du eine Methode, die die ds_queue durchgeht, und deren Einzelnen Z Werte überprüft.

    Beispielcode (create/oCheckZ):

    GML-Quellcode

    1. dsgRaster = ds_grid_create(room_width/Blocklänge,room_height/Blockhöhe);
    2. ds_grid_set_region(dsgRaster ,0,0,room_width/Blocklänge,room_height/Blockhöhe,0);


    Beispielcode (User Event 0/oCheckZ):

    GML-Quellcode

    1. switch(ds_grid_get(dsgRaster,_x,_y)) {
    2. case 0: ds_grid_set(dsgRaster,_x,_y,1);
    3. break;
    4. case 1: var __id;
    5. __id = ds_queue_create();
    6. ds_grid_set(dsgRaster,_x,_y,_id);
    7. ds_queue_enqueue(__id,_id)
    8. break;
    9. default : ds_queue_enqueue(ds_grid_get(dsgRaster,_x,_y),_id);
    10. }


    Bei einer Kollision kannst du nun die ds_queue in eine neue lokale ds_queue kopieren, und so für jede einzelne Instanz, dessen ID'n du hast, den Z-Wert prüfen.
    Dieser weg scheint mir etwas umständlich, jedoch wüsste ich keine bessere Lösung, ausser die von Yoyo machen den Game Maker mal >3-Dimensional Array fähig ^^

    Der Code ist übrigens nicht getestet, sondern einfach grade schnell zusammengeschustert, ob überhaupt was funtkioniert, weiß ich auch nicht. Bin mir auch nicht sicher ob man eine ds_grid in einer switch-Konstruktion verwenden kann, da dort auch Strings die ja theoretisch gesehen für Delphi nicht Ordinal sind (soweit ich weiß), gespeichert werden können.

    Möglicherweiße hilft das trotzdem, hoffe ist nicht ganz umsonst.

    Grüße,
    Mokuyobi
    木曜日 (Mokuyōbi)
  • Du könntest alle Objekte die in der nähe sind mit "with" ansprechen und fragen ob sie mit dem zu kollidierendem Objekt zusammentreffen (mit der Maske kollidieren) und dann entsprechend des Modells zusätzlich eine höhenabfrage machen.
    So far, Schattenphoenix~
    _____________________________________________________________________________
    "Who needs a stairway to heaven...
    If there is an elevator to hell... ?
    "
    - Vergessen
    "Auch ein perfektes Chaos ist etwas vollkommenes."
    - Jean Genet
  • Ich würde Shattenphönix zustimmen. Alles andere ist für quadratische Blöcke irgendwie viel zu kompliziert...
    Oder du schreibst das z-Kollsions-Skript doch in die Blocke rein und zwar in das Kolisionsevent mit dem Spieler.
    Das automatische Kolisionssystem ist schneller als wenn du im step event mit place_meeting, etc. abfragst.

    Willst du auf diese Drachen und -eier klicken?
    Sie werden sich freuen ;)
  • @Schattenphoenix:
    Darüber habe ich mir auc hschon gedacht, aber das wäre doch viel zu rechenaufwendig wenn ich ca 200 Blöcke mit "with" abfragen würde. oder? (und das jedes Step...)

    @DragonGamer:

    So eine Kollission habe ich ursprünglich auch gehabt, jedoch dachte ic hdas die "standart- Kollission" des GM in Punkto geschwindichkeit recht langsam ist. (weiss nicht wie es sich auf die Performance auswirkt wenn 200 Blöcke eine Kollission mit einem Spieler abfragen.)
  • Hmh, irgendwo, irgendwwann stößt man immer an die Grenzen vom GM.
    Ich könnte jetzt die Multithreading sll empfehlen aber ich glaube einfach dass es auch ohne geht. Probiers einfach.
    Setz auf alle Fälle preziese collission der Masken auf false und wenn es geht auch vom Player. Dann sollte es wirklich schnell genug sein.
    Ich hatte mal ein Spiel bei dem der Player mit 1300 Quadraten kollidieren konnte pro Raum mit prezisem player(!) und es lief recht gut. Ok, im nachinein war es extrem ineffektiv geproggt, aber trotzdem.

    Willst du auf diese Drachen und -eier klicken?
    Sie werden sich freuen ;)