JeuWeb - Crée ton jeu par navigateur
Boucle & tick coté server NodeJS? - 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 : Boucle & tick coté server NodeJS? (/showthread.php?tid=7509)

Pages : 1 2 3 4 5 6 7 8


RE: Boucle & tick coté server NodeJS? - Argorate - 23-11-2015

La téléportation dont je parlais n'étais pas sur l'affichage du client, mais sur la réalité du serveur.

De mon point de vue, chaque tick est la réalité, il n'y a pas d'interpolation coté serveur entre deux ticks, d'où l'importance d'avoir un taux élevé.

Toi tu pars sur le principe inverse, mais comment ça se passe pour la détection de collision?
Tu me dis qu'il interpole entre t et t + Dt, mais concrètement? Il fait défiler chaque milliseconde entre t et t +Dt pour faire à chaque fois le calcule de collision?
J'imagine que non, c'est pas très performant. Du coup comment ça se passe avec ta conception ?


RE: Boucle & tick coté server NodeJS? - Xenos - 23-11-2015

Le jeu est calculé à une fréquence de 30Hz (je ne parlerai pas de "FPS" ça fait trop "affichage"). Chaque calcul génère un état du jeu X auquel est associé sa date de calcul t, donc X(t). Quand le client veut afficher le jeu, il demande l'état du jeu au serveur, qui lui répond par le X(t). Maintenant, le client veut afficher le jeu à la date t', différente de t.
Ensuite, le client attend de recevoir X(t+dt), le prochain état calculé par le serveur, et il fait alors l'interpolation entre X(t) (état passé mais récent) et X(t+dt) (état actuel), pour avoir une image affichée fluide.

Il peut aussi exister une autre approche, consistant à utiliser seulement X(t) pour prédire les prochaines positions à afficher (donc, des positions futures). Le client affiche donc X+dX. Puis, quand le client reçoit X(t+dt) (la vraie position), il refait ses prédictions en se basant sur X(t+dt) (≠X+dX). Pour éviter une saute d'image due à l'écart entre X(t+dt) et X+dX, le client peut effectuer un second lissage.
C'est plus compliqué à mettre en place, mais cela permet d'être toujours "à jour" par rapport au serveur (dans le 1er cas, bien plus simple, le client a 0 à 1/30e de seconde de retard sur le serveur, puisqu'à chaque fois qu'il reçoit X(t+dt), il affiche en pratique X(t) et fait le lissage pendant la durée dt).

Note que cette approche prédictive est adaptée aux réseaux: dans le cas de la 1ere approche, si le client ne reçoit pas X(t+dt), son affichage se freeze car il n'aura pas les points à interpoler.

Mais bon, tout cela (interpolation de l'affichage du client) est une problématique différente de celle proposée dans ton 1er message (fréquence des ticks coté serveur et calcul du monde du jeu coté serveur).


PS: Cette problématique de l'interpolation, tu ne devrais pas avoir à la traiter d'ailleurs, car si tu es sur un jeu classique, temps réel, alors tu devrais avoir un moteur/SDK qui se charge de ce travail


RE: Boucle & tick coté server NodeJS? - Argorate - 23-11-2015

Y a une vrai confusion là. je ne parle pas de l'affichage depuis t'aleur, je m'en fiche, c'est pas le sujet, les deux sont totalement disjoint. ^^

Ce dont je te parle c'est de la boucle serveur :
Si ton serveur à 3 ticks par seconde, ça veux dire que l'objet n'a que 3 paires de coordonnées par seconde, donc ça va être chaud pour les petits projectiles de toucher une cible en déplacement, c'est pour ça que plus tu augmentes le nombre de ticks serveurs, plus tu as une "netteté" qui apparait (virtuellement, pas sur les écrans, car je ne parle tjs pas de l'affichage, mais juste de la représentation mentale de la réalité incarné par le serveur).
C'est un peu comme le nombre de polygones en openGL : une sphère avec peu de polygone ne rend pas vraiment sphérique, plus tu en mets, plus ça s'affine, c'est un peu - par analogie - la même chose ici.


