In Anbetracht des Kontextes Ihrer Frage, http://nodewar.com/ , gibt es einige spezifische Überlegungen für Ihre Lösung:
- Sie haben eine (niedrige) maximale Winkelgeschwindigkeit und genügend maximales Drehmoment, um diese in sehr kurzer Zeit zu erreichen.
- Ihre Drohne und Ihr Ziel haben jeweils Geschwindigkeit und externe Beschleunigung, die nicht mit dem Schub zusammenhängen (Gravitation ist im Überfluss vorhanden).
- Ihr gewünschtes Ziel ändert sich so häufig, dass der Versuch, perfekt zu zielen, eine Verschwendung wäre. Sie sollten versuchen, näher zu kommen, und es jedes Bild korrigieren.
Diese Methoden habe ich beschlossen, um eine gewünschte Beschleunigung zu erreichen.
Beschleunigung, nicht Geschwindigkeit
Da Sie bereits eine bestimmte Geschwindigkeit haben und sich Ihr Ziel bewegt, müssen Sie nicht auf einen Punkt zugehen. Sie benötigen Schub, um Ihre Geschwindigkeit auf das zu ändern, was sie sein sollte. Dies bedeutet, dass Ihr Schiff nicht darauf zeigen muss, wohin es fährt, sondern in die Richtung, in die es beschleunigen soll.
// My target velocity is for maintaining a circular orbit. Yours may differ.
// Earlier, I calculated total gravity and the perpendicular direction.
// You may wish to subtract gravity from your total, rather than match it.
var targetVel = o.lib.vec.times(lateralDir, targetVelMag);
var targetAccel = lv.sum(
o.lib.vec.diff(targetVel, o.me.vel),
o.lib.vec.times(gravity, 1 / o.me.mass)
);
In Richtung der rechten Richtung steuern
Sie haben einen Beschleunigungsvektor, den Sie jetzt anwenden möchten. Bestimmen Sie, wie weit Sie drehen müssen. Ich habe hier wahrscheinlich mehr Schritte als erforderlich verwendet, aber die Rotationskoordinaten verwirren mich, und ich denke, dass der Wert der nicht begrenzten Schiffsrotation ohnehin ein Fehler in der API ist.
// convert acceleration to an angle
var polar = o.lib.vec.toPolar(targetAccel);
var traj = polar[1];
// constrain the angle to +/-2PI, because the ship's rotation is not limited
// by default
var fixed_rot = o.lib.ang.rescale(o.me.rot);
// limit the correction to be +/-1PI
var traj_correction = traj - fixed_rot;
if (traj_correction > (Math.PI)){
traj_correction = (2 * Math.PI) - traj_correction;
} else if (traj_correction < (-1 * Math.PI)){
traj_correction = (2 * Math.PI) + traj_correction;
}
Eine einfache Formel. Es schadet nicht, ständig zu drehen. Wenden Sie also keine Teildrehmomentwerte an. Wenn Sie eine kleine Korrektur der Winkelgeschwindigkeit benötigen, können Sie diese Bestimmung ohnehin mehrmals pro Sekunde vornehmen.
if (traj_correction > 0){
torque = 1;
} else if (traj_correction < 0){
torque = -1;
}
Eine weniger einfache Formel. Es wird einen Punkt geben, an dem Sie nicht weiter drehen möchten, weil Sie schließlich aufhören möchten. Glücklicherweise bedeutet diese Winkelgeschwindigkeitsbegrenzung, dass Sie schnell von der maximalen Winkelgeschwindigkeit auf Null verlangsamen können. Sie müssen nur berechnen, wann Sie dies tun müssen.
var max_a_accel = c.MAX_TORQUE / o.me.m_i;
var a_deccel_time = Math.abs(o.me.a_vel) / max_a_accel;
// the same math as linear acceleration, now in angles.
var stopping_angle = 0.5 * max_a_accel * a_deccel_time * a_deccel_time;
if (stopping_angle >= Math.abs(traj_correction)){
// slowdown required. Reverse torque
torque *= -1;
}
Nachdem Sie den obigen Code an Ihre Bedürfnisse angepasst haben, sollte sich Ihr Schiff schnell und präzise in den Winkel drehen, den Sie dem Ziel gegeben haben.
Rammgeschwindigkeit
Also, wann stoßen? Wiederum verursachen die schnelle Änderung des Ziels und andere Faktoren große Schwierigkeiten bei der Lösung einer exakten Lösung. Versuche es nicht.
// if the heading is close to the final value, thrust.
if (Math.abs(traj_correction ) < 0.02) { // about 1 degree
if (true
// some logical test, in case you don't want to accelerate past
// a maximum speed, or some such. Not required for your stated purpose.
){
thrust = 1;
}
}
In den Fällen, in denen Sie einen Teilschub benötigen, können Sie sich erneut darauf verlassen, dass Sie mehrmals pro Sekunde zwischen 0 und 1 Schub wählen können. Dies gibt Ihnen einen effektiven Teilschub, ohne den tatsächlichen Wert zu verändern.
Viel Glück!