JeuWeb - Crée ton jeu par navigateur
Le temps dans un jeu sur navigateur - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Le temps dans un jeu sur navigateur (/showthread.php?tid=7470)



Le temps dans un jeu sur navigateur - OursGroumy - 15-10-2015

Bonjour à tous.

Je suis actuellement entrain de travailler sur un projet avec un ami. Nous nous sommes donnés comme idée de faire un jeu sur navigateur, il ressemblerait sur certains points a un Ogame ou Travian. Mais nous voulons développer un jeu un peu plus tactique.

Nous sommes parti sur l'idée de développer en PHP avec Symfony2.

Pour donner une idée de notre niveau, nous sommes étudiants en master informatique. Nous n'avons pas une grande expérience dans le Web (seulement des projets perso), mais une bonne connaissance des concepts informatiques.

L'idée est que chaque joueur puisse posséder des flottes (de bateaux). Et affecter des missions à ses flottes (Comme se déplacer, attaquer, transporter, patrouiller ...).
Chaque actions prenant un temps variable pouvant aller a plusieurs heures.
La carte sur laquelle ils évoluent est une grille de case d'eau ou de terre (un bateau ne se déplaçant que sur l'eau ...). Et les cases de terre peuvent être occupées par des forts ou des villes.
Un bateau ou un fort possède une zone de contrôle qui représente les cases qu'il peut protéger. Si un bateau patrouille et qu'un bateau ennemi rentre dans sa zone de contrôle, il y a combat.
Nous tenons vraiment a implémenter ce principe car le jeu se baserait beaucoup sur l'attaque et la défense de certains point (convois, villes ...).

Notre problème est le suivant. Imaginons que 2 joueurs soient adversaire. j1 envoi sa flotte en un point A. J2 envoi la sienne en un point B. Ces deux actions vont prendre un certain temps. Les deux joueurs se déconnectent et il ne reste plus aucun joueur de connecté sur le serveur (et plus de requêtes PHP envoyés au serveur).
Seulement les deux flottes se croisent en un point C et devraient se battre. Comment détecter cette rencontre ?
Je vois deux solutions.

Une qui m'a été matraqué a chaque fois que j'ai parlé de ce problème, mais qui ne me semble pas bonne :
_Calculer les collisions à l'avance et les résoudre lorsqu'une requête est envoyée au serveur.
Seulement cela demande de stocker toutes les collisions possible. Si on imagine que la flotte du J1 interceptée par un autre bateau (appelons le J3). Alors deux possibilité. Soit la flotte de J1 gagne, et alors elle continue et rencontre la flotte de J2. Soit elle perd et c'est celle du J3 qui continue sa route. Et ira pourquoi pas rencontrer d'autres flottes.
Cela demanderait d’implémenter un arbre des possibilités. Et de le faire résoudre lorsqu'une requête est envoyée au serveur. Ce qui voudrait dire qu'une requête lambda envoyée par un joueur devrait faire résoudre tout l'arbre. Ca ne me semble pas être une bonne idée.

_Un mécanisme qui permettrait de faire tourner une boucle infinie sur le serveur dans laquelle on résous les positions et les événements. Seulement je ne vois pas comment l’implémenter. Cela voudrait dire qu'il tourne sur le serveur sans qu'il n'y ait de requêtes PHP.
Seulement je ne sais pas du temps comment implémenter ça. Ni même si c'est possible en utilisant PHP.

