37 votes

Jeu multijoueur avec backend et frontend JavaScript. Quelles sont les meilleures pratiques ?

Je pense créer un jeu multi-joueurs sur le web en Node.js . Cela signifie que j'utiliserai le même langage dans le backend et dans le frontend. Il s'agirait d'un projet en temps réel, avec une vingtaine de personnes maximum dans chaque "salle", et j'ai donc quelques idées :

  1. Comment compenser le retard entre tous les utilisateurs pour que chacun voie la même chose au même moment ? Je pense suivre le temps de ping moyen de chaque joueur, trouver le plus lent, et informer les autres clients du temps (en millisecondes) dont ils doivent être retardés chacun pour que tout le monde soit aussi synchronisé que possible.

  2. J'envisage de faire tourner le code du jeu dans le backend ainsi que dans le frontend (puisque c'est du JavaScript aux deux extrémités) et d'avoir juste un mécanisme de correction d'erreur pour se synchroniser avec le "vrai jeu" dans le backend. De cette façon, le jeu devrait se dérouler sans problème sur le front-end et avec seulement quelques pépins lorsque la synchronisation se produit. Cela minimiserait également le piratage JavaScript en front-end puisque les tricheurs seraient synchronisés avec le jeu en back-end.

  3. Dois-je recevoir les actions des joueurs via le socket (pressions sur les touches), informer tous les autres clients des actions des autres joueurs et, pendant ce temps, "jouer" le jeu dans le backend et envoyer des informations de synchronisation à tout le monde sur l'état complet du jeu de temps en temps pour les synchroniser ?

Qu'en pensez-vous ? Y a-t-il d'autres éléments que je devrais prendre en considération ou auxquels je devrais prêter attention ?

Veuillez poster toute réflexion ou tout lien vers de la documentation ou des articles concernant les jeux multi-joueurs.


EDIT : Ceux-ci sont utiles :

27voto

Kylotan Points 14114

1 - est impossible. Vous ne savez pas exactement combien de temps un message mettra à arriver sur un client et aucune mesure que vous prenez ne sera nécessairement applicable au prochain message que vous enverrez. Le mieux que vous puissiez faire est une approximation, mais vous devez toujours supposer que les gens verront SOIT des choses légèrement différentes SOIT les mêmes choses à des moments légèrement différents. Je recommanderais d'envoyer simplement l'état actuel à tout le monde et d'utiliser l'interpolation/extrapolation pour lisser le jeu, de sorte que tout le monde voit le jeu quelques millisecondes dans le passé, le délai variant à la fois entre les joueurs et dans le temps. En général, c'est rarement un gros problème. Si vous voulez vraiment mettre en mémoire tampon certains états passés sur le serveur, vous pouvez interpoler entre eux et envoyer différentes anciennes données à différentes personnes pour tenter de synchroniser ce qu'elles voient, mais combiné avec la simulation côté client et la gigue dans les temps de transmission, vous verrez toujours quelques différences entre les machines.

2 - la méthode classique consiste à exécuter la simulation sur le serveur et à envoyer régulièrement des (petites) mises à jour d'état aux clients. Les clients exécutent généralement leurs propres simulations et disposent d'un moyen de faire le lien entre leur propre état prédit/interpolé et l'état faisant autorité que le serveur leur envoie. Toutes les décisions autres que celles prises par l'utilisateur doivent être prises par le serveur. En fin de compte, la façon dont vous mélangez ces éléments n'est qu'un compromis entre une apparence lisse et un état précis, c'est donc une décision cosmétique que vous devrez prendre.

3 - votre client doit généralement traduire une pression sur une touche en une action logique. Votre serveur ne se soucie pas des touches. Envoyez cette action logique au serveur et il peut la diffuser aux autres clients s'ils en ont besoin. En général, vous n'avez pas besoin de faire quoi que ce soit ici - tout changement pertinent causé par l'action changera l'état du jeu, et sera donc envoyé dans la diffusion normale de cet état.

5voto

Tauren Points 9324

Je n'aborderai pas directement vos points car les autres réponses le font si bien. Mais je vous suggère de vous intéresser à HTML5, WebSockets et Comet, qui promettent d'améliorer considérablement les performances en temps réel. Ces technologies vous permettent d'avoir des requêtes HTTP de longue durée, ce qui permet au serveur de pousser les données vers le client plutôt que de laisser le client interroger le serveur. Cela peut accélérer considérablement les choses.

Voici quelques ressources qui devraient s'avérer utiles :

1voto

Santi Points 1
  1. C'est très difficile à faire, et je vois beaucoup de problèmes avec la synchronisation sur "le plus lent". Pouvez-vous assouplir ce point pour que les clients puissent être "éventuellement cohérents" ?

  2. Ça a l'air bien.

  3. J'enverrais des événements d'action courts des frontaux vers le backend, le backend modifierait l'état du jeu et publierait les événements de modification de l'état du jeu vers les clients, en veillant à n'envoyer que les événements nécessaires aux bons abonnés. À ce stade, vous pouvez écarter tous les événements qui ne semblent pas correspondre ou qui semblent être des fakes/hacks.

1voto

MatsT Points 1036

La meilleure solution consiste à conserver la trace de tous les objets à un seul endroit, à savoir le serveur. Tout le monde verra les informations des serveurs un temps de déplacement plus tard que ce qui "se passe réellement" et les commandes des gens prendront un temps de déplacement pour s'enregistrer sur le serveur. Il n'y a vraiment aucun moyen de contourner ce problème. Pour certaines applications, il peut être pratique de simuler son propre mouvement immédiatement sans attendre la réponse du serveur, mais cela conduira sans aucun doute à un cauchemar avec la programmation du timing et les gens se verront généralement les uns les autres "à la traîne". La détection des collisions est pratiquement impossible.

L'effet net de cette situation est qu'il y aura une certaine lenteur entre le moment où vous entrez vos commandes et celui où vous les voyez se produire, mais nous espérons que les gens apprendront à s'en accommoder et essaieront d'entrer leurs commandes un peu plus tôt pour compenser. Avec des connexions lentes, les jeux rapides en temps réel sont tout simplement impossibles.

1voto

colin moock Points 479

Si vous cherchez un exemple de code pour apprendre, il existe un jeu multijoueur en ligne de Pong réalisé en ActionScript avec des éléments physiques côté serveur interpolés par les clients.

Cet exemple de Pong est construit sur le Plate-forme syndicale qui est disponible gratuitement pour un maximum de 1000 connexions clients simultanées.

L'Union dispose d'un cadre client JavaScript, _OrbiterMicro (client JavaScript)_ .

Et vous pouvez également écrire votre logique côté serveur en JavaScript, voir _Création de modules de salle avec JavaScript_ .

(Divulgation complète : je suis le cofondateur de Union).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X