SDL 2 / Rotieren von Kollisionsbereichen fehlerhaft



  • Hallo,

    Ich arbeite momentan an einer Kollisionserkennung. Ich lege für die Models Kollisionsbereiche fest. Die fixen Kollisionsbereiche liegen im Array ppCol_rect und werden zum Verändern an ppCol_rect_copy übergeben. Momentan arbeite ich nur am "nach rechts rotieren". Beim rotieren wird zwar nach rechts rotiert aber die Kollisionsbereiche werden dabei immer wieder zusammengeschrumpft.

    Gut erkennbar im Video:

    http://youtu.be/_acQHu9-HDE

    Hier der Code:

    void CModel_2D::move_col_areas()
    {
      int mid_x = 0;
      int mid_y = 0;
      double radiant = 0;
    
      d_point punkt_a;
      d_point punkt_b;
      d_point punkt_c;
      d_point punkt_d;
    
      // Kollisionsbereiche einfach auf der x-y-Achse verschieben
    
      for(int i = 0 ; i < col_area_number ; i++)
      {
        // auslesen und an buffer übergeben und verändern!
    
        ppCol_rect_copy[i]->p_a->set_stuetz((ppCol_rect[i]->p_a->get_stuetz_x() + pos_x), (ppCol_rect[i]->p_a->get_stuetz_y() + pos_y));
        ppCol_rect_copy[i]->p_a->set_direction(ppCol_rect[i]->p_a->get_dir_x(), ppCol_rect[i]->p_a->get_dir_y());		                                    ppCol_rect_copy[i]->p_b->set_stuetz((ppCol_rect[i]->p_b->get_stuetz_x() + pos_x), (ppCol_rect[i]->p_b->get_stuetz_y() + pos_y));
        ppCol_rect_copy[i]->p_b->set_direction(ppCol_rect[i]->p_b->get_dir_x(), ppCol_rect[i]->p_b->get_dir_y());
        ppCol_rect_copy[i]->p_c->set_stuetz((ppCol_rect[i]->p_c->get_stuetz_x() + pos_x), (ppCol_rect[i]->p_c->get_stuetz_y() + pos_y));
        ppCol_rect_copy[i]->p_c->set_direction(ppCol_rect[i]->p_c->get_dir_x(), ppCol_rect[i]->p_c->get_dir_y());
        ppCol_rect_copy[i]->p_d->set_stuetz((ppCol_rect[i]->p_d->get_stuetz_x() + pos_x), (ppCol_rect[i]->p_d->get_stuetz_y() + pos_y));
        ppCol_rect_copy[i]->p_d->set_direction(ppCol_rect[i]->p_d->get_dir_x(), ppCol_rect[i]->p_d->get_dir_y());
      }
    
      if(current_angle != 0)
      {
        // Mit Rotation
        // aktueller Mittelpunkt des Models
    
        mid_x = (pos_x + (((double) pImage->getWidth()) / 2));
        mid_y = (pos_y + (((double) pImage->getHeight()) / 2));
    
        for(int i = 0 ; i < col_area_number ; i++)
        {
          punkt_a.x = ppCol_rect_copy[i]->p_a->get_stuetz_x();
          punkt_a.y = ppCol_rect_copy[i]->p_a->get_stuetz_y();
          punkt_b.x = ppCol_rect_copy[i]->p_b->get_stuetz_x();
          punkt_b.y = ppCol_rect_copy[i]->p_b->get_stuetz_y();
          punkt_c.x = ppCol_rect_copy[i]->p_c->get_stuetz_x();
          punkt_c.y = ppCol_rect_copy[i]->p_c->get_stuetz_y();
          punkt_d.x = ppCol_rect_copy[i]->p_d->get_stuetz_x();
          punkt_d.y = ppCol_rect_copy[i]->p_d->get_stuetz_y();
    
          radiant = current_angle * (PI / 180);
    
          if(rot_dir == CMODEL_2D_ROTATE_RIGHT)
          {
            punkt_a.x = mid_x + (punkt_a.x - mid_x) * cos(radiant) - (punkt_a.y - mid_y) * sin(radiant);
            punkt_a.y = mid_y + (punkt_a.x - mid_x) * sin(radiant) + (punkt_a.y - mid_y) * cos(radiant);
            punkt_b.x = mid_x + (punkt_b.x - mid_x) * cos(radiant) - (punkt_b.y - mid_y) * sin(radiant);
            punkt_b.y = mid_y + (punkt_b.x - mid_x) * sin(radiant) + (punkt_b.y - mid_y) * cos(radiant);
            punkt_c.x = mid_x + (punkt_c.x - mid_x) * cos(radiant) - (punkt_c.y - mid_y) * sin(radiant);
            punkt_c.y = mid_y + (punkt_c.x - mid_x) * sin(radiant) + (punkt_c.y - mid_y) * cos(radiant);
            punkt_d.x = mid_x + (punkt_d.x - mid_x) * cos(radiant) - (punkt_d.y - mid_y) * sin(radiant);
            punkt_d.y = mid_y + (punkt_d.x - mid_x) * sin(radiant) + (punkt_d.y - mid_y) * cos(radiant);
          }
    
          ppCol_rect_copy[i]->p_a->set_stuetz(punkt_a.x, punkt_a.y);
          ppCol_rect_copy[i]->p_b->set_stuetz(punkt_b.x, punkt_b.y);
          ppCol_rect_copy[i]->p_c->set_stuetz(punkt_c.x, punkt_c.y);
          ppCol_rect_copy[i]->p_d->set_stuetz(punkt_d.x, punkt_d.y);
    
          ppCol_rect_copy[i]->p_a->set_direction((punkt_b.x - punkt_a.x), (punkt_b.y - punkt_a.y));
          ppCol_rect_copy[i]->p_b->set_direction((punkt_c.x - punkt_b.x), (punkt_c.y - punkt_b.y));
          ppCol_rect_copy[i]->p_c->set_direction((punkt_d.x - punkt_c.x), (punkt_d.y - punkt_c.y));
          ppCol_rect_copy[i]->p_d->set_direction((punkt_a.x - punkt_d.x), (punkt_a.y - punkt_d.y));
        }
      }
    }
    

    Momentan verstehe ich nicht, warum es nicht geht. Den selben Rotationsalgorithmus habe ich im Hauptmenü und da funktioniert er augenscheinlich.

    Jede Hilfe wäre hier super.

    Gruß,
    Patrick



  • Moin!
    Sorry: ich verstehe das Problem nicht. Insbesondere verstehe ich nicht, was der gezeigte Code mit dem Problem zu tun hat.



  • Bei ungefähr 8 Sekunden in dem Video beginnt das Problem. Die Kollisionsrechtecke sind das Problem. Sie werden nicht korrekt rotiert. Bei 8 Sekunden im Video kommt von rechts der blaue Asteorid beispielsweise. Dort drehen sich die Kollisionsbereiche falsch aus einem Grund, der mir nicht bekannt ist. Das tun sie generell bei jedem Asteoriden, der sich nach rechts dreht, weil ich die Linksrotation auch noch nicht implementiert habe. Da wären sie bestimmt auch fehlerhaft. Also das Problem: Die Kollisionsbereiche (Rechtecke, im Video zart Rosa) rotieren falsch.

    ppCol_rect und die Kopie davon (ppCol_rect_copy) beinhalten ALLE Kollisionsbereiche eines Models. Beide sind Zeiger (auch Arrays) auf eine eigene "Rechteck" Struktur. Diese Struktur hat einfach nur 4 Vektoren (Objekte), die das Rechteck bilden (a, b, c, d)

    ppCol_rect[0]->p_a ist zum Beispiel der Vektor a des aller ersten Kollisionsbereiches. Dieser Vektor bildet zum Beispiel die Strecke von oben links nach oben rechts eines (Kollisions)rechteckes.

    p_b: von rechts oben nach rechts unten
    p_c: von rechts unten nach links unten
    p_d: von links unten nach links oben

    Die Vektoren haben auch Methoden wie:

    set_stuetz(x, y): womit ein Stützvektor gesetzt wird, falls man eine Gerade beschreiben will.
    set_direction(x, y): setzt einen Richtungsvektor
    get_stuetz_x(): gibt die x-Komponente des Stützvektors aus

    ect. usw.

    Im Code oben werden dann alle 4 Stützvektoren (oder alle 4 Punkte) eines Kollisionsrechteckes gedreht. Anschließend werden neue Richtungsvektoren berechnet.

    Mehr passiert da eigentlich nicht. Und wie gesagt, die Rotation funktioniert aber nicht richtig. Die Kollisionsrechtecke werden zusammengedrückt.



  • Müsste in den Zeilen 18-24 nicht auch irgendwo ppCol_rect_copy[i]->p_c->set_stuetz(...); aufgerufen werden?

    Diese Copy&Paste Programmierung ist ermüdend zu lesen. Evtl. packst Du die Zeiger pX in ein Array, dann kannst Du da mit einer Schleife durchpflügen, gleiches gilt für die Hilfsvariablen d_point punkt_X.

    Was IMHO nicht optimal ist, ist dass man die ganzen Vektoren so umständlich zusammenbasteln muss.
    Mach aus deinen Vektoren ein einfaches struct ivec2 {int x, y; } und vergiss diesen Getter und Setter Kram. Dann spendier noch ein einfaches ivec2& get_stuetz() und ebenso für direction. Schon schrumpft Dein Code auf ein erträgliches Maß zusammen.



  • Furble Wurble schrieb:

    Müsste in den Zeilen 18-24 nicht auch irgendwo ppCol_rect_copy[i]->p_c->set_stuetz(...); aufgerufen werden?

    s/p_c/p_b/



  • Was genau meinst du mit den Zeilen 18 - 24?

    Ich bin immer für jede Code-schrumpfende Möglichkeit zu haben, man kann allein meinen Code schon schrumpfen lassen, indem man Zeilen 37 - 44 weglässt und direkt ab Zeile 50 einfügt. Ich hatte das nur erstmal gelassen der... haha... naja "Übersicht" halber ^^



  • PadMad schrieb:

    Was genau meinst du mit den Zeilen 18 - 24?

    Ich meine, die Zeilen 18-24 in Deinem Code oben. Da fehlt set_stuetz() fuer den Zeiger p_b , richtig?



  • Ah, ja, sorry.
    Das hatte ich hier beim Einfügen ins Forum scheinbar versehentlich gelöscht 😞
    Das ist in meinem Code aber drin. keine Ahnung wie das passiert ist. Der Rest stimmt aber.



  • Problem gelöst.

    da ich punkt_a.x beim rotieren bereits verändert habe, ist es natürlich ein Fehler ihn in punkt_a.y darunter gleich einzusetzen, da er da ja schon verändert ist. Da muss natürlich die ursprüngliche Koordinate hin 😃


Log in to reply