RE: Boucle & tick coté server NodeJS? - Xenos - 23-11-2015

Citation :Si ton serveur à 3 ticks par seconde, ça veux dire que l'objet n'a que 3 paires de coordonnées par seconde, donc ça va être chaud pour les petits projectiles de toucher une cible en déplacement
Comme dit précédemment: cf Continuous Collision Detection

Ton analogie ne fonctionne que si le modèle mathématique est un modèle de convergence, ce qui n'est pas forcément le cas dans tes calculs. Un exemple rapide: 1 tick = 1Hz, à chaque tick tu ajoutes 1.0 à un compteur. La valeur du compteur est donc similaire à un timestamp. Tu passes de 1Hz à 10.000Hz. Chaque tick ajoute 0.0001 donc. Or, d'après ce convertisseur, 0.0001 devient 9.9999997e-5 dans le type Float (car on ne peut pas y représenter tous les réels, et même certains fractionnaire n'existent pas). Du coup, affiner la fréquence de calcul ne va pas améliorer le résultat final: dans le 1er cas, après 1 an de jeu, le compteur affiche 31.536.000 alors que l'autre compteur affiche 31.535.999

Cela peut sembler négligeable, mais c'est un fait: augmenter le pas de calcul n'améliorera pas forcément ta simulation (le cas d'Eclerd est un bon exemple d'ailleurs ^^). Ce genre de problématique se posera si tu change d'ordre de grandeur dans la valeur du pas temporel (entre dt=30Hz et dt=50Hz, la différence est faible, mais entre 30hz et 100Hz, elle commence à apparaitre et à 1000Hz, t'es overkill).




Donc si je synthétise, Neoaxis est à 30Hz, Medal Of Honor: Allied Assault était à 20Hz (de mémoire), et je doute qu'aller au-delà de 50Hz soit utile. Pour avoir des calculs fiables, mieux vaut se référer à une timeline (ie: microtime). Si besoin, tu peux remplacer les calculs discrets (utilisant seulement l'état courant) par des calculs travaillant sur la continuité (CCD, utilisant donc l'état précédent et l'état courant).

PS: et l'affichage, t'en as parlé le premier, d'où le glissement.


RE: Boucle & tick coté server NodeJS? - Argorate - 23-11-2015

Les problème de flottant sont un problème HS ici.

D'où tu sors les chiffres liés aux jeux là? ça serait très intéressant de pouvoir comparer avec plus de jeux.

Sinon, c'est l'article de sephi qui en parlait, d'où mon allusion.^^


RE: Boucle & tick coté server NodeJS? - Xenos - 23-11-2015

