Bilanciamento dinamico del propulsore della nave spaziale


14

Le navi spaziali nel mio gioco intendevano essere costruite dai giocatori con una quantità arbitraria di propulsori collegati ovunque con qualsiasi rotazione. Al momento ho un po 'di codice sporco per ruotare la nave di un determinato angolo (accelerando e decelerando).

Ecco un esempio di una nave simmetrica rivolta verso il punto in cui punta la linea rossa, a cui viene detto di ruotare a sinistra.

Nave

Tuttavia, come puoi immaginare, a seconda di dove il giocatore ha messo i propulsori, a volte forze lineari indesiderate influenzano la nave. In questo caso, la nave inizia ad avanzare.

Sto elaborando se è possibile trovare la massima spinta che un propulsore può applicare per non causare velocità lineare. (Nel caso precedente non ci sarebbe nulla poiché non c'è nulla che possa contrastare le forze dei propulsori posteriori, e quelle anteriori si uccidono a vicenda).

Ciò che ho escogitato finora è una formula per determinare l '"efficienza di virata", ad es. Quanta rotazione è causata in relazione al movimento lineare.

a - posizione vettore all'elica a b - posizione vettore all'elica b v1 - forza dall'elica a v2 - forza dall'elica b

efficienzaDelta = a.cross (v1) / | v1 | - (a.cross (v1) + b.cross (v2)) / | v1 + v2 |

, in pratica "a.cross (v1 * t) / | v1 |" dovrebbe essere l'efficienza del turno. E poi lo sottraggiamo dall'efficienza di virata dei propulsori combinati, per vedere se vale la pena sparare il nuovo propulsore.

Il problema sorge quando mi rendo conto che i propulsori non sono in grado di essere accesi / spenti, ma possono variare la loro spinta da 0 a 1. E come procedere quando il giocatore vuole che la nave vada avanti. Ovviamente, ci dovrebbe essere un equilibrio tra quanto ruotare / spostare.

Non sono uno scienziato missilistico, quindi spero che ci sia qualcuno che possa dirmi se è anche possibile calcolare l'acceleratore di ciascun propulsore in questo modo e darmi una spinta nella giusta direzione.

Grazie per aver dedicato del tempo! / Kim


3
Ho iniziato sullo stesso percorso, ma con molte configurazioni, è impossibile sia ruotare che non tradurre. Quindi togli la rotazione? O permetti la traduzione? In definitiva, spetta all'utente progettare la nave. Per la mia demo di questo, l'ho finto. Correlati: gamedev.stackexchange.com/questions/58216/… , gamedev.stackexchange.com/questions/40615/…
MichaelHouse

Ho seguito un percorso simile e ho finito per scrivere una demo in questa pagina . Mentre muovi i propulsori (trascinali sulla nave per impostare posizione e potenza) disegna tre forme. L'intuizione è che puoi pensare a tutti i possibili movimenti come a un punto nello spazio 3d (x, y, rotazione), ed essere limitati a 0-1 è un vincolo in quello spazio. Quindi finisci con una forma 3d contenente tutti i possibili movimenti. Se non vuoi alcuna velocità lineare, stai osservando la linea (x = 0, y = 0) in quello spazio (Q, W, E, S tutti 0 nella mia demo)
tra

Risposte:


7

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 fin una direzione dired è 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 dire rsono 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 tper 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_isoddisfacendo 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}).


Molto ben spiegato!
Kim,

1
Cosa Sum_isignifica in questo contesto?
S. Tarık Çetin,

1

Il mio primo pensiero è stato una soluzione puramente empirica, ovvero simulare il rig in un ambiente sandbox per vari gradi di spinta per capire come si comporta. Invece di bilanciare un sacco di matematica complessa nella ricerca di una soluzione deterministica, puoi raggiungerla numericamente, ad esempio usando il metodo newton. Esempio:

L'intervallo per la spinta è compreso tra 0 e 1000, dove 1000 è MOLTO.

Passo 1

Simula con fiducia (0 + 1000) / 2 = 500. Risultato: troppa fiducia

Passo 2

L'intervallo è ora compreso tra 0 e 500 Simula con fiducia (0 + 500) / 2 = 250. Risultato: troppa fiducia

Passaggio n. 3

L'intervallo è ora da 0 a 250 Simula con fiducia (0 + 250) / 2 = 125 Risultato: fiducia troppo scarsa

Passaggio 4

L'intervallo è ora compreso tra 125 e 250 Simula con fiducia (125 + 250) /2=187.5 Risultato con troppa fiducia

Il passaggio n. 5 è ora compreso tra 125 e 187,5 Simula con fiducia (125 + 187,5) /2=156,25 Il risultato è troppo poco attendibile

L' intervallo n. 6 è ora compreso tra 156,25 e 187,5 L'intervallo è inferiore alla soglia di 35, il che significa che è una stima abbastanza buona

Risultato finale = (187.5 + 156.25) / 2 = 171.875

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.