Boucle de jeu côté serveur

8

De nombreux jeux java utilisent thread.sleep () pour contrôler les fps. Étant donné que le serveur n'affiche pas de graphiques, la boucle de jeu du serveur doit-elle continuer à fonctionner uniquement en calculant le temps delta? Comme cet exemple:

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);
}
Wolfrevo Kcats
la source
11
"De nombreux jeux java utilisent thread.sleep () pour contrôler les fps" Man, j'espère que non.
MichaelHouse
1
@ Byte56 Je ne dirais pas beaucoup, mais certains pourraient faire une telle chose. Bien que sleepig soit quelque chose de commun, son mécanisme n'est pas prédéfini. Thread.Sleepest le moyen le plus simple, certains pourraient attendre des interruptions du système d'exploitation. Vous pouvez même compter vSync comme un mécanisme de sommeil.
Ali1S232

Réponses:

6

Il y a plusieurs raisons pour lesquelles je ne dirais pas cela:

  1. Les ressources informatiques sont précieuses. même s'ils sont gratuits, vous ne devez pas les gaspiller. considérons le cas où deux serveurs ou plus s'exécutent simultanément sur un même ordinateur. Si une seule instance de serveur consomme tous les cycles de CPU, les autres instances échoueront simplement. Certes, OS tentera de gérer ce comportement un peu gourmand, mais cela aura un coût. Vous ne saurez pas où le système d'exploitation suspendra votre processus et donnera des cycles de processeur à l'autre. Vous pouvez également vouloir libérer votre serveur en même temps que le jeu réel, afin que les joueurs puissent lancer leurs propres jeux LAN. C'est un peu ennuyeux si je dédie un de mes cœurs de processeur juste pour exécuter un serveur de jeu!

  2. La plupart des jeux, les jeux synchronisés spécialement en réseau, utilisent un pas de temps fixe. tout simplement parce qu'ils veulent pouvoir prédire ce qui va se passer côté client. Le pas de temps dynamique est idéal pour de nombreuses raisons tant que vous exécutez une seule instance de votre jeu et qu'il ne sera synchronisé avec nulle part ailleurs. Cela vous donnera la puissance du système exécutant le jeu dans toute sa mesure. Mais encore une fois, il y a un prix. Vous ne pourrez pas prédire ce qui va se passer si vous relancez le jeu. envisager une collision physique simple, où une boîte frappe une autre boîte. Le moindre changement de pas de temps entraînera de grandes différences dans la résolution de collision résultante.

  3. Il y a une raison simple pour laquelle les gens utilisent Thread.Sleep comme vous l'avez suggéré, car ajouter plus de précision ne se traduira pas par un meilleur jeu. Lorsque vous jouez à un jeu, vous ne remarquerez généralement pas si un objet est à un ou deux pixels. Vous ne gagnerez donc rien en augmentant la précision. Il existe également une limite de bande passante réseau, côté serveur et côté client. Cela signifie que vous ne pourrez généralement pas envoyer plus de 30 à 60 mises à jour par seconde. Je peux donc demander pourquoi devriez-vous calculer les états que vous allez simplement jeter?

  4. Il existe de nombreux cas où l'augmentation de la précision peut causer des problèmes. Par exemple, les gens ont tendance à utiliser la "synchronisation verticale" afin que le tampon graphique ne soit pas mis à jour lors de l'envoi de données au moniteur (ce qui pourrait entraîner une rupture). De plus, la plupart des jeux utilisent des flotteurs comme conteneur de numéro principal, mais ils ne sont pas précis. Vous ne remarquerez peut-être pas lorsque les nombres sont compris entre 2 ^ -20 et 2 ^ 20, mais en dehors de cette plage, vous verrez des comportements inexacts. Par exemple, si vous essayez d'ajouter 10 ^ -5 à 10 ^ 5, il ignore simplement votre ajout. Ces erreurs ne sont généralement pas visibles, mais lorsque vous n'avez pas un contrôle total sur votre pas de temps, les choses peuvent devenir laides. Dans votre cas, comme il n'y a pas de rendu, je suppose que votre temps de mise à jour devrait être d'environ 10 ^ -4 au maximum, ce qui signifie que toutes les modifications pour les nombres supérieurs à 100 seront gâchées!

  5. Dans certains jeux, seules les commandes des joueurs feront des différences imprévisibles. vous pouvez donc utiliser uniquement votre serveur pour diffuser les commandes de chaque joueur aux autres joueurs. Dans ces cas, vous pouvez simplement attendre que l'un des clients envoie une mise à jour au serveur. Il n'y a rien à calculer entre ces mises à jour, ce qui signifie que les clients peuvent tout faire (à part la diffusion large), alors laissez le serveur uniquement faire son travail et laisser quoi que ce soit d'autre aux clients.

Ali1S232
la source
Merci, vous y avez fait valoir de bons points. Je pense que je n'ai pas besoin d'horodatage variable. Encore une chose, que proposez-vous comme mécanisme de sommeil?
Wolfrevo Kcats
@WlofrevoKcast Il est entièrement basé sur les besoins de votre jeu, mais pour la plupart des jeux, les chronomètres de langue internes (ou les interruptions de temps du système d'exploitation) sont un bon choix.
Ali1S232
4

Vous devriez lire ceci (horodatage semi-fixe ou entièrement fixe?) Et ceci (Gaffer on Games - Fix your Timestep) .

Je ne sais pas pourquoi vous incluez un FPS cible dans votre logique de serveur. Trouvez un pas de temps fixe qui vous convient et mettez-le à jour en conséquence.

Fondamentalement, vous aurez une autre boucle while dans votre while (gameRunning)boucle qui accumulera du temps jusqu'à ce qu'elle soit prête à faire une mise à jour. Ensuite, vous effectuez des mises à jour à intervalles fixes.

MichaelHouse
la source