Not So Advance Wars, un jeu de stratégie en ligne pour une game jam
#1
Hello !

Me revoilà avec un jeu de game jam ! Cette fois on se rapproche de JeuWeb puisque c'est un jeu multijoueur en ligne... Il s'agit de Not So Advance Wars, un clone du jeu Advance Wars sur Game Boy Advance. C'est en téléchargement sur la page itch.io du projet.

Le client est codé en Lua avec le moteur LÖVE, et le serveur en Elixir. Comme d'habitude, tout est sur GitHub : le client et le serveur.

[Image: xAinDy.gif]

Je n'avais jamais travaillé avec les sockets (en l'occurrence TCP) et ça n'a donc pas été facile de mettre le pied à l'étrier. Le processus de développement était assez laborieux puisque je testais avec deux ordinateurs. Je n'ai pu travailler que la dernière semaine de la jam : il y a donc 7 jours de travail acharnés derrière tout ça, à environ 10 heures par jour. Vive les vacances scolaires pour les enseignants !

La mise en production du serveur a été triviale grâce à Distillery. Cet outil crée des exécutables à partir des sources Elixir et qui permettent de lancer le jeu en background, en foreground ou bien en foreground avec une console interactive (pour pouvoir surveiller ce qui se passe, intervenir, se rajouter de l'argent).

Le jeu fonctionne sans base de données : tout est stocké en mémoire le temps de la partie, et la liste des joueurs connectés et des lobbies ouverts est stockée en mémoire pour toute la durée d'exécution du serveur. Elixir permet de lancer des "processus" qui tournent simultanément et attendent des messages. En l'occurrence ici j'en ai 3 : un qui gère les joueurs connectés (il maintient une liste au gré des connexions/déconnexions), un qui gère les lobbies (pareil, il maintient une liste des lobbies ouverts, les ferme quand un joueur quitte ou que la partie pour ce lobby démarre) et enfin un process pour chaque partie lancée, qui reste ouvert jusqu'à la fin de cette partie.

Côté Lua, j'aime toujours la simplicité du langage mais je m'exaspère de la pauvreté de sa librairie standard et de son écosystème. Je pense changer bientôt de techno, sans doute au profit du langage Haxe et de l'un de ses nombreux moteurs.

Le jeu fonctionne essentiellement avec des machine à état : l'app est une machine à états avec un état par écran : l'écran principal avec les joueurs connectés et les parties, l'écran qui affiche la partie en cours et l'écran de cinématique de combat. Chacun de ces écrans est également une machine à états. Et enfin dans la cinématique de combat, le background et chaque unité affichée est une machine à états également ! Cela m'a permis d'organiser assez facilement le déroulement d'un combat (et donc son animation).

Je vous attends sur le jeu !
Répondre
#2
Quel boulet, j'ai oublié de laisser le lien pour télécharger les exécutables ! 

https://sephi-chan.itch.io/not-so-advance-wars

Pour les gens sous Windows, il faut télécharger la version ZIP qui contient un dossier à extraire, il faut exécuter le fichier not_so_advance_wars.exe qui est dedans.

Pour ceux sous macOS, il y a un fichier not_so_advance_wars.app exécutable directement.

Pour ceux qui sont sous Linux, il faut installer LÖVE en amont, ce qui permet de télécharger et d'exécuter le fichier not_so_advance_wars.love.
Répondre
#3
Woah c'est classe. Tu kiffes Elixir hein ?

Est-ce que tu peux détailler rapidement l'archi du jeu pour la connexion, la partie, le lobby (gen_server tout ça) ?
Répondre
#4
J'adore ! C'est tellement cool d'imaginer que son serveur "vit", plutôt que de penser en requête/réponse qui charge les informations et les décharges aussitôt.

J'utilise la librairie Erlang Ranch pour accepter les connexions TCP entrantes. Ça spawn un process tcp_handler par connexion active. Tous les messages échangés sont encodés en JSON. C'est pas forcément optimal en terme de volume de données, mais ça me semble sans importance compte tenu du faible nombre d'échanges.

Une fois connecté, le client envoie un message au serveur dans lequel il s'identifie par un UUID. Quand le handler TCP reçoit ce message, il l'indique au process GenServer players qui stock une liste des joueurs connectés. On push aux autres clients. Quand la connexion est coupée, le process est notifié et vire le joueur de la liste (et on en informe aussi les autres clients).

De la même manière, quand le handler TCP reçoit le message pour ouvrir un lobby, le GenServer lobbies est notifié et le stock dans une map qui associe un UUID de lobby a une map contenant quelques infos. Le joueur sera le joueur 1 de la partie à venir. Si la connexion coupe, on vire le lobbies de la liste. A nouveau, on notifie les autres clients.

Quand un joueur envoie le message pour rejoindre un lobby, on fait quelques tests (le lobby existe-t-il ? est-ce que c'est pas un joueur qui tente de rejoindre le lobby qu'il a créé…) puis on crée la partie grâce au process GenServer Games. Un process GenServer Game est alors créé sous un superviseur (il y en a un par partie en cours). Le PID du process est stocké dans un Registry avec l'UUID de la partie comme clé (l'intérêt est que le Registry est automatiquement nettoyé quand le process de la partie est terminé). Le deuxième joueur arrivé devient le joueur 2 de la partie. Les deux joueurs sont notifiés du démarrage de la partie. Chaque process contient les informations de sa partie.

