Synchronisation des mouvements basée sur les tuiles multijoueurs

8

Je dois synchroniser le mouvement de plusieurs joueurs sur Internet et j'essaie de trouver le moyen le plus sûr de le faire.

Le jeu est basé sur des tuiles, vous ne pouvez vous déplacer que dans 4 directions, et chaque mouvement déplace le sprite 32px (au fil du temps bien sûr). Maintenant, si je voulais simplement envoyer cette action de déplacement au serveur, qui la diffuserait à tous les joueurs, pendant que la touche de marche est maintenue enfoncée, pour continuer à marcher, je dois prendre cette prochaine commande, l'envoyer au serveur, et à tous les clients, à temps, ou le mouvement ne sera plus fluide. J'ai vu cela dans d'autres jeux, et cela peut devenir moche assez rapidement, même sans décalage. Je me demande donc si c'est même une option viable. Cela semble être une très bonne méthode pour un seul joueur, car c'est facile, simple (il suffit de prendre l'action de mouvement suivante à temps et de l'ajouter à une liste), et vous pouvez facilement ajouter des mouvements de souris (en cliquant sur une tuile), pour ajouter un chemin d'accès à une file d'attente, c'est parcouru.

L'autre chose qui m'est venue à l'esprit était d'envoyer l'information que quelqu'un a commencé à se déplacer dans une certaine direction, et encore une fois qu'il a arrêté ou changé la direction, ainsi que la position, de sorte que le sprite apparaisse à la bonne position, ou plutôt pour que la position peut être fixée en cas de problème. Cela devrait (espérons-le) ne poser des problèmes que si quelqu'un est vraiment en retard, auquel cas il faut s'y attendre. Pour que cela fonctionne, j'ai besoin d'une sorte de file d'attente, où les changements de direction entrants et les trucs sont enregistrés, afin que le sprite sache où aller, une fois le mouvement actuel vers la tuile suivante terminé. Cela pourrait réellement fonctionner, mais semble un peu trop compliqué. Bien que ce soit la seule façon de le faire, sans risque de bégaiement. Si un changement d'arrêt ou de direction est reçu du côté client, il ' s enregistré dans une file d'attente et le caractère continue de se déplacer vers les coordonnées spécifiées, avant de s'arrêter ou de changer de direction. Si la nouvelle commande arrive trop tard, il y aura aussi du bégaiement bien sûr ...

J'ai du mal à décider d'une méthode, et je n'ai pas encore vraiment trouvé d'exemples pour cela. Mon principal problème est de garder le mouvement des tuiles en douceur, c'est pourquoi d'autres sujets concernant la synchronisation des mouvements basés sur les pixels n'aident pas trop.

Quelle est la manière "standard" de procéder?

Mars
la source

Réponses:

4

Je suppose que vous parlez de bouger en temps réel. Essayer d'interpoler la position est probablement une cause perdue; sur une connexion lente, votre état de jeu pourrait tomber de plus en plus derrière l'état de jeu réel. Contrairement à l'autre commentaire, je déconseille de mettre beaucoup de logique de jeu côté serveur. Lorsque j'ai implémenté ce type de solutions, le client a constamment un socket TCP sur le serveur. Lorsque l'état du jeu change, il envoie un message au serveur, comme «le client est à x = 10, y = 20». Le serveur envoie le message aux autres clients, qui essaient de le gérer en fonction de leur propre logique interne. L'utilisation de TCP garantit que vos messages arrivent dans l'ordre.

Malheureusement, même les jeux AAA ne peuvent pas supporter un décalage extrême; les joueurs se déplacent parfois très rapidement, car leurs états local et réseau sont loin de se détraquer. Surveiller le ping aller-retour et donner des coups de pied aux utilisateurs qui sont trop lointains / lents aidera à cela.

Alan Gardner
la source
1
+1 pour "même les jeux AAA ne peuvent pas supporter un décalage extrême;" En fait, personne ne peut gérer parfaitement même les petits retards. Nous pouvons cependant donner l'impression que nous le pouvons.
Valmond
3

