Vous devez d'abord déterminer la différence d'angle entre la direction de la tourelle et la direction de la cible.
Vector2 turretToTarget = target.position - turret.position;
float desiredAngle = atan2(turretToTarget.y, turretToTarget.x);
float angleDiff = desiredAngle - turret.angle;
// Normalize angle to [-PI,PI] range. This ensures that the turret
// turns the shortest way.
while (angleDiff < -PI) angleDiff += 2*PI;
while (angleDiff >= PI) angleDiff -= 2*PI;
Une fois que vous avez ces quantités, vous pouvez configurer une expression du deuxième degré pour l'angle de la tourelle. Vous devez calculer cela à chaque mise à jour pour vous assurer que vous utilisez toujours les dernières données de positions et de vitesses.
// Compute angular acceleration.
const float C0 = // Must be determined.
const float C1 = // Must be determined.
float angularAcc = C0 * angleDiff - C1 * turret.angularVelocity;
Ici, le premier terme (zéro degré) dans l'expression d'accélération fera tourner la tourelle vers la cible. Cependant, il ne s'arrêtera pas dans le temps mais oscillera plutôt d'avant en arrière. Pour l'arrêter, nous avons besoin du deuxième terme d'amortissement (premier degré) qui provoque une vitesse de rotation élevée à opposer à une accélération élevée.
Maintenant, les constantes positives (pas nécessairement les constantes de programme) doivent être déterminées et équilibrées pour que le système se comporte bien. C0
est le principal contrôle de la vitesse du système. Une valeur élevée pour C0
donnera une vitesse de rotation rapide et une valeur faible donnera une vitesse de rotation faible. La valeur réelle dépend de nombreux facteurs, vous devez donc utiliser essais et erreurs ici. C1
contrôle l'amplitude de l'amortissement. Le discriminant de l'équation quadratique nous dit que si C1*C1 - 4*C0 >= 0
nous avons un système non oscillant.
// New definition.
const float C1 = 2*sqrt(C0); // Stabilizes the system.
Vous devriez probablement choisir C1
un peu plus grand que cela pour des raisons numériques, mais pas trop grand car il peut devenir très sur-amorti et lent à répondre à la place. Encore une fois, vous devez modifier.
Il est également important de noter que ce code ne calcule que l'accélération angulaire. L'angle et la vitesse angulaire doivent être mis à jour à partir de cela ailleurs, en utilisant et en quelque sorte un intégrateur. D'après la question, je suppose que cela a été couvert.
Enfin, il y a quelque chose à dire sur le retard, car la tourelle sera probablement toujours derrière lors du suivi d'une cible rapide. Un moyen simple de résoudre ce problème consiste à ajouter une prédiction linéaire à la position de la cible, c'est-à-dire à viser toujours légèrement en avant dans la direction avant de la cible.
// Improvement of the first lines above.
const float predictionTime = 1; // One second prediction, you need to experiment.
Vector2 turretToTarget = target.position + predictionTime * target.velocity - turret.position;
/// ...
Quant à maintenir la tourelle dirigée dans le rayon de la cible pendant un certain temps, cela peut être une exigence difficile à imposer directement à ce type de système. Vous pouvez être certain que ce contrôleur s'efforcera de garder la tourelle dirigée vers la cible (ou plutôt la position prédite) à tout moment. Si le résultat s'avère que vous avez de ne pas être satisfaisante pour modifier les paramètres predictionTime
, C0
et C1
(dans des limites de stabilité).