Je vais couper court: nous n’allons pas parler code dans cet article. Nous allons parler de tout le reste !
Pour mettre un peu de contexte: j’avais besoin d’un side project (comme n’importe quel dev quoi) et je voulais retoucher à du mobile depuis un moment. J’ai donc décider de me lancer dans un jeu mobile multijoueur.
Le concept
J’avais déjà eu l’idée de ce jeu pour la fin de stage d’un certain MP qui se reconnaîtra, il nous fallait quelque chose de simple mais drôle et efficace. On a donc décidé de piocher dans ce qui existait déjà et de le revisiter légèrement.
Nous avons donc décider de partir sur un système dans lequel un joueur peut créer une salle et y inviter des amis. Puis des rounds s’enchaînent au cours desquels des bouts de phrases sont proposés et chaque joueurs doivent les compléter en étant le plus drôle possible. Un peu comme Limite-Limite mais avec possibilité de remplir soi-même les phrases et non avec des cartes.
Les technos
Je voulais faire du mobile et je voulais travailler un peu avec du socket (ça me manquait). Pour l’API je suis donc parti sur quelque chose de simple et que je maîtrisais suffisamment: Symfony 5. Comme ça l’API serait une partie facile et je pourrai vraiment me concentrer sur les deux aspects que je voulais travailler en priorité.
Pour le front, je connaissais déjà React Native mais je n’y avais pas touché depuis un moment, et mes connaissances restaient limitées. Comme je ne voulais pas faire du natif directement ce choix me paraissait cohérent pour apprendre quelque chose au cours de se projet. J’ai hésite avec du Flutter mais j’ai laissé ce choix à mon prochain projet.
Pour les sockets quelques choix s’offraient à moi et après un rapide benchmark, je suis parti sur Socket.IO pour profiter du système de room intégré. Et ses performances restent très bonnes à grande échelle.
Pour stocker les images je suis parti sur un S3 pour pouvoir migrer le back facilement en cas de souci.
La stack était définie, il fallait maintenant s’y mettre !
La structure de données
J’ai décidé de commencer par l’API, le plus simple en soi et histoire de pouvoir ensuite construire chaque vue de l’application sans avoir à y revenir pour tout rebrancher. J’ai donc déjà défini le modèle de données suivant:
Prenons juste la partie jeu pour simplifier: les Users créent et se rejoignent dans une Room. Une fois le jeu lancé, on crée une série de Rounds. Chaque Round est associé à une Sentence. La Sentence représente la phrase à remplir proposée lors de la partie. Chaque User peut alors envoyer une Proposal, une proposition de réponse. À la fin du round, les joueurs peuvent alors voter pour leur Proposal préféré.
Le coeur du jeu: le socket
Étant un jeu mobile multijoueur, l’application devait pouvoir fournir l’état du jeu en direct à chaque joueur. Avertir quand tout le monde a rempli, faire bouger tout le monde entre les différents écrans, … Deux façons de faire s’offrent alors: un refresh toutes les secondes ou du socket. Pour des raisons évidentes, je suis parti sur des sockets.
Notre serveur va avoir plusieurs actions:
- Pouvoir créer une salle pour un admin
- Pouvoir rejoindre une salle
- Pouvoir quitter une salle
- Pouvoir démarrer la partie
- Pouvoir envoyer les informations du round à tous les utilisateurs
- Prévenir qu’un utilisateur a rempli sa phrase (pour avoir un indicateur genre « 3/4 ont rempli leur phrases »)
- Pouvoir récupérer toutes les phrases
- Pouvoir voter
- Obtenir les résultats finaux
- Pouvoir kick un joueur
Il faut également réussir à gérer correctement les déconnexions/reconnexions, surtout quand l’admin se déconnecte. Mais globalement la grosse partie de la reconnexion peut se faire côté appli.
Dans l’idée, pour limiter le poids d’utilisation de notre serveur, seules 3 infos seront stockées: un booléen qui indique si je suis admin ou non, le code de notre room actuelle et la liste des utilisateurs.
Histoire de gagner du temps, je me suis servi de la gestion built-in des rooms dans soket.io. Ce qui me permet avec un simple bout de code d’envoyer un message à tous les utilisateurs :
socket.to(`room:${room}`).emit(/* Something */);
Ceci étant fait, il fallait développer l’app !
L’application
Comme dit plus haut, Polincorrect est développé en React Native. Je suis parti d’un template vide pour cette fois plutôt que de m’entraîner sur un boilerplate (mais ça viendra, promis).
Les points importants à travailler étaient les suivants:
- Avoir un design amusant et dynamique
- Gérer la connexion et les calls sécurisés
- Pouvoir gérer les sons (musique, clics sur des boutons)
- Gérer les sockets proprement (détection des déconnexion, …)
Et bien entendu, pouvoir avoir un affichage le plus fidèle possible entre iOS et Android !
Sans trop de surprise, la partie la plus longue a été la partie « jeu ». Le reste étant purement de la gestion de formulaires et d’affichages. J’ai quand même craqué pour une flopée de packages pour aller plus vite (pour gérer par exemple l’asyncstorage, les sons, les animations, l’image-picker, …). Quitte à être sur du Node, autant en profiter !
Vivons dans notre temps: le design
Je ne suis pas designer. Ça n’est pas un scoop ! Mais je voulais quand même quelque chose d’original et de pas moche. Et comme nous étions au début du projet en 2022, les joies de la technologie m’ont permis de demander un design à MidJourney ! Ce qui m’a donné ceci:
Celui en haut à droite me tentant bien, mais il n’était pas très précis. Donc je suis allé demander à Dall.E de nouvelles suggestions depuis cette image. Et j’ai obtenu ceci:
Mieux non ? En terme de couleurs et de personnages. J’ai donc re-travaillé (à la main cette fois) pour obtenir ceci:
Et voilà ! Nous avions le design final de Polincorrect ! Enfin… Le style quoi, bref pour le reste je me suis adapté à ce que j’avais.
Le reste du développement s’est passé de façon tout à fait standard: remplie de bugs et de larmes. Et après quelques mois (je ne travaillais dessus que les soirs et les WE) une première version a pu être lancée. J’ai rempli la base avec environ 200 phrases puis j’ai pu lancer les premiers tests utilisateurs.
L’étape cruciale: les tests utilisateurs
Pour ce faire j’ai créé 3 groupes différents et j’ai préparé un petit Google Form et je leur ai fait tester plusieurs parties chacun. Non seulement de nombreux bugs sont apparus (possibilité de demander deux rounds d’un coup, problèmes de déconnexion qui crée deux utilisateurs identiques et bloque le jeu, …) ce qui a rendu tout ça très laborieux. Puis les premiers résultats sont tombés:
- Le titre n’est pas clair (pour moi c’était « POLItically iNCORRECT« , certains le trouvent trop compliqué, pour d’autres ça veut dire « faut être poli et correct »)
- Les phrases pas assez drôles
- Le design est bien (top, seule partie pas faite par moi)
- Le jeu manque de rythme et d’animations
Et globalement :
Bon… Peu mieux faire !
J’ai donc décidé que:
- Tant pis pour le titre, j’aime bien
- On garde le design également
- Je retire des actions de l’hôte de partie (qui devait valider entre chaque round) pour dynamiser un peu plus
- Je rajoute la possibilité de changer de round si un utilisateur est trop lent
- Je rajoute des animations
- Je me creuse la tête pour les phrases
J’ai également par la suite permis de kick un joueur de la partie et de soumettre une idée de phrase.
Lancement et conclusion
J’ai donc après plusieurs itérations et re-tests lancer le jeu. J’ai ajouté depuis de nombreuses fonctionnalités et d’autres viendront sûrement.
À l’heure de l’écriture de cette conclusion, une petite centaine de téléchargements ont été enregistrés (sur les deux stores cumulés). Un score très humble mais c’est déjà bien, honnêtement je suis content ! Et un peu moins de 200 parties ont été jouées pour le moment !
Bref, pas forcément des chiffres incroyables mais le développement et l’aventure qu’a été ce jeu sont honnêtement une très belle expérience et j’y ai pris beaucoup de plaisir. J’ai beaucoup appris et j’ai commis beaucoup d’erreurs. La prochaine application sera mieux travaillée et plus solide !
En attendant, si vous voulez tester le jeu, voici les liens des stores:
iOS: https://apps.apple.com/us/app/polincorrect/id1667335945
Android: https://play.google.com/store/apps/details?id=com.medrupaloscil.Poli