Ensuite, chaque message qui arrive au TCP handler et qui concerne le jeu est géré (déplacement d'unité, attaque, fin de tour, etc.) jusqu'à ce qu'une attaque mette fin à la partie. L'identité du gagnant est envoyé avec les résultats du combat et le processus est arrêté.

Voilà pour le cycle de vie !

Là je suis en train de faire un Risk en CQRS/Event Sourcing (avec Commanded) et c'est fun. Peut-être que je ferais le client si le développement du serveur se passe bien. 2
Répondre
#5
Cool merci. J'ai l'impression que tu n'utilises pas de FSM ce coup-ci. N'y-a-t'il pas des cas ou un joueur pourrait envoyer un message inattendu ? Par exemple un ordre d'attaque alors que ce n'est pas à son tour ? Comment gères-tu ce cas ?
Répondre
#6
L'autre fois je n'avais pas été très satisfait de la FSM, j'avais l'impression d'avoir peu d'états, et un état énorme. Là j'y suis allé plus bêtement : je fais des tests. :p

C'est pas le plus élégant mais ça a bien fonctionné. 2

Par contre côté client en Lua j'ai des FSM partout ! Une qui pilote l'app, une pour chaque écran (menu, map et animation de combat). Dans l'animation de combat j'ai une FSM pour le fond et une pour chaque unité affichée. Ça marche trop bien !
Répondre
#7
pour les gars qui ... comme moi...

;-)

Citation :FSM est un sigle, qui signifie : FSM est un code, qui signifie : selon la norme ISO 3166-1 (liste des codes pays), les États fédérés de Micronésie ont pour code alpha-2 FM ;selon la liste des codes pays utilisés par l'OTAN, les États fédérés de Micronésie ont pour code alpha-3 MSN ;selon la liste des codes pays utilisés par l'OTAN, les États fédérés de Micronésie n'ont pas de code alpha-2 ;
[WIP]projet Rivages
[WIP]projet Arthur (comme si ça suffisait pas d'un...)
Répondre
#8
Pardon ! :p
Répondre
#9
Haha
Répondre
#10
Je l'ai téléchargé mais je n'ai pas encore pu y jouer : au début parce qu'il fallait rajouter une règle pour mon pare-feu au niveau de Löve alors que je l'avais rajouté bêtement sur le faux .exe, et ensuite parce que je suis seul sur le serveur (91152).

Ça reste assez impressionnant, tout de même, d'avoir proposé du jeu en réseau pour une Jam (avec un client en Lua !).
Répondre


Sujets apparemment similaires...
Sujet Auteur Réponses Affichages Dernier message
  Spherium, un jeu codé pour une game jam Sephi-Chan 18 1 778 12-14-2018, 10:19 PM
Dernier message: Sephi-Chan



Utilisateur(s) parcourant ce sujet : 1 visiteur(s)