Lenkrakete



  • Hallo,

    ich habe folgendes Problem:
    Bin gerade dabei ein kleines Spiel zu programmieren und komme nicht weiter.
    Ich erinnere mich, mal ein Video gesehn zu haben, in dem gezeigt wurde, wie man die einzelnen Koordinaten zwischen zwei Objekten berechnet, weiß es aber nicht mehr genau.

    Ich habe mal eine Skizze angefertigt, damit ihr wisst was ich meine:
    http://img193.imageshack.us/img193/4082/collision.jpg

    Man könnte natürlich verschiedene Abfragen machen
    if(Flugzeug->x > 200 && Flugzeug->x < 300 ...)
    aber es geht doch bestimmt einfacher oder?

    Wäre nett wenn mir jmd helfen könnte.
    Danke



  • Was möchtest du genau berechnen? Mit "einzelnen Koordinaten zwischen zwei Objekten" meinst du wahrscheinlich die Punkte auf der Verbindungsgeraden, oder?

    Bei einer Lenkrakete würde ich jedoch anders vorgehen. Da auch die Ausrichtung (Drehung der Rakete) eine Rolle spielt, musst du Winkel miteinbeziehen. Den Winkel zwischen zwei Punkten (gegenüber der positiven x-Achse) kannst du mit Arcustangens berechnen, in C++ kannst du die Funktion atan2() nehmen. Auf diese Weise weisst du, in welche Richtung die Rakete fliegt. Um daraus wieder kartesische Koordinaten (x und y) zu gewinnen, brauchst du die trigonometrischen Funktionen Sinus und Cosinus ( sin() bzw. cos() ).

    Das Ganze könnte sinngemäss etwa so aussehen, wobei vx und vy die Geschwindigkeiten der Rakete in x- und y-Richtung repräsentieren ( vRak ist der Betrag der Geschwindigkeit).

    float winkel = atan2(yZiel-yRak, xZiel-xRak);
    
    float vx = vRak * cos(winkel);
    float vy = vRak * sin(winkel);
    


  • Vielen Dank für die schnelle Antwort.

    Ja ich meinte, die Punkte auf der Verbindungsgerade.
    Ich schau mir das mal genauer an und versuch es mal umzusetzen,
    ich meld mich dann wieder.
    Vielen Dank



  • Was ich noch nicht ganz verstehe ist die Sacht mit dem vRak.

    Betrag der Geschindigkeit im Sinne von
    Summe, also xRak + yRak?

    Ich hab gelsen, dass man die Norm eines Vektors auch als Betrag bezeichnet, aber dieses Thema wurde im Unterricht noch nicht behandelt, sprich ich weiß nichts darüber.

    Könntest du vRak nochmal näher definieren?

    An sonsten ist mir alles klar geworden, nochmal vielen Dank.



  • Nein, für die Gesamtgeschwindigkeit müsstest du den Satz von Pythagoras verwenden, also vRat2=xRak2+yRak2



  • Nico12 schrieb:

    Ich hab gelsen, dass man die Norm eines Vektors auch als Betrag bezeichnet, aber dieses Thema wurde im Unterricht noch nicht behandelt, sprich ich weiß nichts darüber.

    Das habe ich gemeint. Wenn du einen Vektor (x,y) hast, ist dessen Betrag die Länge des Vektors, also die Wurzel aus x2+y2 (siehe auch Wikipedia).

    vRak soll dabei eine von dir festgelegte Grösse sein, die aussagt, wie schnell sich die Rakete fortbewegt. Als Einheit musst du dabei irgendetwas Sinnvolles festlegen, wie Pixel pro Frame oder sowas.



  • Ok, vielen Dank,
    ich probiers mal aus.



  • Ich bins, nochmal,
    ich habs jetzt mal ausprobiert, aber ich bekomme es einfach nicht hin.
    Ich hab mal einen Teil der Funktion gepostet, vllt wisst ihr ja weiter,
    ich hab wohl noch nicht alles verstanden, egal welchen Wert ich für vRak nehme, entweder wird die Rakete garnicht abgebildetet bzw ausserhalt des Sichtfelds oder sie bewegt sich nicht und bleibt an ihrer Startposition.

    //player == Flugzeug
    //en == enemy
    if(en->rocket_fire == 1)
    {
    	float winkel = atan2( (player->y - en->rocket_y),         
                                  (player->x - en->rocket_x) );
    
    	en->rocket_xspeed = vRak * cos(winkel);
    	en->rocket_yspeed = vRak * sin(winkel);
    
            if(player->x < en->x)
            {
    	     en->rocket_x -= en->rocket_xspeed;
    	     en->rocket_y -= en->rocket_yspeed;
            }else
            {         
             en->rocket_x += en->rocket_xspeed;
    	     en->rocket_y += en->rocket_yspeed;
            }
    
            //scroll routine (horizontal scrolling game)
    	    en->rocket_x -=STEP;
    
    //Rakete auf dem Buffer abbilden
    pivot_scaled_sprite(buffer, enemy_rocket_b , en->rocket_x, en->rocket_y, 
                        0, 0, ftofix(en->rocket_angle), ftofix(en->rocket_scale));
    
    }
    


  • Das If-Else ist nicht nötig, da Sinus und Cosinus auch negative Werte liefern können und somit alle Richtungen abgedeckt sind. Addiere die Geschwindigkeit immer zur Position, ohne Fallunterscheidung.

    Wenn die Y-Achse deines Koordinatensystems nach unten zeigt, nimm -sin(winkel) statt sin(winkel) . Probier am besten ein wenig aus.



  • Ich weiss zwar nicht ob es noch aktuell ist, hatte bis eben in etwa das gleiche problem (bin noch blutiger anfänger).
    Auf folgende Lösung bin ich gekommen.

    const double PI = 3.14159265;
    const double RadToDeg = 180 / PI;
    const double DegToRad = PI / 180;
    
    dreieck_a = position_ist_x-position_soll_x;
    dreieck_b = position_ist_y-position_soll_y;
    dreieck_c = sqrt (pow (dreieck_a,2) + pow (dreieck_b,2));
    winkel_alpha = asin (dreieck_a / dreieck_c )*RadToDeg;
    winkel_beta = 90 - winkel_alpha;
    dreieck_c = speed * time;
    dreieck_a = dreieck_c * cos(winkel_beta*DegToRad);
    dreieck_b = sqrt (pow(dreieck_c,2) - pow(dreieck_a,2));
    position_ist_x = ceil(position_ist_x - dreieck_a);
    position_ist_y = ceil(position_ist_y - dreieck_b);
    

    Evtl. konnte ich ja helfen.



  • Warum nicht einfach so? (wenn du schon Allegro benutzt...)

    float player_x, player_y; // irgendwo von dir festgelegt
      float rakete_x, rakete_y; // aktuelle position oder raketenwerfer position
      float rakete_speed; // speed der rakete in pixeln
    
      float dist_x, dist_y, dist_z;
      dist_x = player_x - rakete_x;
      dist_y = player_y - rakete_y;
      dist_z = 0;
    
      normalize_vector_f(&dist_x, &dist_y, &dist_z);
      dist_x *= rakete_speed;
      dist_y *= rakete_speed;
    
      rakete_x += dist_x;
      rakete_y += dist_y;
    

    EDIT:

    Pi ist übrigens als M_PI in <cmath> definiert.



  • Fellhuhn schrieb:

    Pi ist übrigens als M_PI in <cmath> definiert.

    Leider ist M_PI weder in C noch in C++ standardisiert und somit nicht portabel.



  • Nexus schrieb:

    Fellhuhn schrieb:

    Pi ist übrigens als M_PI in <cmath> definiert.

    Leider ist M_PI weder in C noch in C++ standardisiert und somit nicht portabel.

    Man kann ja immer noch acos(1)*2 verwenden 😃

    Felix



  • Phoemuex schrieb:

    Man kann ja immer noch acos(1)*2 verwenden 😃

    Null? Dann ist ja sogar sqrt(10.f) noch genauer. 😉



  • Nexus schrieb:

    Phoemuex schrieb:

    Man kann ja immer noch acos(1)*2 verwenden 😃

    Null? Dann ist ja sogar sqrt(10.f) noch genauer. 😉

    Ups 😮 , ich meinte natürlich asin(1)*2 💡


Anmelden zum Antworten