Lenkrakete
-
EOP schrieb:
Was ich an meinem (leider kürzlich verstorbenen) Bruder immer bewundert habe:
Er hat grundsätzlich alle Jobangebote der Rüstungsindustrie abgelehnt.Ansonsten sollte man "Algoryhtmus" erst mal einigermaßen richtig schreiben können, bevor man nach einem fragt.
Ich weiß, daß ich mich mit meinen posts immer unbeliebter mache...
Danke für den hilfreichen Post.
Und damit du heute schlafen kannst : algorithmus.gute Nacht.
lg
-
Du kannst zunächst die relativen Zielkoordinaten ausrechnen
float dx = targetx - raketex; float dy = targety - raketey;diese dann in das Raketen-eigene Koordinatensystem umrechnen (drehen). Die Rakete hat eine "nach vorne"-Achse und eine "zur Seite"-Achse:
float vorne = dx*sin(m_rot) + dy*cos(m_rot); float seite = dx*cos(m_rot) - dy*sin(m_rot);Wenn die Rakete jetzt schon direkt auf das Ziel zufliegt sollte
seitegleich Null sein undvornegleich dem Abstand zwischen Rakete und Ziel sein. Aus dem Quetientenseite/vornelässt sich über den Arcustangens der Korrekturwinkel bestimmen, der dann noch auf +/-4 Grad beschränkt werden muss:float kwinkel = atan(seite/vorne); if (kwinkel<-4*pi/180) kwinkel=-4*pi/180; else if (kwinkel>+4*pi/180) kwinkel=+4*pi/180; m_rot += kwinkelDanach sollte prüfen, ob
m_rotnicht unnötig groß oder klein geworden ist:if (m_rot> 2) m_rot -= 2*pi; else if (m_rot<-2) m_rot += 2*pi;Denn sonst kannst Du noch Ärger mit Rundungsfehlern bekommen.
Das ganze lässt sich auch komplett ohne
sin,cosundatanregeln. Dazu kannst Du stattm_roteinfach einen normalisierten Richtungsvektor speichern und diesen dann verändern.Alle Angaben ohne Gewähr (Ich habe den Code nicht getestet).
HTH,
SP
-
cirbi schrieb:
EOP schrieb:
Was ich an meinem (leider kürzlich verstorbenen) Bruder immer bewundert habe:
Er hat grundsätzlich alle Jobangebote der Rüstungsindustrie abgelehnt.Ansonsten sollte man "Algoryhtmus" erst mal einigermaßen richtig schreiben können, bevor man nach einem fragt.
Ich weiß, daß ich mich mit meinen posts immer unbeliebter mache...
Danke für den hilfreichen Post.
Und damit du heute schlafen kannst : algorithmus.gute Nacht.
lg
Na es geht doch. :p
-
Tach,
leider klappt dein Code auch nicht

Sprich er fliegt in die Richtung, dann dreht er und is weg
Hier nochma alles code :
void CProjectil::Update(float time) { float speed = 2; float tempx = sin(m_rot)*speed; float tempy = cos(m_rot)*speed; float dx = m_targetX - m_xPos; float dy = m_targetY - m_yPos; float vorne = dx*sin(m_rot) + dy*cos(m_rot); float seite = dx*cos(m_rot) - dy*sin(m_rot); float kwinkel = atan(seite/vorne); if (kwinkel<=-4.0f*3.1415f/180) kwinkel=-0.8f*3.1415f/180.0f; else if (kwinkel>=+4.0f*3.1415f/180) kwinkel=+0.8f*3.1415f/180.0f; m_rot += kwinkel ; if (m_rot> 2.0f) m_rot -= 2.0f*3.1415f; else if (m_rot<-2.0f) m_rot += 2.0f*3.1415f; m_xPos += tempy; m_yPos += tempx; } void CProjectil::setTarget(float x, float y) { m_targetX = x; m_targetY = y; }
-
Nimm doch
atan2(), wenn du den Quadranten berücksichtigen willst. Ausserdem nimmt man normalerweise eher den Cosinus für die x-Achse, aber das hängt natürlich davon ab, wo dein Winkel 0 ist. Und muss das Folgende so sein? Falls ja, solltest du die Bezeichner überdenken.m_xPos += tempy; m_yPos += tempx;Ich hab dir doch auf spieleprogrammierer.de bereits gesagt, du solltest dir mal Klassen und Funktionen überlegen. Plötzlich hast du ein fast gleiches Problem, aber brauchst dich wieder stundenlang abzumühen und Code zu kopieren. Alleine schon wie oft du Pi ausschreibst oder zwischen Grad und Bogenmass umrechnest...
-
Tach,
kenne mich mit Vektoren nicht aus, darum schreibe ich mir keine Klasse dafür.
Wieso funktioniert die oben genannte Funktion nicht ?
Also bei 0° zeigt das Objekt nacht rechts.
Bei 90° nach unten.
180° links.
270° oben.Vllt hilft das

