IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

NodeJS Discussion :

Main loop coté serveur pour un jeu avec NodeJS?


Sujet :

NodeJS

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Game Créator
    Inscrit en
    Août 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Game Créator

    Informations forums :
    Inscription : Août 2006
    Messages : 39
    Par défaut Main loop coté serveur pour un jeu avec NodeJS?
    Bonjour,

    j'aimerai bien discuter de comment gérer la boucle qui génère un jeu coté serveur avec NodeJS par exemple. Ça pourrait être bien de voir l'ensemble des solutions existante et leur avantages/désavantages.

    Pour gérer la simulation d'un monde coté serveur, on raisonne en "tick" ou "tour". La première chose qui vient donc à l'esprit c'est combien de "ticks" par seconde choisit-on?
    Comment faire ce choix? Quel impacte sur le jeu?

    Ensuite, comment l'appliquer en pratique?

    J'ai vu certaines implémentations qui utilisent un mais ça semble très douteux puisqu'on ne contrôle plus le nombre de ticks en faisant cela. Ça dépend de la capacité de la machine et du nombre de choses à calculé par tick. Ça me parait être une mauvaise solution, peu stable.

    Ensuite il y a la méthode du
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    setInterval(function(){
    tick();
    }, INTERVAL);
    que l'on peut justement minuté en milliseconde, mais le problème c'est qu'on ne peut pas descendre plus bas que la milliseconde...
    Mais finalement a-t-on besoin de pouvoir faire plus que 1000 ticks par seconde? Cela semble déjà être beaucoup. Du coup cette solution parait attrayante.
    J'ai d'ailleurs trouvé un module (dont je ne vois pas l'utilité réel en pratique) mais qui semble confirmer cette approche : https://www.npmjs.com/package/game-loop-dispatch

    Mais un autre problème qui me vient en tête : quelques soit la méthode choisit : que se passe t-il si le temps effectif pour passer un tick est supérieur au temps théorique?


    Voilà, pas mal de problématiques, si vous avez des idées, des retours d'expériences, ou des articles/tuto en français, je suis preneur.


    Merci.

  2. #2
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    Pourquoi un loop côté serveur ? C'est un jeu temps réel ? Généralement on parle de main loop dans un jeu pour maintenir des FPS constants, actualiser le rendu, enregistrer les saisies utilisateur... que des choses qui se passent côté client. Sinon si c'est pour un jeu temps réel avec par exemple une série d'actions qui doivent se produire toutes les minutes, là un setInterval est plus adapté oui. Mais attention, tu ne peux pas prédire le temps que prendront les échanges entre client et serveur.

  3. #3
    Membre chevronné

    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 311
    Par défaut
    Comme tu travailles avec le framework NodeJs , n’oublie pas qu’il possède déjà une MainLoop pour gérer les évènements et les actions asynchrones.

    Donc toutes boucles infinis est à proscrire, dans NodeJs ,car tu vas bloquer l’exécution de ton script et donc ne jamais rendre la main , ne laissant, ainsi, aucune chance aux callbacks de tes actions asynchrones de s’exécuter.

    De manières générales et pour obtenir de bonnes performances, il faut toujours penser à rendre la main, donc d’écrire des scripts dont l’exécution se doit d’être court.
    Pour chaque itérations, tu dois donc estimer la volumétrie et le temps de calcule d’une itération.
    • Si la volumétrie est trop importante il te faut sous découper ton itérations, et celle-ci devient forcement asynchrone
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      function subIterate(array,limit,iterator,endCallback)
      {
      	var idx = -1;
      	function next()
      	{
      		idx+=1;
      		if(idx==array.length)
      			endCallback();
      		else
      		{
      			if(idx%limit==0)
      				setImmediate(iterator,array[idx],next)
      			else
      				iterator(array[idx],next);
      		}
      	}
      	next();
      }
       
      subIterate(collisions,2000,
      function(collision,nextCollision)
      {
      	physicEngine.creatContact(collision.entityA,collision.entityA)
      	nextCollision();
      },
      function()
      {
      	physicEngine.simulate()
      });
    • Si le temps de calcule est trop important, i te faut découper ton traitement
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      subIterate(collection,1,
      function(item,nextItem)
      {
      	traitementA(item,
      	function (err,resultA)
      	{
      		traitementA(item,resultA
      		function (err,resultB)
      		{
      			traitementA(resultA,resultB,nextItem)
      		})
      	})
      },
      function()
      {
      	//all done for collection
      });

    Je te conseille d’écrire toutes tes fonctions avec des signatures asynchrones, et donc d’ajouter le mot clef return a la liste des mots clef a proscrire ( while, for, throw , etc) , car le refactor d’un traitement synchrone en asynchrone est très douloureux !

    Concernant la fréquence d’intervalle des ticks, elle ne peut pas être garantie même avec un setInterval , tu dois donc prendre en compte le delta temps entre chaque tick

  4. #4
    Membre averti
    Homme Profil pro
    Game Créator
    Inscrit en
    Août 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Game Créator

    Informations forums :
    Inscription : Août 2006
    Messages : 39
    Par défaut
    Oui il s'agit d'un jeu temps réel, sinon je ne parlerais pas de boucle coté serveur^^

    Le principe est que même sans client, le serveur tourne, le monde doit évolué, le client ne fait qu'envoyer des requêtes qui modifie des états/valeurs dans les objets qui compose le monde, mais le monde doit tourner tout seul sur le serveur. Je ne sais pas du coup quel méthode adopté.

    Effectivement l'argument de rendre la main pour que les events qui arrivent soit traités semble pertinent, donc on part plutôt sur un setInterval, mais de combien?
    Pour modéliser un univers, combien de tick/frame sont nécessaire ?

    Que faire si le temps de calcule est trop long? Chaque tick doit faire bouger tous les joueurs, tous les objets, calculé les collisions, ajouter des éléments ou en supprimer etc... beaucoup de chose à calculer, plusieurs fois par seconde. Le fait qu'il n'y ait pas de graphisme nous arrange bien, mais que faire si un tick est trop long? Exemple: je décide de faire 1 tick toute les 100ms, si un tick met 150ms à se calculer, ça veux dire que deux tick vont être gérer en parallèle à cause du setInterval... C'est assez problématique !

    Tu me dis qu'il faut couper le traitement pour le rendre asynchrone, je répond forcement non. Il faut qu'un tick se calcule entièrement et sans interruption ni prise en compte des events venu des clients, ça doit etre continue pour etre cohérent. C'est entre deux ticks que sont supposé être dépiler les events clients. Mais là aussi, même problème. Si les tick sont trop long, le "temps entre deux tick" n'existe plus...

  5. #5
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    Je ne comprends pas pourquoi tu parles de "frames" côté serveur. Les frames affichées côté client ne sont pas calculées côté serveur, ce serait une aberration en performance. Faire plusieurs itérations de calcul par seconde, ça ne me paraît pas envisageable avec du TCP. Même avec Websockets c'est ambitieux, dans de mauvaises conditions réseau le ping peut augmenter fortement. Dans tous les cas, il faut que le même code tourne côté client et que la réponse serveur vienne se synchroniser et éventuellement corriger les valeurs côté client. Et j'opterais plutôt pour un ping loop plutôt qu'une itération à délai fixe.

    C'est quel type de jeu exactement ?

  6. #6
    Membre averti
    Homme Profil pro
    Game Créator
    Inscrit en
    Août 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Game Créator

    Informations forums :
    Inscription : Août 2006
    Messages : 39
    Par défaut
    Moi je ne comprends pas comment vous concevez vos jeux en temps réel avec ce raisonnement, pouvez-vous développer?

    Un jeu temps réel doit pouvoir tourner sans aucun client. Le client ne fait que modifier l'état d'objet ou la valeur de variable, mais le serveur doit avoir un système de loop pour simuler la réalité dont il a la charge.
    Et il n'y a pas nécessairement le même nombre de tick coté serveur que coté client qui concerne uniquement l'affichage. L'affichage peut avoir moins de frame et compenser par de l'interpolation.

Discussions similaires

  1. [JSTL] Ecart local/serveur pour affichage de \" avec c:set et c:out
    Par cbil1 dans le forum Taglibs
    Réponses: 0
    Dernier message: 05/01/2012, 11h03
  2. Quels outils pour un jeu avec élément 3D ?
    Par Sergejack dans le forum Flash
    Réponses: 3
    Dernier message: 18/08/2009, 10h53
  3. Architecture client serveur pour un jeu
    Par cb-bk dans le forum Réseau et multijoueurs
    Réponses: 13
    Dernier message: 29/07/2009, 01h00
  4. Quels outils pour un jeu avec élément 3D ?
    Par Sergejack dans le forum Général Conception Web
    Réponses: 4
    Dernier message: 24/07/2009, 13h24
  5. Choix du Serveur pour un jeu flash
    Par Velvounet dans le forum Jeux web
    Réponses: 5
    Dernier message: 08/08/2008, 22h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo