[C/C++] Kollisionsabfrage für x-Objekte

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von Flyde, 9. Juli 2010 .

  1. 9. Juli 2010
    Kollisionsabfrage für x-Objekte

    Hi, ich hab grad ein paar probleme ein großes problem auf ein kleines zu splitten...

    Wenn ich eine kollision abfragen würde (in dem fall mal wieder mein pong klon) dann frag ich z.b. ab: Wenn ball.y auf spieler1.y und ball.x zwischen spieler1.x + spieler1.breite ist -> kollision

    das gleiche für spieler 2.. das gleiche für die wände, jetzt stell ich mir vor ich habe eine art "map" für ein spiel, nehmen wir breakout mit seinen vielen steinen die den ball kollidieren lassen... wie frage ich allgemein für x und y werte ab ob es gerade mit einem objekt kolidiert?

    Im prinzip stelle ich mir gerade etwas vor wie ein 2 dimensionales feld Array[100][100] und jeder quadrant sind z.b. 10px was quasi 1000*1000 pixel wären.. dann das array durchgängig für jeden x und y mit FREE innitalisieren und (mit nem leveleditor der noch gemacht werden muss) dann halt bei Array[40][50] -> OBJEKT[x]

    der ball fliegt dabei durch die einzelnen quadranten.. bei bestimmten x werten quasi Array[aktuell++][aktuell] und bei y Array[aktuell][aktuell++]

    ist meine herangehensweise richtig?
     
  2. 9. Juli 2010
    AW: Kollisionsabfrage für x-Objekte

    Hmm, im Prinzip ist deine Methode auch mäglich, aber ich würde eher eine Objektliste machen mit allen vorhandenen (angezeigten) Elementen des Spiels und pro Objekt würde ich halt die Position, die Größe und das aussehen Speichern und um die Kollision zu prüfen würde ich dann einfach alle Objekte in der Liste mit einem bestimmten ausgewählten Objekt vergleichen (Position unter beachtung der Objektgrößen) und dabei Prüfen ob es eine kollision gibt.

    Mfg Rushh0ur
     
  3. 9. Juli 2010
    AW: Kollisionsabfrage für x-Objekte

    hm reden wir bei objektlisten von etwas wie
    Code:
    CBlock *block[5];
    block[0] = new CBlock(pos_vector, size_vector, "bild.jpg");
    block[1] = new CBlock(pos_vector2, size_vector2, "test.jpg");
    ...
    etc. 
    ?

    Natürlich das ganze ein wenig dynamischer

    dann durch die objektliste durchiterieren und die positionen vergleichen?
    Die sache dabei ist nur, wär das nicht ein wenig "prozesslastig" wenn man bei 1000 objekten alle auf die ballkollision testen muss? bei meiner idee wär das ja quasi immer abhängig von nem trigger im jeweiligen feld (wobei mir das mit der objektliste tatsächlich besser gefällt! nur noch die eine sache da beseitigen )

    EDIT:

    Hab mir mal ne Basisklasse geschrieben, denke mal mit ner CKollision könnte man da bestimmt was drehen davon leite ich dann in meinem Pong fall noch CBall und CPlayer ab

    Code:
    #pragma once
    
    class CObjects
    {
     private:
     sf::Vector2f pos;
     sf::Vector2f size;
     sf::Image img;
     public:
     CObjects(void);
     CObjects(sf::Vector2f pos_new, sf::Vector2f size_new);
     CObjects(sf::Vector2f pos_new, sf::Vector2f size_new, sf::Image img_new);
     ~CObjects(void);
    
     // Setter
     void set_pos(sf::Vector2f pos_new);
     void set_size(sf::Vector2f size_new);
     void set_img(sf::Image img_new);
    };
     
  4. 10. Juli 2010
    AW: Kollisionsabfrage für x-Objekte

    Nun ja Kollosionsabfragen sind tatsächlich Rechenaufwändige Prozesse um die man nicht drum herum kommt. In der Praxis werden diese durch Zussamenfassen von Objekten durchgeführt sowie Radiusvergleiche (Abstand), mit dem letzteren ist gemeint das zuerst nur der Abstand zwischen zwei Objekten überprüft wird um im vorraus sagen zu können ob eine Kollision statt finden kann, diese ist im Vergleich zur korrekten Kollisionprüfung schneller.
    Wird beim Radiusvergleiche festgestellt das eine Kollision möglich ist wird die korrekte Prüfung durchgeführt, dadurch erreicht man insgesammt weniger Rechenaufwand.
    Desweiteren würde ich noch ein Angabe beim Objekt machen mit der ich im Vorraus sagen kann, ob das Objekt überhaupt mit einem anderen Objekt kollidieren kann (Objekte auserhalb des "Spielraums").

    Ach ja am Rande noch; durch das Zussamenfassen von Objekten in einer Liste erreichst du beim Rendern mehr dynamik.

    Mfg Rushh0ur
     
  5. 10. Juli 2010
    AW: Kollisionsabfrage für x-Objekte

    Man könnte auch beides kombinieren. Ein "uniform grid" (besser: Quadtree ) für die broad phase (kann A überhaupt mit B kollidieren?). In den jeweiligen Zellen speicherst du in einer Liste alle Objekte, die sich in ihr befinden (bzw. zum Teil in ihr liegen) und wenn der Ball diese Zelle(n) betritt musst du nur noch die paar Objekte überprüfen (narrow phase).

    Wichtig ist evtl. noch, dass du die Physik vom Spiel entkoppelst, um eine stabilere Simulation zu bekommen (viele Verfahren hassen variable Zeitschritte!).
    Beispiel: Deine Simulation soll in 10ms Schritten laufen. Wenn seit dem letzten Frame 20ms vergangen sind, musst du sie 2x aufrufen usw. usf., sonst kann es passieren, dass der Ball mal durch ein Block "tunnelt", wenn er sich zu schnell bewegt.

    mfg r90

    P.S.: Wieso nicht eine fertige lib nehmen: Box2D?
     
  6. 10. Juli 2010
    AW: Kollisionsabfrage für x-Objekte

    ich benutze eine fertige lib, sfml war für mich die bis jetzt am einfachsten aufgebaute.. mir ging es erstmal darum mir im klaren darüber zu werden was für anforderungen ein spiel alles hat, von den klassen her ist tatsächlich sfml bis jetzt am bequemsten gewesen (siehe namespace sf SFML)

    Das mit der physik und den tunneln ist mir schon aufgefallen, ich glaube ich hab das weitgehend gefixed.. ich brauch nurnoch ne gescheite formel für die reflektion deswegen beschäftige ich mich grad freiwillig mit physik... *g* aber muss ich durch

    danke euch beiden, denke falls nicht noch ein guter vorschlag kommt nehme ich grad den sogenannten quadtree mit objekten die ich abspeicher

    edit: hab mir den quadtree ma angeschaut, ist das tatsächlich sinvoll? also sieht für mich wie ein binärbaum nur halt mit 4 childelementen aus, wie soll ich mir daraus eine map vorstellen mit nem hauptknoten ganz oben?
     
  7. 10. Juli 2010
    Zuletzt von einem Moderator bearbeitet: 15. April 2017
    AW: Kollisionsabfrage für x-Objekte

    das ist sinnvoll um nicht 1000 objekte auf eine kollision zu überprüfen. d.h. du teilst deine "map" in 4 gleichmäßige quadranten und diese quandranten kannst du rekursiv weiter unterteilen, bis du denkst du hast eine angemessene tiefe erreicht.

    Beispiel:
    quadtree.jpg
    {img-src: //img691.imageshack.us/img691/5825/quadtree.jpg}


    Befindet sich dein Userobjekt in dem grauen Quadrant, so macht es Sinn, nur die Objekte innerhalb des Quadranten auf eine Kollision zu prüfen. Bei den restlichen Quadranten liegt keine Kollision vor.

    Gruß
    wollknoll
     
  8. 10. Juli 2010
    Zuletzt von einem Moderator bearbeitet: 14. April 2017
    AW: Kollisionsabfrage für x-Objekte

    Reflexion:
    v - dein Vektor, der reflektiert werden soll
    n - Normaleneinheitsvektor (ein Vektor der Länge 1, der senkrecht auf der Fläche/etc seht, an der reflektiert werden soll)
    v' - reflektierter Vektor

    v' = v - 2 * (v . n) * n

    * = Skalarmultiplikation, . = Skalarprodukt

    Beispiel: Ein Vektor, der 4 Einheiten nach rechts zeigt, soll an einer Linie, mit einem Winkel von 45° zur x-Achse, reflektiert werden.
    v = [4, 0]
    n = [-sin(45°), cos(45°)] -> [-0,707..., 0,707...]

    Bild
    v' = [4, 0] - 2 * ([-0,707..., 0,707...] . [4, 0]) * n = [4, 0] - [4, -4] = [0, 4]
     
  9. 10. Juli 2010
    Zuletzt von einem Moderator bearbeitet: 15. April 2017
    AW: Kollisionsabfrage für x-Objekte

    das ist prinzipiell richtig und hab ich auch so realisiert aber ist eher unwahrscheinlich denn es kommen noch faktoren dazu wie die geschwindigkeit des spielers während der ball auf dem spieler kommt und ein drall.. wenn ich es bei dieser lösung von dir belassen würde (was ich anfangs hatte) würde ein ball immer gleich und berechenbar fliegen

    ja dieser ansatz ist echt gut, hab ich garnicht darüber nachgedacht! gott sei dank hatte ich algorithmen und datenstrukturen sonst hät ich grad nur bahnhof verstanden
     
  10. 11. Juli 2010
    AW: Kollisionsabfrage für x-Objekte

    Bei Breakout wird einfach noch der Abstand des Balles zur Mitte des paddles genommen und anhand dessen der Vektor etwas gedreht. Also je weiter rechts der Ball auftrifft, desto mehr wird der Vektor nach rechts gedreht. Das gleiche natürlich, je weiter er links auftrifft. Dazu nimmst du dann noch die Geschwindigkeit entlang der x-Achse des paddles hinzu. Anders bekommst du einen Drall nicht ohne viel Aufwand simuliert. Sonst brauchst du noch den ganzen Mist wie Rotationsgeschwindigkeit, Schwerpunkt, Reibung etc. und ganz miese Mathematik um das korrekt machen zu können.

    Das mit der Geschwindigkeit des Spielers ist einfach... du addierst einfach die Geschwindigkeit, die der Spieler in die neue Flugrichtung des Balls hat. Wenn der Spieler sich auf dem Ball zubewegt wird der Ball schneller, wenn er sich von ihm Weg bewegt langsamer.

    v' += sign(v_spieler . dir_ball) * sqrt(|v_spieler . dir_ball|) * dir_ball
    sign() ist -1, falls der Ausdruck negativ ist und +1, falls der Ausdruck positiv ist.
    dir_ball ist der normierte Richtungsvektor vom Ball (der reflektierte).
     
  11. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.