Presumo che tu abbia un movimento fisicamente corretto per la tua nave, altrimenti questa analisi non regge. Hai bisogno di qualcosa di più forte dell'efficienza per risolvere correttamente questo problema.
Ogni propulsore produrrà due effetti sul movimento della nave: lineare e angolare. Questi possono essere considerati in modo indipendente. Se il propulsore produce una forza f
in una direzione dir
ed è sfalsato dal centro di massa da un vettore r
(non dal centro geometrico o dal centro dello sprite!), L'effetto sulla componente lineare è:
t = f * dir // f is a scalar, dir is unit length
L'effetto sulla velocità angolare è dato dalla coppia:
tau = f * <dir.x, dir.y, 0> CROSS <r.x, r.y, 0> // cross product
t
è un vettore di forza (ovvero la spinta lineare). tau
è uno scalare con segno che, quando diviso per il momento di inerzia di massa, darà l'accelerazione angolare. È importante che dir
e r
sono entrambi nello stesso spazio di coordinate, cioè sia in coordinate locali o sia in coordinate mondo.
L'accelerazione lineare complessiva della nave è data dalla somma di quella t
per ciascun propulsore divisa per la massa della nave. Allo stesso modo, l'accelerazione angolare è solo la somma delle coppie divise per il momento di inerzia di massa (che è un altro scalare). La nave non girerà se la coppia totale è zero. Allo stesso modo, non si muoverà se la spinta totale è zero. La coppia di richiamo è uno scalare ma la spinta (la somma di t
's) è un vettore 2D.
Il punto di questa esposizione è che ora possiamo scrivere il nostro problema come programma lineare . Per prima cosa vogliamo che la nostra nave ruoti senza muoversi . Abbiamo una variabile per ogni propulsore, $ x_1, x_2, ... $, che è la quantità di spinta che il propulsore fornirà. Un insieme di vincoli è:
0 <= x_i < fmax_i //for each i
dove fmax
è la forza massima per quel propulsore (questo ci permette di avere quelli più forti o più deboli). Quindi, diciamo che entrambe le uguaglianze:
0 = Sum_i x_i * dir_i.x
0 = Sum_i x_i * dir_i.y
Questo codifica il vincolo che non applicheremo un'accelerazione lineare, dicendo che la spinta totale è zero (la spinta è un vettore, quindi diciamo solo che ogni parte è zero).
Ora vogliamo che la nostra nave giri. Presumibilmente vogliamo farlo il più rapidamente possibile, quindi vogliamo:
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>
Risolvere il problema x_i
soddisfacendo le disuguaglianze e le uguaglianze di cui sopra, massimizzando la somma sopra, ci darà la spinta desiderata. La maggior parte dei linguaggi di programmazione ha a disposizione una libreria LP. Basta inserire il problema sopra e produrrà la tua risposta.
Un problema simile ci permetterà di muoverci senza voltarci. Supponiamo di riscrivere il nostro problema in un sistema di coordinate in cui vogliamo spostarci nella direzione x positiva. Quindi i vincoli sono:
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
Con il vincolo che i propulsori possono produrre la spinta solo in una singola direzione, ci saranno limiti al tipo di rotazioni e velocità lineari che sarai in grado di raggiungere. Questo si manifesterà come soluzione 0 = x_1 = x_2 = ... = x_n
, il che significa che non arriverai mai da nessuna parte. Per mitigare questo, suggerisco di aggiungere una coppia di propulsori piccoli, deboli (diciamo 5% o 10%) per ogni giocatore che posiziona il propulsore a 45 gradi su entrambi i lati. Ciò darà maggiore flessibilità alla soluzione, poiché possono essere utilizzati per contrastare gli effetti secondari deboli dei propulsori principali.
Infine, per un massimo di forse 100 propulsori, la soluzione per l'LP è abbastanza veloce da fare per frame. Tuttavia, poiché la soluzione non dipende dalla posizione o dallo stato corrente, è possibile pre-calcolare la soluzione per ogni ragionevole combinazione di input del controller ogni volta che la forma cambia (ciò include l'aggiunta di non propulsori che cambiano il momento di inerzia o la massa della nave, perché allora i propulsori si trovano in una posizione diversa rispetto al centro di massa!). Sono disponibili 24 possibilità (ovvero 8 direzioni volte {rotazione a sinistra, nessuna rotazione, rotazione a destra}).