Ciclo di gioco lato server


8

Molti giochi Java usano thread.sleep () per controllare fps. Dal momento che il server non visualizza grafica, il loop di gioco del server dovrebbe continuare a funzionare solo calcolando il delta time? Come questo esempio:

long lastLoopTime = System.nanoTime();
final int TARGET_FPS = 60;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;   

while (gameRunning)
{
   long now = System.nanoTime();
   long updateLength = now - lastLoopTime;
   lastLoopTime = now;
   double delta = updateLength / ((double)OPTIMAL_TIME);

   doGameUpdates(delta);
}

11
"Molti giochi Java usano thread.sleep () per controllare gli fps" Amico, spero di no.
MichaelHouse

1
@ Byte56 Non direi molti, ma alcuni potrebbero fare una cosa del genere. Sebbene sleepig sia qualcosa di comune, il suo meccanismo non è predefinito. Thread.Sleepè il modo più semplice, alcuni potrebbero attendere interruzioni del sistema operativo. Puoi persino contare vSync come meccanismo di sospensione.
Ali1S232,

Risposte:


6

Ci sono molte ragioni per cui non suggerirei che:

  1. Le risorse del computer sono preziose. anche se sono gratuiti, non dovresti sprecarli. considerare il caso in cui due o più server sono in esecuzione contemporaneamente su un computer. Se una singola istanza del server consuma tutti i cicli della CPU, altre istanze semplicemente falliranno. Surly OS proverà a gestire questo tipo di comportamento avido ma avrà un costo. Non saprai dove il sistema operativo interromperà il processo e fornirà i cicli della CPU all'altro. Inoltre, potresti voler rilasciare il tuo server insieme al gioco reale, in modo che i giocatori possano avviare i propri giochi LAN. È un po 'fastidioso se ho dedicato uno dei miei core CPU solo per eseguire un server di gioco!

  2. La maggior parte dei giochi, giochi sincronizzati appositamente collegati in rete, utilizza un time-step fisso. semplicemente perché vogliono essere in grado di prevedere cosa accadrà dal lato client. Il time step dinamico è ottimo per tanti motivi, purché si esegua una singola istanza del gioco e non sarà sincronizzato con nessun altro. Ti garantirà la potenza del sistema che esegue il gioco nella sua massima estensione. Ma di nuovo c'è un prezzo per questo. Non sarai in grado di prevedere cosa accadrà se esegui di nuovo il gioco. considera la semplice collisione fisica, in cui una scatola colpisce un'altra scatola. Anche il minimo cambiamento nella fase temporale comporterà grandi differenze nella risoluzione della collisione risultante.

  3. C'è un semplice motivo per cui le persone usano Thread.Sleep come hai suggerito, perché l'aggiunta di maggiore precisione non si tradurrà in un gioco migliore. Quando stai giocando, di solito non ti accorgerai se un oggetto è spento di uno o due pixel. Quindi non otterrai nulla aumentando la precisione. Inoltre esiste un limite di larghezza di banda di rete, sia lato server che lato client. Ciò significa che di solito non sarai in grado di inviare più di 30-60 aggiornamenti al secondo. Quindi posso chiederti perché dovresti calcolare gli stati che stai per buttare via?

  4. Ci sono molti casi in cui l'aumento della precisione potrebbe causare problemi. Ad esempio, le persone tendono a utilizzare la "Sincronizzazione verticale" in modo tale che il buffer grafico non venga aggiornato durante l'invio di dati al monitor (il che potrebbe provocare la rottura). Inoltre, la maggior parte dei giochi utilizza i float come contenitore di numeri principali ma non sono precisi. Potresti non notare quando i numeri sono compresi tra 2 ^ -20 e 2 ^ 20 ma al di fuori di questo intervallo vedrai comportamenti imprecisi. Ad esempio, se provi ad aggiungere da 10 ^ -5 a 10 ^ 5, semplicemente ignora la tua aggiunta. Questi tipi di errori non sono generalmente visibili, ma quando non si ha il pieno controllo del proprio passo temporale, le cose potrebbero diventare brutte. Nel tuo caso, poiché non è necessario alcun rendering, suppongo che il tempo di aggiornamento dovrebbe essere al massimo di circa 10 ^ -4, il che significa che tutte le modifiche per numeri superiori a 100 verranno incasinate!

  5. In alcuni giochi, sono solo i comandi del giocatore a fare differenze imprevedibili. quindi potresti voler usare il tuo server solo per trasmettere i comandi di ciascun giocatore agli altri giocatori. In questi casi potresti semplicemente aspettare fino a quando uno dei client non invierà al server un aggiornamento. Non c'è nulla da calcolare tra questi aggiornamenti, il che significa che i client possono fare qualsiasi cosa (oltre al cast generico), quindi lascia che il server faccia solo il suo lavoro e lasci qualcos'altro ai client.


Grazie, hai fatto buoni punti lì. Penso di non aver bisogno di un timestep variabile. Ancora un'altra cosa, cosa suggerisci come meccanismo per dormire?
Wolfrevo Kcats il

@WlofrevoKcast È completamente basato sulle esigenze del tuo gioco, ma per la maggior parte dei giochi, i timer di lingua interna (o interruzioni di tempo del sistema operativo) sono una scelta abbastanza buona.
Ali1S232,

4

Dovresti leggere questo (Timestep semi-fisso o Full-fixed?) E questo (Gaffer on Games - Fix your Timestep) .

Non sono sicuro del motivo per cui stai includendo un FPS di destinazione nella logica del tuo server. Trova un passaggio temporale fisso adatto a te e aggiorna in base a quello.

Fondamentalmente avrai un altro ciclo while all'interno del tuo while (gameRunning)ciclo che accumulerà tempo fino a quando non è pronto per fare un aggiornamento. Quindi esegui aggiornamenti a intervalli fissi.

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.