[2D]Kollision gegen Wand



  • Ich habe nach viel hin- und her eine funktionierende (pixelgenaue) Kollisionsabfrage hinbekommen. Nur stellt sich mir jetzt ein Problem: Wie halte ich ein Sprite (z.b. eine viereckige Wand 32x32) davon ab, andere Sprites durchzulassen? Ich kann zwar prüfen, ob ein Objekt ein solches Objekt berührt:

    if Collide(Objekt, Wand)
    

    Aber bei der Kollision "steckt" das Objekt bereits in der Wand. Mein erster Ansatz war, einfach bei einer Kollision einen Schritt wieder zurückzugehen:

    if (Collide(Objekt, Wand))
    {
    	Objekt.MoveLeft();
    	return;
    }
    

    Das Problem ist aber, dass dies (natürlich) nur funktioniert, wenn ich von links kollidiere. Kommt das Objekt von rechts auf die Wand zu, wird es "durch die Wand" nach links gezogen. Also müsste ich rein theoretisch die Richtung bestimmen, von wo kollidiert wird.

    Eine Idee, wie ich das bewerkstelligen könnte? Das alles muss schön verpackt in meine Engine rein, was noch eine Herausforderung mehr ist.



  • Du musst schon wissen von wo dein Objekt gekommen ist.
    Dann kannst du es auch zurücksetzen.
    Geschwindigkeitsvektoren z.B. sind gut geeignet dafür.



  • Dbof schrieb:

    Ich habe nach viel hin- und her eine funktionierende (pixelgenaue) Kollisionsabfrage hinbekommen.

    Pixelgenaue Kollisionsabfragen sind meistens nicht nötig. Und vermutlich oft gar nicht das was man möchte, bzw. sie haben einfach einige z.T. schwere Nachteile.

    Du musst schon wissen von wo dein Objekt gekommen ist.
    Dann kannst du es auch zurücksetzen.

    Das ist ein Ansatz.

    Ein andere Ansatz wäre einfach zu gucken auf welcher Seite das bewegbare Objekt im unbewegten drinnensteckt, und es dann in diese Richtung rausschieben. Bzw. wenn man zwei bewegbare Objekte hat, dann einfach beide entlang des ermittelten Vektors (Mittelpuntk1 - Mittelpuntk2) auseinanderschieben. (Sind die beiden Mittelpunkte gleich wählt man einfach zufällig eine Richtung)

    Dann muss man nicht wissen wo das Objekt hergekommen ist.

    Ich bin mir übrigens gar nicht mal sicher, ob die "wissen wo es hergekommen ist" Variante für die meisten 2D Games überhaupt die bessere Wahl ist.

    ----

    Achja, nochwas
    @Dbof
    falls du irgendwas in Richtung Physics machen willst (also mehr als nur einfache Kollisionsabfragen), dann guck dir die Box2D an.



  • Amino schrieb:

    Du musst schon wissen von wo dein Objekt gekommen ist.
    Dann kannst du es auch zurücksetzen.
    Geschwindigkeitsvektoren z.B. sind gut geeignet dafür.

    Gut, aber wie stelle ich das an? Nehmen wir mal an (s. Bild), dass zwei Objekte nach einem Schritt so zusammenhängen. Wie willst du nun prüfen, aus welcher Richtung die Box kam?

    In meiner Engine habe ich im Prinzip eine Klasse, deren Objekte Sprites sind. Ich will das jetzt benutzerfreundlich gestalten und z.b. eine Variable

    bool solid;
    

    einführen, die prinzipiell verhindern soll, dass ein anderes Objekt durch das solide Objekt gehen kann (so wie Wände eben 😉 )

    ------------------------------------------------

    Pixelgenaue Kollisionsabfragen sind meistens nicht nötig. Und vermutlich oft gar nicht das was man möchte, bzw. sie haben einfach einige z.T. schwere Nachteile.

    Das ist bei mir optional, aber hier ein Beispiel, bei dem pixelgenaue Kollision geeigneter ist: http://goo.gl/zeA3U

    @Dbof
    falls du irgendwas in Richtung Physics machen willst (also mehr als nur einfache Kollisionsabfragen), dann guck dir die Box2D an.

    Box2D kenne ich, aber ich glaube nicht, dass ich eine so umfangreiche Physik implementieren werde. Kollision ist bisher das Einzige, was ich brauche, und die hab ich auch so gut gelöst.

    Ein andere Ansatz wäre einfach zu gucken auf welcher Seite das bewegbare Objekt im unbewegten drinnensteckt, und es dann in diese Richtung rausschieben.

    Ich werde mal versuchen, das elegant zu implementieren. Mal sehen, was sich so machen lässt, ohne großen Aufwand für den Benutzer.

    Weitere Ideen und Pseudocode sind gerne gesehen 😋



  • Dbof schrieb:

    Pixelgenaue Kollisionsabfragen sind meistens nicht nötig. Und vermutlich oft gar nicht das was man möchte, bzw. sie haben einfach einige z.T. schwere Nachteile.

    Das ist bei mir optional, aber hier ein Beispiel, bei dem pixelgenaue Kollision geeigneter ist: http://goo.gl/zeA3U

    Nö, das ist ein Beispiel dafür, dass schlecht gewählte rechteckige Kollisionsbereiche schlecht sind. Was für eine Überraschung! 🤡
    Man kann aber die Bereiche besser wählen, dann kommt man auch mit Rechtecken aus.
    Und man kann was anderes als Rechtecke verwenden, z.B. Kreise.

    http://www.blackgolem.com/component/content/article/26-development/138-circle-collision-detection-beauty.html

    Oder, wenn man sich dir Arbeit antun will, beliebige Polygone.

    ----

    Gerade 2D Shooter sind ein Genre, wo ich ganz sicher keine pixelgenaue Kollisionsabfrage haben möchte. Zumindest nicht, wenn die Kollisionsmaske 1:1 der sichtbaren Form der Objekte entspricht. Ruiniert bloss den Spielspass wenn man schon stirbt, obwohl einen das andere Objekt bloss "gestreift" hat. Spiel mal ein paar klassische 2D Shooter, und du wirst sehen, da verwendet keiner pixelgenaue Kollisionsabfragen.



  • Dbof schrieb:

    Amino schrieb:

    Du musst schon wissen von wo dein Objekt gekommen ist.
    Dann kannst du es auch zurücksetzen.
    Geschwindigkeitsvektoren z.B. sind gut geeignet dafür.

    Gut, aber wie stelle ich das an? Nehmen wir mal an (s. Bild), dass zwei Objekte nach einem Schritt so zusammenhängen. Wie willst du nun prüfen, aus welcher Richtung die Box kam?

    Wurde doch schon erwähnt - Geschwindigkeitsvektoren.
    Damit die von dir gezeigte Kollision zustande kommt, muss sich ja ein (oder auch beide) Objekt(e) bewegt haben. Jedes dieser Objekte hat einen eigenen Geschwindigkeitsvektor (was Vektoren sind weisst du hoffentlich).
    Damit weisst du dann auch aus welcher Richtung ein bestimmtes Objekt kam und du weisst ebenfalls, welche Strecke es zurückgelegt hat.



  • Ruiniert bloss den Spielspass wenn man schon stirbt, obwohl einen das andere Objekt bloss "gestreift" hat.

    Eben das passiert mit der pixelgenauen Erkennung nicht. Wenn eine Bounding Box/Circle - Erkennung stattfindet, ist die Wahrscheinlichkeit höher, dass das Objekt in Wirklichkeit nicht getroffen wurde. Nun ja, ist Ansichtssache, und ich möchte mich da nicht unbedingt darum streiten. Jeder so wie er möchte. Außerdem habe ich es ja gesagt, perfekte Erkennung ist bei mir optional, man kann auch für tilebasierte Spiele z.b. mit einer BBox ausreichend auf Kollision prüfen 😉

    inter2k3 schrieb:

    Wurde doch schon erwähnt - Geschwindigkeitsvektoren.
    Damit die von dir gezeigte Kollision zustande kommt, muss sich ja ein (oder auch beide) Objekt(e) bewegt haben. Jedes dieser Objekte hat einen eigenen Geschwindigkeitsvektor (was Vektoren sind weisst du hoffentlich).
    Damit weisst du dann auch aus welcher Richtung ein bestimmtes Objekt kam und du weisst ebenfalls, welche Strecke es zurückgelegt hat.

    Das ist mir dann doch zu umständlich. Ich weiß zwar, was Vektoren sind, aber die Berechnungen damit sind mir noch unbekannt (Skalarprodukt, Addition...). Das riecht zu stark nach Physik-Engine und da kann ich auch gleich Box2D oder eine andere fertige Engine nehmen.

    Ich hab das jetzt folgendermaßen gelöst. Ich speichere beim Bewegen immer die letzte Bewegungsrichtung und kann nun mit einer Methode MoveBack(); bei (nicht perfekter) Kollision einfach dagegensteuern.

    Vielen Dank für eure Anregungen!


Log in to reply