Fondamentalement, voici comment vous pouvez le faire de manière simple et sécurisée (avertissement, pseudocode extrême):

A) Le client (playerid = 5) demande au serveur de se déplacer vers la droite (ou mieux, vers la tuile 73,18)

B) Le serveur vérifie sa grande carte 2D qui contient des joueurs (ou ID joueurs par exemple):

 if(map[73][18] == occupied)
     Send back ('Not OK') to client (the case is blocked by another player)
else
    Set the new position as blocked: map[73][18]=5
    Release the old position: map[72][18]=0;
    Send a 'new position: 5, 73,18' message to all players who are nearby (moving client included)

C) Les clients reçoivent un message «nouvelle position» (enfin, ou le joueur 5 reçoit le message «Pas OK»)

D) les clients déplacent lentement l'élément qui a playerid = 5 vers sa nouvelle position (ou le crée s'il n'a pas un élément avec playerid = 5)

Valmond
la source
Eh bien, merci, mais mon problème est de le garder en douceur sur les autres clients sur plusieurs mouvements de tuile continus, pas le mouvement de tuile en général ^^
Mars
Réglez la vitesse correctement et compensez le décalage avec par exemple un calcul mort ou simplement un mouvement `` stupide '' vers la cible à vitesse constante '' (ou une vitesse proportionnelle sur un certain trésor si vous envoyez des horodatages le long des positions) et ça devrait aller.
Valmond
1

Je pense que la méthode que vous avez décrite est plutôt bonne, surtout dans un jeu simpliste où seulement 4 coups sont autorisés. Voici comment je l'ai implémenté.

Je ne connais aucune norme, mais la première chose qui m'est venue à l'esprit était de ne diffuser que les «changements d'entrée», les changements dans l'entrée d'un joueur, d'un joueur aux autres. Par exemple, vous pouvez diffuser uniquement des messages du type [touche enfoncée, ID clé, heure] ou [touche relâchée, ID clé, heure], et laisser le jeu des joueurs agir en fonction de ces modifications d'entrée. L'inclusion du temps aidera à la correction du chemin (si le joueur a changé de direction au temps t, alors "aller de l'avant" au temps t + 1 devra être fixé).

Cependant, avec cette solution, vous pouvez rencontrer le problème des messages perdus; supposez que le message "clé libérée" n'a jamais été envoyé? Quelque chose qui peut aider cela consiste à interroger périodiquement l'état de jeu d'un joueur et à renvoyer la position actuelle du joueur, ainsi que n'importe quelle touche enfoncée, ou même à retourner l'état de jeu entier. En fonction du nombre de joueurs et de commandes, vous pouvez le modifier afin d'équilibrer le message passant entre clients / serveur pour un bon équilibre.

Vous pouvez également étudier la planification de parcours. Par exemple, si le joueur avance depuis 5 secondes, alors dans les millisecondes suivantes, il est possible que le joueur continue d'avancer. Dans ce cas, vous pouvez créer un semblant de prédiction de chemin afin d'éviter le décalage. C'est essentiellement ce que fait la méthode ci-dessus, bien que cela puisse prendre en compte les chemins circulaires.

J'espère que cela a aidé!

Jonathan Pitre
la source
1
Le problème avec simplement l'envoi d'entrées est que si vous en manquez une seule ou parfois les interprétez simplement dans le mauvais ordre, votre état de jeu ne sera plus correct, c'est-à-dire. deux clients afficheront différents «écrans».
Valmond
@Valmond très bon point ... en fait, j'ai envie de supprimer ma réponse, car dans cette lumière, elle semble incorrecte.
Jonathan Pitre
1
Vous pouvez envoyer les entrées au serveur (jusqu'à ce que ce soit OK) mais le serveur doit (IMO) envoyer des données exactes ou au moins vérifier les données ou peut-être envoyer tout l'état du jeu (cela a été fait dans de vrais jeux par exemple Blood Bowl ), vous pouvez peut-être modifier votre réponse au lieu de la supprimer :-)
Valmond