Moen
11/06/2013, 18h12
Bonjour, aujourd'hui un peu d'algo et d'optimisation, et des questions évidement.
Pour mon projet je me suis posé la question : "Comment rendre des déplacements réaliste en jeu en ligne 2D tout en réduisant fortement la complexité coté serveur et les échanges réseau?"
L'un des gros problèmes des moteurs iso à sprite, c'est que les mouvement des créatures ET des personnages sont saccadés ou robotique, en effet ils se déplacent de bloc en bloc (tiles), et pour des raisons de performance, les blocs sont généralement assez gros (~70cm de large dans T4C) Donc quand on veut légèrement se déplacer vers le haut ou le bas, on se retrouve à forcement avec un personnage qui se balade sur 70cm, le rendu n'est pas terrible. Le moyen le plus évident de rendre l'action plus fluide c'est de réduire la taille des cellules. Oui mais, dans ce cas là, coté serveur, que se passe-t-il ? Si je passe d'une structure qui gère l'état du terrain (sol, eau, boue...) de 3000*3000 à 6000*6000, ma mémoire explose, juste en doublant la précision, et tout ça pour des déplacements fluides. (pour ceux qui n'ont pas lu mon projet (ici (http://forum.canardpc.com/threads/79350-West!-the-ou%C3%A8b-mmoRPG-orient%C3%A9-Jeu-de-R%C3%B4le)) sachez que je fais du javascript histoire de me mettre des battons dans les roues de la performance!!)
C'est comme ça que fonctionne T4C, encore aujourd'hui, et c'est pas terrible (alors que c'est du bon vieux c++). Pourtant on pourrait mieux faire !
Je pose le problème en termes simples : j'ai un render engine en 3Diso (donc 2d), dans lequel je veux gérer des collisions réalistes, où les personnages auront un déplacement qui aura l'air naturel autant que se peut et le tout sans tuer les perfs du serveur, et en interdisant la triche.
La solution qui me parait la plus évidente : avoir deux échelles différentes, coté client ou coté serveur.
Coté serveur, le monde est découpé par exemple en une grille de 3000x300 cases, d'1m de coté. Ces cases peuvent représenter les collisions absolues (genre : "Rien ne traverse cette case", ou "les créatures de taille X ne passent pas", ou "les créatures volantes et les projectile des armes passent (eau toxique...)" etc ...)
Premier effet de bord, ça réduit la précision des collisions qui se retrouvent à la précision d'1m, mais on verra qu'on peut tricher pour les améliorer coté client (ça répartie la charge et le serveur suinte moins de sang pendant l'effort)
Mieux, on peut ne représenter des structures qui ne contiennent que les infos utiles. Pour les collisions, pas besoin d'un tableau de 3000x3000, mais juste un hash des cases réellement en mode collision (on met par défaut les collisions classique genre 'Sol').
Coté client maintenant, on va pouvoir tricher, en multipliant par 3 la précision des cases, déjà parce que c'est totalement virtuel, il n'y aura pas besoin de maintenir un tableau de 3000 cases², juste un jeu de coordonnées qui ira jusqu'à 9000* (https://www.youtube.com/watch?v=SiMHTK15Pik), maintenant une pression sur une touche de clavier va nous faire nous déplacer d'une unité client, donc 1/3 d'unité serveur, on se retrouve avec une précision de 33cm, c'est mieux !
Par conséquence on informe le serveur uniquement au moment de changer de cellule, donc 1/3 des déplacements se retrouvent à être validés, mais à l'écran c'est nickel. (à la louche, parce qu'il y a les déplacements diagonaux)
Problème 1 : Que faire en cas de déco/reco propre. On va stocker la position 'client' de l'utilisateur au moment de la déco, et au moment de la reco on valide la position client par rapport à la position serveur (pour éviter le cheat!), si on est dans la même tranche de division sur une case (serveur) qui n'est pas en collision, c'est vendu.
Problème 2 : que faire en cas de crash coté client. On aura pas l'info coté client, ou une info qui sera erronée. Dans ce cas c'est l'information coté serveur qui dictera le comportement, on aura un personnage qui aura légèrement bougé, mais au final pas de grand malheur. (idem pour ceux qui tenteraient de tricher en envoyant n'importe quoi comme coord)
Problème 3 : le serveur crashe, dans ce cas time warp, on se retrouve là où le serveur à sauvé pour la dernière fois, c'est con mais j'ai pas de bonne idée pour éviter la triche.
Bon, c'est bien sympas tout ça mais on a toujours pas de collision au pixel. En effet, mais là encore on peut gruger visuellement coté client!
Un perso peut marcher sur une case 'collision', mais ne peux pas atteindre une case au delà de la case de collision, en fait il ne peut pas la traverser. C'est subtil mais ça permet de faire effet sympas. Bien sur le serveur verra toujours l'utilisateur sur une case sans collision. On peut faire une collision autour d'un arbre tout en laissant les joueurs frôler le tronc
Pour plus de réalisme maintenant il faudrait conserver l'orientation d'une créature. (pour des compétences de discrétions ou autre), mais c'est une autre histoire !!
Des idées pour améliorer mon algo ?! Vous voyez un endroit où ça peut coincer ?! Ou même un meilleur algo pour gère les mêmes problématiques.
N'oubliez pas que je le fais pour répondre à mes contraintes (2D, javascript...) il y a des choses bien plus malignes à faire avec des langages compilés memory safe, mais je ne peux pas compter dessus vu que je ne contrôle pas 100% de ma mémoire ^^
Pour mon projet je me suis posé la question : "Comment rendre des déplacements réaliste en jeu en ligne 2D tout en réduisant fortement la complexité coté serveur et les échanges réseau?"
L'un des gros problèmes des moteurs iso à sprite, c'est que les mouvement des créatures ET des personnages sont saccadés ou robotique, en effet ils se déplacent de bloc en bloc (tiles), et pour des raisons de performance, les blocs sont généralement assez gros (~70cm de large dans T4C) Donc quand on veut légèrement se déplacer vers le haut ou le bas, on se retrouve à forcement avec un personnage qui se balade sur 70cm, le rendu n'est pas terrible. Le moyen le plus évident de rendre l'action plus fluide c'est de réduire la taille des cellules. Oui mais, dans ce cas là, coté serveur, que se passe-t-il ? Si je passe d'une structure qui gère l'état du terrain (sol, eau, boue...) de 3000*3000 à 6000*6000, ma mémoire explose, juste en doublant la précision, et tout ça pour des déplacements fluides. (pour ceux qui n'ont pas lu mon projet (ici (http://forum.canardpc.com/threads/79350-West!-the-ou%C3%A8b-mmoRPG-orient%C3%A9-Jeu-de-R%C3%B4le)) sachez que je fais du javascript histoire de me mettre des battons dans les roues de la performance!!)
C'est comme ça que fonctionne T4C, encore aujourd'hui, et c'est pas terrible (alors que c'est du bon vieux c++). Pourtant on pourrait mieux faire !
Je pose le problème en termes simples : j'ai un render engine en 3Diso (donc 2d), dans lequel je veux gérer des collisions réalistes, où les personnages auront un déplacement qui aura l'air naturel autant que se peut et le tout sans tuer les perfs du serveur, et en interdisant la triche.
La solution qui me parait la plus évidente : avoir deux échelles différentes, coté client ou coté serveur.
Coté serveur, le monde est découpé par exemple en une grille de 3000x300 cases, d'1m de coté. Ces cases peuvent représenter les collisions absolues (genre : "Rien ne traverse cette case", ou "les créatures de taille X ne passent pas", ou "les créatures volantes et les projectile des armes passent (eau toxique...)" etc ...)
Premier effet de bord, ça réduit la précision des collisions qui se retrouvent à la précision d'1m, mais on verra qu'on peut tricher pour les améliorer coté client (ça répartie la charge et le serveur suinte moins de sang pendant l'effort)
Mieux, on peut ne représenter des structures qui ne contiennent que les infos utiles. Pour les collisions, pas besoin d'un tableau de 3000x3000, mais juste un hash des cases réellement en mode collision (on met par défaut les collisions classique genre 'Sol').
Coté client maintenant, on va pouvoir tricher, en multipliant par 3 la précision des cases, déjà parce que c'est totalement virtuel, il n'y aura pas besoin de maintenir un tableau de 3000 cases², juste un jeu de coordonnées qui ira jusqu'à 9000* (https://www.youtube.com/watch?v=SiMHTK15Pik), maintenant une pression sur une touche de clavier va nous faire nous déplacer d'une unité client, donc 1/3 d'unité serveur, on se retrouve avec une précision de 33cm, c'est mieux !
Par conséquence on informe le serveur uniquement au moment de changer de cellule, donc 1/3 des déplacements se retrouvent à être validés, mais à l'écran c'est nickel. (à la louche, parce qu'il y a les déplacements diagonaux)
Problème 1 : Que faire en cas de déco/reco propre. On va stocker la position 'client' de l'utilisateur au moment de la déco, et au moment de la reco on valide la position client par rapport à la position serveur (pour éviter le cheat!), si on est dans la même tranche de division sur une case (serveur) qui n'est pas en collision, c'est vendu.
Problème 2 : que faire en cas de crash coté client. On aura pas l'info coté client, ou une info qui sera erronée. Dans ce cas c'est l'information coté serveur qui dictera le comportement, on aura un personnage qui aura légèrement bougé, mais au final pas de grand malheur. (idem pour ceux qui tenteraient de tricher en envoyant n'importe quoi comme coord)
Problème 3 : le serveur crashe, dans ce cas time warp, on se retrouve là où le serveur à sauvé pour la dernière fois, c'est con mais j'ai pas de bonne idée pour éviter la triche.
Bon, c'est bien sympas tout ça mais on a toujours pas de collision au pixel. En effet, mais là encore on peut gruger visuellement coté client!
Un perso peut marcher sur une case 'collision', mais ne peux pas atteindre une case au delà de la case de collision, en fait il ne peut pas la traverser. C'est subtil mais ça permet de faire effet sympas. Bien sur le serveur verra toujours l'utilisateur sur une case sans collision. On peut faire une collision autour d'un arbre tout en laissant les joueurs frôler le tronc
Pour plus de réalisme maintenant il faudrait conserver l'orientation d'une créature. (pour des compétences de discrétions ou autre), mais c'est une autre histoire !!
Des idées pour améliorer mon algo ?! Vous voyez un endroit où ça peut coincer ?! Ou même un meilleur algo pour gère les mêmes problématiques.
N'oubliez pas que je le fais pour répondre à mes contraintes (2D, javascript...) il y a des choses bien plus malignes à faire avec des langages compilés memory safe, mais je ne peux pas compter dessus vu que je ne contrôle pas 100% de ma mémoire ^^