Je suppose que vous avez un mouvement physiquement correct pour votre navire, sinon cette analyse ne tiendra pas. Vous avez besoin de quelque chose de plus fort que l'efficacité pour résoudre correctement ce problème.
Chaque propulseur produira deux effets sur le mouvement du navire: linéaire et angulaire. Ceux-ci peuvent être considérés indépendamment. Si le propulseur produit une force f
dans une direction dir
, et est décalé du centre de masse par un vecteur r
(pas le centre géométrique ou le centre du sprite!), Alors l'effet sur la composante linéaire est:
t = f * dir // f is a scalar, dir is unit length
L'effet sur la vitesse angulaire est donné par le couple:
tau = f * <dir.x, dir.y, 0> CROSS <r.x, r.y, 0> // cross product
t
est un vecteur de force (c'est-à-dire la poussée linéaire). tau
est un scalaire signé qui, divisé par le moment d'inertie de masse, donnera l'accélération angulaire. Il est important que dir
et r
soient tous deux dans le même espace de coordonnées, c'est-à-dire les deux en coordonnées locales ou les deux en coordonnées mondiales.
L'accélération linéaire globale du navire est donnée par la somme des t
s pour chaque propulseur divisée par la masse du navire. De même, l'accélération angulaire n'est que la somme des couples divisés par le moment d'inertie de masse (qui est un autre scalaire). Le navire ne tournera pas si le couple total est nul. De même, il ne bougera pas si la poussée totale est nulle. Le couple de rappel est un scalaire mais une poussée (la somme dest
) est un vecteur 2D.
Le point de cette exposition est que maintenant nous pouvons écrire notre problème comme un programme linéaire . Dites d'abord que nous voulons que notre navire tourne sans bouger . Nous avons une variable pour chaque propulseur, $ x_1, x_2, ... $, qui est la quantité de poussée que le propulseur fournira. Un ensemble de contraintes est:
0 <= x_i < fmax_i //for each i
où fmax
est la force maximale pour ce propulseur (cela nous permet d'avoir des forces plus fortes ou plus faibles). Ensuite, nous disons que les deux égalités:
0 = Sum_i x_i * dir_i.x
0 = Sum_i x_i * dir_i.y
Cela encode la contrainte que nous n'appliquerons pas d'accélération linéaire, en disant que la poussée totale est nulle (la poussée est un vecteur, donc nous disons simplement que chaque partie est nulle).
Maintenant, nous voulons que notre navire tourne. Vraisemblablement, nous voulons le faire le plus rapidement possible, nous voulons donc:
max (Sum_i x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0>
Résoudre pour le x_i
tout en satisfaisant les inégalités et les égalités ci-dessus, tout en maximisant la somme ci-dessus, nous donnera la poussée souhaitée. La plupart des langages de programmation ont une bibliothèque LP disponible pour eux. Mettez simplement le problème ci-dessus et cela produira votre réponse.
Un problème similaire nous permettra d'avancer sans tourner. Supposons que nous réécrivions notre problème dans un système de coordonnées dans lequel nous voulons nous déplacer dans la direction x positive. Alors les contraintes sont:
0 <= x_i < fmax_i //for each i
max Sum_i x_i * dir_i.x
0 = Sum_i x_i * dir_i.y
0 = (Sum_i x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0> // as before
Avec la contrainte que les propulseurs ne peuvent produire une poussée que dans une seule direction, il y aura des limites au type de rotations et de vitesses linéaires que vous pourrez réaliser. Cela se manifestera lorsque la solution sera0 = x_1 = x_2 = ... = x_n
, ce qui signifie que vous n'irez nulle part. Pour atténuer cela, je suggère d'ajouter une paire de petits propulseurs faibles (disons 5% ou 10%) pour chaque joueur placé à 45 degrés de chaque côté. Cela donnera à la solution plus de flexibilité, car ceux-ci peuvent être utilisés pour contrer les effets secondaires faibles des propulseurs principaux.
Enfin, pour jusqu'à 100 propulseurs, la solution au LP est suffisamment rapide pour être effectuée par image. Cependant, comme la solution ne dépend pas de l'emplacement ou de l'état actuel, vous pouvez précalculer la solution pour chaque combinaison d'entrée de contrôleur raisonnable chaque fois que la forme change (cela inclut l'ajout de non-propulseurs qui modifient le moment d'inertie ou la masse du navire, car alors les propulseurs sont dans un emplacement différent par rapport au centre de masse!). C'est 24 possibilités (soit 8 directions fois {rotation gauche, pas de rotation, rotation droite}).