lg
-
cirbi schrieb:
kenne mich mit Vektoren nicht aus, darum schreibe ich mir keine Klasse dafür.
Ein 2-dimensionaler Vektor sollte kein Problem sein, da das dann nur x und y besitzt und eigentlich nichts weiteres ist, als das, was du hier darstellst. Allerdings einfacher zu verstehen und man kann dann auch einfacher damit operieren, als immer ein x und y mitzutragen.
Alleine schon das sollte helfen:
struct vec2d { float x; float y; };Wenn du hier noch ein paar Operatoren, wie +,- usw. beibringst, dann ist das schon sehr viel Wert.
-
cirbi schrieb:
Wieso funktioniert die oben genannte Funktion nicht ?
Also bei 0° zeigt das Objekt nacht rechts.
Bei 90° nach unten.
180° links.
270° oben.Das passt aber nicht ganz zu Deinem
sin/cos-Kram. Es sei denn, deine Y-Achse zeigt nach rechts und Deine X-Achse zeigt nach unten.Hier ist mal eine recht kurze Lösung mit komplexen Zahlen:
#include <iostream> #include <complex> #include <cmath> #include <algorithm> using namespace std; typedef complex<float> cfloat; class rakete { cfloat richtung; //< immer auf 1 normiert public: cfloat position; //< Potition der Rakete cfloat ziel; //< Zielposition float speed; float wendigkeit; explicit rakete(float x=0, float y=0, float rot=0, float zielx=0, float ziely=0) : richtung(polar(1.f,rot)), position(x,y), ziel(zielx,ziely), speed(1), wendigkeit(0.07f) {} void set_rot(float rot) {richtung = polar(1.f,rot);} float get_rot() const {return arg(richtung);} float get_x() const {return position.real();} float get_y() const {return position.imag();} void update(); }; void rakete::update() { float k = arg( (ziel-position)*conj(richtung) ); k = max(-wendigkeit,min(k,wendigkeit)); richtung *= polar(1.f,k); richtung /= abs(richtung); position += richtung * speed; } ostream& operator<<(ostream& os, rakete const& r) { os << "(x=" << r.get_x() << ", y=" << r.get_y() << ", rot="; os << r.get_rot() << ')'; return os; } int main() { // Rakete startet bei (0,0), fliegt in Richtung +X // mit Geschwindigkeit 1 soll auf das Ziel (15,5) lenken. rakete r (0,0, 0, 15,5); for (int zeit=0; zeit<20; ++zeit) { cout << r << '\n'; r.update(); } }Die "Wendigkeit" von 0.07 ergibt sich aus 4°*pi/180.
Gruß,
SP
-
Tach,
hab jetz den Winkel rausbekommen.
Aber ich weiß nicht ob er nach link oder rechts lenken soll, immer nur die zahlen von 0 bis pi ausgibt, egal ob target oben oder unten ist.Hier der relevante Code :
void cplayer::update(float vx, float vy) { float speed = 4; float tempx = cos(rot)*speed; float tempy = sin(rot)*speed; float lineB = distance(vx,vy,x,y); float lineA = distance(vx,vy,x+tempx,y+tempy); float deg = innerRad(lineA, lineB, speed); // hier von 0 bis pi if(deg <= DegToRad(2.0f)) { rot+= deg; } else if(deg >= 3.1415f) { rot+= DegToRad(2.0f); } else if(deg <= 3.1415f) { rot-= DegToRad(2.0f); } x += tempx; y += tempy; }#define pi 3.1415926f inline float DegToRad(float deg) { return 2.0f*pi*(deg/360.0f); } inline float distance(float x1, float y1, float x2, float y2) { return sqrt(pow(x1-x2,2)+pow(y1-y2,2)); } inline float innerRad(float lineA, float lineB, float lineC) { return acos( ( pow(lineB,2)+pow(lineC,2)-pow(lineA,2) )/ (2*lineB*lineC ) ); }lg
-
Kennst Du das Skalarprodukt? Das ist extrem praktisch, wenn man wissen will, ob zwei gegebene Richtungen ungefähr gleich sind (Skalaprodukt ist dann größer Null), ob sie senkrecht zueinander sind (Skalarprodukt ist dann Null), oder ob sie in die entgegengesetzte Richtung zeigen (Skalarprodukt ist dann negativ).
Die Richtung, in die Deine Rakete fliegt ist (tempx,tempy). Die Richtung in der das Ziel liegt -- relativ zur Rakete -- ist (vx-x,vy-y). Eine Richtung senkrecht zur Flugrichtung ist die Flugrichtung um 90° gedreht: (-tempy,tempx). Diese liegt von der Rakete aus gesehen auf einer bestimmten Seite. Wenn also Deine X/Y Achse nach rechts und unten zeigt, dann entspricht diese 90° Drehung einer Drehung im Uhrzeigersinn -- es ist also von der Rakete ausgesehen "rechts". Wenn Deine Y-Achse nach oben zeigt ist es "links" und eine Drehung entgegen dem Uhrzeigersinn.
Berechne nun das Skalarprodukt zwischen (-tempy,tempx) und (vx-x,vy-y). In diesem Fall ist es (vy-y)*tempx-(vx-x)*tempy. Ist der Wert größer als Null, musst Du
rotvergrößern -- sonst verkleinern.Gruß,
SP
-
da du die lösung jz schon kennst, nur noch einige punkte:
drakon schrieb:
Alleine schon das sollte helfen:
struct vec2d { float x; float y; };Wenn du hier noch ein paar Operatoren, wie +,- usw. beibringst, dann ist das schon sehr viel Wert.
#define pi 3.1415926f
->
const float pi (3.141592681);die inline`s brauchst du imho nicht
if(deg >= 3.1415f)
hat dir pi dann doch nicht mehr gefallen? ;Pcplayer::update(float vx, float vy) { float speed = 4;klingt so, als ob die rakete ein spieler wäre
wenn das falsch ist, solltest du mal überlegen, warum du die geschwindigkeit nicht als member hast
außerdem ist vx bzw vy evtl nicht der allerbeste variablen-name... ich könnte damit zumindest nix anfangentempx
wie wärs statt dessen mit next_step_x oder act_x oder move_x oder keine Ahnung...würd ich die fkt wahrscheinlich in move und calculate oder so was in der richtung aufteilen...
wenn ich das richtig verstehe, willst du ja die rakete mit dem aktuellen winkel fliegen lassen und für das nächste stück den winkel berechnen...
(würd ich auch nich so machen - wieso nicht gleich den neuen wert nehmen?)usw...
sieht irgendwie ein wenig so aus, als ob du dir das leben unnötig kompliziert machen würdest, in dem du deine fkt so groß und unübersichtlich werden lässt...
bb