J'ai les bases des sockets TCP, de la communication UDP, etc., mais je ne trouve pas grand-chose sur la façon de les appliquer à un environnement de jeu en temps réel.
J'ai un clone Pong, avec 4 joueurs, et j'ai besoin de synchroniser les positions des palettes entre les trois clients et le serveur (le serveur est le quatrième joueur). Actuellement, j'utilise UDP pour envoyer des mises à jour en temps réel (mouvements de pagaie), et TCP pour configurer le lobby du jeu, etc.
Est-ce une mauvaise chose de spammer d'énormes quantités de trafic UDP? Dois-je examiner quelque chose comme DCCP pour ses fonctionnalités de congestion? Ou n'est-ce pas vraiment un problème avec un projet à petite échelle comme celui-ci?
Quand les messages de synchronisation doivent-ils être envoyés entre le client / serveur? Actuellement, le serveur envoie des paquets UDP avec l'état actuel du jeu aussi rapidement qu'il peut gérer, et les clients renvoient leur position de palette vers le serveur aussi vite qu'ils le peuvent. Est-ce la meilleure façon de le faire? Y a-t-il une sorte de retard que je devrais ajouter pour que les messages soient envoyés toutes les X millisecondes, ou dois-je envoyer des messages uniquement lorsque des événements se produisent? (par exemple, la vitesse de la palette a changé en raison de l'entrée de l'utilisateur)
Serait-il préférable que les clients communiquent leurs positions de pagaie entre eux?
Je pose ces questions dans le contexte de Pong, mais je suis également intéressé par la manière dont ces problèmes seraient surmontés dans d'autres jeux ou par des solutions généralisées.
la source
Réponses:
Avoir un intervalle de mise à jour configurable (afin que vous puissiez modifier et essayer 5 paquets par seconde ou 20), et chaque trame voir s'il est temps d'envoyer une mise à jour. Vous pouvez être d'accord avec un jeu simple qui envoie des paquets pour chaque événement, mais dans un jeu plus complexe, ce n'est pas pratique. Gardez également à l'esprit qu'il y a une surcharge de paquets, donc si vous envoyez un tas de petits paquets, vous allez gaspiller la bande passante.
Chaque intervalle de mise à jour demande à chaque client d'envoyer sa position de palette au serveur ou à chaque client (peer-peer). Demandez au serveur d'envoyer également la position de la balle et un vecteur de vitesse. Chaque client peut exécuter le même code de dessin d'écran qu'il le fait en mode solo afin que le mouvement de la balle soit fluide. En multijoueur, vous n'avez que le serveur qui envoie les mises à jour de position / vitesse pour la balle à un intervalle régulier (et si vous le souhaitez à chaque fois qu'elle frappe quelque chose).
Faites en sorte que les mises à jour de la position des balles référencent une durée de jeu sur tous les clients afin que vous puissiez éliminer les paquets en panne et même rendre l'interpolation de la position des balles plus précise (vous connaissez la position et la vitesse à un moment précis dans le passé afin de pouvoir interpoler le nouveau position).
Avec ce modèle avec un jeu décalé, vous pouvez parfois voir la balle reculer ou sauter un peu. Mais avec une connexion décente, cela devrait être assez lisse.
la source
Concernant les problèmes de trafic - vous voulez éviter d'envoyer plus de 20-30 paquets par seconde par pair. Dans le cas général, si vous envoyez des paquets plus petits et moins nombreux, vous ressentirez (légèrement) moins de latence et une chance moindre de paquets perdus.
Vous ne voulez certainement pas envoyer les mises à jour à une vitesse plus rapide que le framerate, car les joueurs ne pourront pas faire la différence - en effet, si vous n'envoyez des paquets que 10 fois par seconde et interpolez / extrapolez les résultats du côté réception , la plupart des joueurs ne remarqueront pas de différence.
la source
C'est une question assez large, mais je vais essayer de résumer les aspects importants.
La première décision à prendre dans le code réseau de votre jeu est de savoir si vous souhaitez une configuration client / serveur d'un arrangement poste à poste. La plupart des jeux, RTS étant probablement la seule exception notable, utilisent probablement une architecture client / serveur. Le principal avantage est que cette disposition est plus tolérante aux pannes et offre plus de contrôle sur les données que chaque client reçoit. Le pair à pair permet d'envoyer beaucoup moins de données, mais nécessite que chaque pair simule entièrement le monde précisément comme tous les autres pairs. Si un pair est en retard ou se désynchronise, tout le monde doit attendre qu'il récupère ou il est simplement perdu.
UDP est généralement le bon choix également, certainement pour n'importe quel modèle client / serveur. TCP peut être pratique pour un jeu peer-to-peer, mais même alors UDP peut être un meilleur choix. Fondamentalement, UDP gère moins pour vous, ce qui signifie plus d'efforts mais aussi plus de contrôle sur la façon dont vous traitez les pannes.
Pour Pong, le choix que je ferais serait client / serveur, étant donné qu'il s'agit d'un jeu orienté vers l'action. Une chose à noter ici, même si vous dites qu'un joueur "est le serveur", il vaut mieux structurer votre code de telle sorte qu'il exécute essentiellement un serveur local et s'y connecte en tant que client.
Vous ne voulez certainement pas "spammer" les mises à jour dans n'importe quelle direction. Une mise à jour du serveur par trame suffit, et votre serveur doit fonctionner à une fréquence d'images fixe. C'est à vous de décider, mais il n'est pas nécessaire d'aller par dessus bord. Un cadre de 50 ms (20 FPS) est suffisant pour obtenir un jeu fluide et agréable. Pour garder les choses en douceur sur le client, vous souhaitez utiliser l'interpolation. Le client doit constamment effectuer la transition entre les instantanés de trame du serveur, mais cela pourrait facilement faire l'objet d'une question distincte.
Les mises à jour client devraient également être limitées, bien qu'une par image soit beaucoup trop si votre client fonctionne à une fréquence d'images décente.
la source
Vous souciez-vous de tricher?
Sinon, passer de pair à pair réduira de moitié votre décalage, car c'est A <-> C au lieu de A <-> B <-> C. Si c'est le cas, pour l'équité de la synchronisation, vous voudrez peut-être rendre la réponse quelque peu décalée pour le joueur local, ou ce que la plupart des jeux font - laissez le joueur faire quoi que ce soit localement, puis revenez en arrière si le résultat du serveur diverge du simulé localement.
Un clone de pong est en fait un peu délicat, car contrairement à la plupart des jeux, vous ne pouvez pas (en tant que développeur) tricher en ayant un côté voir un coup et l'autre pas.
En ce qui concerne quelque chose de généralisé, une technique dont j'ai entendu parler mais que je n'ai pas trouvée nécessaire (peut-être pour les jeux d'action) est de conserver les actions avec leurs horodatages réels (recevoir le temps - ping / 2), et de faire reculer le serveur ( snap) si un événement antérieur survient, puis réappliquez les actions ultérieures. De cette façon, tout le monde est cohérent localement, sauf en cas de conflit dû aux interactions des différents joueurs. Le seul danger est la possibilité de «faire reculer le temps» s'ils simulent une connexion retardée.
la source
Google estime. L'envoi de mises à jour pour 4 joueurs ne sera pas significatif. La quantité de données envoyées sera de l'ordre des octets. Donc, cela signifie que les mises à jour fréquentes devraient être correctes. Avec un calcul à l'estime, vous déplacez le joueur sur le client et le serveur. Le serveur est l'autorité. Lorsque la position du client devient trop éloignée de la synchronisation du serveur, elle doit revenir à l'alignement. http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Networking L' utilisation d'UDP est la voie à suivre. Des mises à jour seront envoyées fréquemment pour que les données perdues soient bientôt remplacées par les données entrantes de toute façon. La retransmission de paquets de TCP n'en vaut pas la peine pour la position du joueur. Consultez cet article pour plus d'informations sur la façon de garder le client et le serveur synchronisés.
la source
J'ai programmé un jeu de pong en réseau local à 2 joueurs il y a quelques semaines, voici comment je l'ai fait:
-Un côté ouvre un serveur, l'autre se connecte automatiquement -ils sont tous les deux en train de spammer leurs pagaies x position les uns contre les autres à 60 ips ou moins [UDP] -si un côté frappe la balle, ils décident de la vitesse et de la position des nouvelles balles et envoient cela à l'autre [TCP] -si le ballon vole au-delà d'une pagaie, le joueur qui l'a manquée contacte l'autre avec un message d'augmentation de score et le ballon est réinitialisé [TCP] -le ballon est simulé de façon indépendante tout le temps, ce qui convient à la physique de balle simple de pong
Cela crée environ 0,3 à 0,5 Ko / s de trafic à 60 images par seconde et les joueurs n'ont aucun retard dans leur perception, mais uniquement si le ping est en dessous d'un certain seuil, car les balles doivent être transmises à une nouvelle position.
La triche est également facile avec ce système et il y a une forte possibilité de se désynchroniser avec une connexion très perdue, mais qui se soucie de tricher en pong?!
la source