Ben, pour Neoaxis, de la doc comme indiqué plus haut.
Pour MoH, de mon expérience perso (mais je dois pouvoir te trouver la source si cela t'amuse).

Voilà: http://www.neoseeker.com/forums/2149/t196116-console-commands/
variable console sv_fps, définie par défaut à 20.

Et la petite causerie associée (Quake III, car c'est l'engine de Medal Of Honor): http://forums.filefront.com/jedi-knight-ii-jedi-outcast-general-discussion/214168-guide-sv_fps.html (valeurs par défaut: apparemment, entre 20 et 40)


RE: Boucle & tick coté server NodeJS? - niahoo - 24-11-2015

Bon, j'ai pas tout lu, mais déjà node c'est pas méga rapide, donc si tu dois calculer des trajectoires ballistiques par exemple, il te faut un plan B. Compter sur les requêtes WS/HTTP pour recevoir la position d'une balle et d'une cible c'est pas une bonne idée je pense.

Mais sinon en gros pour formaliser ce qui a été dit :


function loop(afterMillisec){
return setTimeout(function(){
startedAt = Date()
calculateNewWorldState()
waitFor = TICK_TIME - (Date() - startedAt) // De mémoire on calcule pas les dates comme ça mais c'est pour l'exemple
loop(waitFor)
}, afterMillisec)
}

Edit :
Citation : Si besoin, tu peux remplacer les calculs discrets (utilisant seulement l'état courant) par des calculs travaillant sur la continuité (CCD, utilisant donc l'état précédent et l'état courant).

Voilà, et avec une "hitbox temporelle" pour des mouvements rapides ça peut le faire. Et comme tu parles de timeline, il faut que tous les events envoyés par les clients soient taggés avec leur timestamp pour les traiter dans l'ordre (dans la mesure du possible, en tenant compte des latences réseau -- tu ne peux pas tout traiter dans l'ordre).

Re edit : d'ailleurs, typiquement ce que je ferais c'est que pour 1 tick je trie tous mes events, et je recalcule le monde pour chacun d'eux :


events = collectClientEvents().sortBy('timestamp')
newWord = events.reduce(function(world, event) {
return word.handle(event) // renvoie un nouveau world
}, currentWorld)

Mais enfin, au final : c'est pour quel jeu ? As-tu vraiment besoin des ticks ? Ne peux tu pas modéliser côté serveur les entités comme joueur, balle, cible, etc ... et leur faire recevoir leurs évents à chacun ? Ou bien simplement utiliser un tick pour trier les events reçus par timestamp puis envoyer à chaque entité son event ?


RE: Boucle & tick coté server NodeJS? - Argorate - 24-11-2015

Il n'y a pas besoin de trier les évents, nodeJS est une pille naturelle, ça les exécutera dans l'ordre d'arrivé. Donc a moins d'habiter aux USA, je considère que la latence sera présente pour tout le monde, je trouve ça pas térrible de perdre du temps à trier, d'autant plus qu'on ne peut JAMAIS faire confiance au client, donc encore moins un chiffre qui pourrait être utiliser par un tricheur habile pour que ses actions soit tjs exécuter en premier.

Non, on utilise l'ordre naturel d'arrivé des messages webwocket, ça ce n'est pas un soucis donc. C'est aux joueurs de pas avoir de sale connexion, comme dans n'importe quel FPS, au delà de 150ms voir 100ms c'est mauvais...

Après pour la modélisation, tu présentes ici la méthode "2", c'est à dire gérer la boucle avec un setTimeout et un delta time, méthode qui ne me plait pas sur le principe, puisque par définition, le nombre de tick ne dépend plus de la volonté du créateur, mais de la vitesse de calcul du CPU de la machine qui fait tourner le programme, ce qui me semble assez mal venu.
Sans parler la très grande complexité introduite par un delta time qu'on doit se trimballer et utiliser à chaque tick, alors que si le tick est l'unité de temps, il n'y a pas a calculer le temps passé, car chaque tick est unitaire. Cette approche est bien plus intuitive et facile à mon gout.


RE: Boucle & tick coté server NodeJS? - Sephi-Chan - 24-11-2015

L'utilisation d'un delta te rend indépendant de la vitesse d'exécution des ticks. Tu ne peux pas décider arbitrairement de la vitesse d'exécution : tu peux seulement espérer que celle que tu choisiras pourra être exécuté dans les temps par ta machine. Il ne suffit pas de le déclarer pour que ça se produise.

Si tu choisis raisonnablement — en tenant compte ta machine et de la masse/complexité des traitements nécessaire pour chaque tick — tu peux faire tourner ton serveur à 30 ou 60 ticks par seconde. Tout ça nécessite des tests empiriques, à renouveler régulièrement. Le mieux est d'instrumentaliser ton code pour te remonter des informations (avec un outil comme statsd par exemple).


RE: Boucle & tick coté server NodeJS? - niahoo - 24-11-2015

La modélisation côté serveur ce n'est pas la solution 2, c'est une autre solution qui rend inutile un setTimeout ou un setInterval.

Citation :Le nombre de tick ne dépend plus de la volonté du créateur, mais de la vitesse de calcul du CPU de la machine qui fait tourner le programme, ce qui me semble assez mal venu.

Avoir son programme qui s'adapte au hardware est un énorme plus ...

Citation :Sans parler la très grande complexité introduite par un delta time
Voilà donc ensuite si tu considère une soustraction comme une très grande complexité c'est sûr que c'est pas gagné :p