_Un timer qui envoi régulièrement l'ordre au serveur de remettre a jour les positons et de résoudre les événements. Là encore je ne sais pas si c'est implementable (vu qu'aucune requête ne vient verifier que le timer s'est écoulé

Ce problème est une grosse barrière a l'avancement de notre projet. Et je serai très reconnaissant si vous pouviez m'éclairer. Parce que j'avoue que personnellement je patauge ... J'en appelle donc à votre expérience des jeux sur navigateurs.


RE: Le temps dans un jeu sur navigateur - Thêta Tau Tau - 15-10-2015

Je pense qu'il est indispensable pour tout jeu web un minimum complexe, d'avoir un moyen de gérer les événements indépendamment des requêtes.

Perso j'y ai pas mal réfléchi pour mon jeu. Je compte implémenter ce "gestionnaire d'événements" très prochainement, je posterait peut être quelque chose à l'occasion.

Niveau technologies j'utilise node. Je compte faire un truc basé sur setTimeout, avec un cache dans la bdd pour pas tout perdre en cas de crash du serveur.
En gros :
-Lors de l'ajout d'un évènement on ajoute une entrée dans la bdd et on lance un setTimeout.
-le setTimeout appelle une fonction qui fait l'action et supprime l'entrée dans la bdd.
-au démarrage du serveur on récupère tous les événements dans la bdd, on résout les événements passés (dans l'ordre) et on lance les setTimeout des événements futurs.
Après il y a deux trois soucis d'optimisation à prendre en compte mais en gros c'est l'idée.


Du coup appliqué à ton cas, on appellerait une fonction à chaque fois qu'il faudrait déplacer une flotte d'une case. Ce script se chargeant du déplacement, des collision, et des combats.


RE: Le temps dans un jeu sur navigateur - Xenos - 15-10-2015

L'attente active (boucle qui tourne en continue et teste ce qu'il faut faire) est souvent une solution bancale car sur-consommatrice de puissance.
Lancer le calcul à la réception d'une requête pose un soucis d'expérience utilisateur: le premier connecté va attendre, parfois plusieurs minutes façon Eclerd, avant de voir la page. Envoyer la page, déconnecter le client, puis calculer n'est pas non plus envisageable (le client reçoit des données périmées car le calcul s'est lancé après).
L'approche prédictive présente le problème que t'as exposé: le calcul N peut influencer le calcul N+1 dont la prédiction devient fausse.

L'alternative usuelle est un Cron Job, qui toutes les heures ou moins (ou plus) va lancer un script PHP qui effectuera les calculs à faire. On peut avoir une "stack" listant ces calculs dans la BDD. Ovh propose une interface pour cela, dans son manager. Sinon, il existe du tuto web. C'est pas complexe: on a un fichier lu par Linux dans lequel on indique les fréquences d'exécution d'un fichier donné (script PHP par exemple, ou commande MySQL).
C'est cette approche que j'utiliserai.

On peut quand même lancer le calcul lors de la réception de la requête si ce calcul est focalisé sur le joueur. Par exemple, pour la prochaine version d'eclerd, la planète entière sera régulièrement recalculée en hors-ligne (via le cron), mais je peux recalculer le pays du joueur (ou un morceau) à chaque requête qu'il envoie, pour qu'il ait des informations hyper-dynamiques (toujours à jour). Cela complexifie un peu les choses car au lieu d'avoir une seule date de dernière simulation pour tout le serveur (sauvée en BDD), j'ai une date de dernière simulation pour chaque usine (stockée aussi en BDD), mais je pense que cela vaut le coup.


Après, il ne faut pas oublier que PHP est un veau (tout langage client sera lent d'ailleurs). Ce genre de simulation consiste souvent à faire de la simple manipulation de données, donc je conseillerai de la faire en MySQL, ou dans tout autre langage de BDD que tu utilises. Pour ma part, la v0 d'Eclerd faisait le calcul de simulation en lisant les données de la base, en les récupérant dans PHP, en caclulant dans PHP, puis en mettant la BDD à jour. C'est très très lent. Depuis que je suis passé par de la procédure SQL, j'ai divisé le temps par 100 voire plus. Donc une ou plusieurs procédures SQL de simulation, lancées par un CRON, devraient être suffisante (les calculs n'ont pas l'air complexes dans ce jeu).


RE: Le temps dans un jeu sur navigateur - Akira777 - 15-10-2015

Pour ma part, j'intégrerai une interface Node.js entre ton client et ton serveur qui viendrait faire office de super tâche CRON en temps réel sur ces évenements.

Elle aurait uniquement pour rôle le tampon entre client et serveur, n'exécuterai pas de code métier mais écouterai et enverrai des requêtes à ton API REST sur Symfony.

Pour ma part, j'aime beaucoup implémenter cette techno pour donner une impression de temps réel sur un jeu qui ne l'est pas du tout : combat tour par tour, évenement, marché d'item, raid surprise, ...