JeuNet
Comment ça marche tout ça
Le principe
-
Le but est de permettre à des joueurs connectés de participer à un jeu sur le net.
-
Chaque joueur voit sa page et peut interagir en cliquant sur des boutons ou en tapant au clavier.
-
Pour cela la page de chaque navigateur doit être mise à jour constamment en fonction des actions de chacun.
-
Il faut aussi gérer quelles sont les actions autorisées pour chacun à tout moment.
-
Suivant le type de jeu il faut pouvoir permettre à un joueur de se joindre à un jeu en cours, ou de le quitter.
Facile ! Y a qu'à !
Oui mais ... comment on fait les mises à jour, qui les fait ? Est-ce le "cerveau" central sur le serveur qui gère tout ça ? Comment dire à la page de se mettre à jour ?
Précisons d'emblée que
-
le serveur ne peut pas de lui-même envoyer une info au navigateur, il ne peut que répondre à une requête de celui-ci
-
C'est au navigateur de demander s'il y a du neuf ...
-
Il lui suffit de demander inlassablement s'il y a du neuf.
-
... mais si tous les navigateurs envoient plusieurs fois par seconde des demandes de mise à jour cela risque d'énerver le serveur (ça m'est arrivé, l'hébergeur OVH a banni mon IP car je faisais trop de requêtes)
Comment j'ai fait.
J'expliquerai plus loin en détail la partie html, php et javascript.
-
Quand un joueur fait quelque chose sur son navigateur la demande est tout de suite envoyée au serveur, celui-ci la stoke, et
-
elle sera redistribuée à la prochaine demande de mise à jour de chaque client (, et tout de suite à celui qui a émis la commande).
-
les navigateurs qui recoivent la mise à jour l'exécutent à ce moment là.
-
chaque commande est datée à la micoseconde près par le serveur
-
le serveur connaît donc toujours la date de la dernière mise à jour.
-
Récapitulons: action du joueur, envoie de la commande, récupération immédiate et exécution locale.
-
Pour tous les navigateurs dès qu'ils sont en route où qu'ils viennent d'exécuter une commande ils renvoient tout de suite au serveur la question YaDuNeuf ? accompagnée de la date de la dernière mise à jour effectuée.
-
Le serveur reçoit une demande YaDuNeuf datée X,
-
si cette date X est plus ancienne que sa dernière date de mise à jour Y, il renvoie tout de suite cette mise à jour (datée Y, avec X<Y).
-
si X>=Y il attend 1 seconde et refait ce test
-
s'il ne se passe rien pendant 10 secondes il répond enfin au navigateur impatient pour lui dire rien de neuf. Le navigateur s'empresse alors de lui renvoyer une demande YaDuNeuf.
-
Avec cette solution il y a un petit délai de 1 s qui peut être introduit, le php fait sleep 1
-
Il faut aussi mettre en place un setTimeout(11000) pour le cas où le serveur ne répondrait rien au bout de 10 s par exemple.
-
Et, quand un navigateur doit envoyer une commande il avorte la requête YaDuNeuf, .. malheureusement celle-ci n'est connue du serveur que s'il envoie quelque chose sur le canal de sortie. Il en est tout flappy d'ailleurs mais bon ...
-
Les demandes YaDuNeuf doivent être envoyées sur un index2.php différent du canal normal car le php ne traite pas la commande si la précedente n'est pas terminée, or il fait de somptueux sleep dix fois de suite si rien ne se passe par action d'un autre joueur.
Implémentation
C'est en javascript surtout, avec une page de html et une pincée de php.
Le plus dur est de "penser" en se mettant à la place d'un bouton sur lequel quelqu'un appuie, n'importe quand.
Là c'est très important car une action sur un bouton déclenche toute la cascade d'événements, chez soi, mais aussi chez les autres.
Je n'ai pas encore tout à fait clair dans ma tête mais ... Que faut-il faire ?
-
vérifier que l'action est valide ... là c'est pas trop dur encore que ... il faut toujours savoir qui on est quel rôle on a, dans quel état suis-je.
-
une fois que l'action supposée du bouton a l'air valide, ... faut-il l'exécuter tout de suite locallement ou pas ? Je ne sais pas, ça dépend.
-
si on l'exécute tout de suite il faut tout mettre en oeuvre pour éventuellement ne pas la refaire plus tard (envoyer un son, déplacer un cheval, ...)
-
on peut très bien l'envoyer à tout le monde ... et exécuter en retour de mise à jour.
-
il y a juste le problème de ne pas programmer deux fois la même chose ...
Outils à télécharger
je fais du javascript et un peu de JQuery, c'est quand même pratique et plus facile à utiliser.
... mais j'ai fait mes petites fonctions hyper pratiques pour encapsuler tout ça car j'en ai eu marre de mettre des "" # + .
show(id)
hide(id)
IdOf(objet)
HtmlOf(id)
HtmlOf(Id, valeur)
HtmlOf(Classe, valeur)
ValOf(Id)
jq(X) où X est un id ou une classe
etc.
(voir packcom/Common/packcomCommon.js)
... à suivre ...
Raymond, le 1er mai 2020.