Sommaire
- Nouveautés dans le jeu
- Le logiciel libre comme support pédagogique
- Quelques mots sur le dev
- Quelques stats
Bonjour'nal,
Et bien dis-donc, c'est qu'on serait presque régulier sur les annonces de sorties de Bim! Ça fait plaisir. Deux versions sont sorties depuis la dernière fois où je t'ai parlé de mon jeu. Je vais te parler des nouveautés, du dev, et d'une petite expérience sociale :)
Pour rappel, Bim! est un jeu libre (code AGPL3 et assets CC-by-sa 4.0) multijoueur de type dernier survivant, et qui se joue uniquement en ligne. Il n'est disponible que pour les systèmes Android. Le jeu étant encore en bêta sa diffusion sur le PlayStore est limitée à quelques pays (France, Belgique, Suisse). Le reste du monde peut néanmoins le trouver sur GitHub, F-Droid, et d'autres magasins alternatifs.
Pas besoin de rester inactif pendant que ça s'installe, tu peux passer le temps en regardant ce qu'il s'est passé durant les deux mois qui nous séparent du dernier journal.
Nouveautés dans le jeu
Ça bouge : les personnages sont animés
Une grande nouveauté de la version 7 est l'arrivée d'animations pour les personnages. Fini les avatars qui glissent ! Maintenant ils marchent et se dandinent. J'en ai aussi profité pour animer la mort du personnage (brûlé ou écrabouillé).
Plus de tolérance sur la fin de partie
Un effet de bord plaisant des animations de défaites est que cela adoucit la transition vers l'écran de fin de partie. Auparavant le passage à cet écran se faisait dès que l'avant dernier joueur vivant perdait. Maintenant on a le temps de le voir perdre et on est moins surpris d'arriver sur la fin de partie.
Au passage j'en ai aussi profité pour temporiser la condition de victoire : tant qu'un joueur est en cours d'animation de défaite, la partie continue. Donc même si on voit l'adversaire brûler, il faut rester vigilant encore quelques secondes. Cela évite les situations frustrantes où un joueur gagne alors qu'il était sur le point de se faire exploser, la victoire n'étant due qu'au fait que l'autre joueur ait perdu pendant l'itération de jeu précédente.
Bonus d'invisibilité
Les joueurs qui l'ont débloqué peuvent maintenant activer un bonus d'invisibilité. Celui-ci apparaît lors de la destruction de certains blocs et rend le joueur invisible pour les autres pendant quelques secondes.
Clique sur l'image pour voir la vidéo.
Tout comme la fonctionnalité de brouillard dont je parlais la dernière fois, l'invisibilité est bien plus amusante que ce que j'avais anticipé ! En effet, cela donne un petit twist stratégique auquel je ne m'attendais pas. En pratique j'observe que mes adversaires et moi-même avons tendance à conserver le bonus dans un coin jusqu'à ce que le passage vers les adversaires soit ouvert. À partir de là les joueurs s'empressent de disparaître puis les bombes poppent de partout :D
Ce bonus est une contribution de jlallas384. Merci !
Récompenses et déblocage des fonctionnalités
Le déblocage des fonctionnalités de jeu se faisait auparavant en jouant, que le joueur gagne ou perde, mais sans indication de progression. À partir de la version 8 les joueurs reçoivent des pièces à chaque partie, qu'ils gagnent ou qu'ils perdent. Ils peuvent ensuite utiliser ces pièces pour accéder aux fonctionnalités supplémentaires.
J'ai aussi modifié la manière dont les fonctionnalités choisies étaient filtrées par le serveur. Dans les précédentes versions il s'agissait d'un « et » logique : la partie se lançait avec ce qui avait été choisi par tous les joueurs. À partir de la version 8 c'est un « ou » logique : tout ce qui a été sélectionné par au moins un joueur est activé.
Dans la mesure où les joueurs « payent » (avec la monnaie du jeu) pour avoir accès à une fonction, il me semblait plus juste de l'activer dès lors qu'elle est demandée.
Affichage de messages d'attente sur l'écran de recherche d'adversaire
Le problème d'un jeu multi-joueurs comme Bim! quand il y a peu de joueurs est que ces derniers vont se pointer sur une recherche d'adversaire dans un moment où il n'y a personne, se lasser, et partir. C'est un peu un problème sans solution. Soit les joueurs se donnent rendez-vous, et ils se retrouvent ensemble, soit ils viennent en touristes et se retrouvent… seuls.
Le seul moyen pour que les touristes rencontrent quelqu'un est de les garder assez longtemps sur la recherche d'adversaire pour qu'ils soient encore là quand quelqu'un d'autre arrive. Pour essayer de les retenir un petit peu j'ai ajouté quelques messages défilant sur cet écran ; des petits commentaires qui se veulent amusants ou divertissants. J'espère que ça permettra de favoriser les rencontres.
Amélioration de la gestion des déconnexions
On m'a remonté à plusieurs reprises des situations de parties qui ne se terminent pas, avec un joueur qui reste tout seul dans l'arène et pas moyen de quitter. « C'est normal », disais-je, « tu as été déconnecté ». Mais si c'est normal du point de vue du dev qui sait que c'est codé comme ça, et que ça fait exactement ce qui est prévu, c'est inattendu et désagréable pour le joueur.
J'ai donc corrigé amélioré la gestion des déconnexions. Ces joueurs qui erraient sans but seront donc dorénavant interrompus par un message les informant qu'ils ont été déconnectés.
Ajustements techniques
Ici on rentre dans des trucs techniques qui ne vont pas intéresser les joueurs, mais ça fait quand même parti du dev ! Soit attentif, il y aura une interro.
Finalement la signature de l'app est optionnelle
J'ai modifié le build Android pour omettre la signature de l'APK si le keystore est absent. J'avais initialement pensé que le keystore serait toujours là, soit localement sur ma machine, soit injecté dans la CI sur GitHub. Cependant, lors de la publication pour F-Droid je me suis retrouvé dans une situation où le build était fait dans un environnement que je ne contrôle pas. J'avais bricolé les scripts uniquement chez eux pour contourner le problème.
Or, ces derniers mois j'ai eu des contributions externes, c'est à dire des pull requests qui devaient évidemment passer la CI mais qui échouaient lors du build Android release puisqu'ils n'avaient pas accès à mes secrets GitHub pour signer le build. Pour éviter de déprimer ces contributeurs devant un pipeline en échec, de les laisser à se demander ce qu'ils ont bien pu casser, j'ai ajouté cette possibilité d'effectuer le build sans le signer. Maintenant si les pipelines sont rouges c'est bel et bien de leur faute !
Version de dev de l'app, car je suis spécial
Une petite modif de confort ; j'ai ajouté la possibilité de faire une version « développeur » de l'application Android. Ça ne change pas grand chose, juste l'icône et l'identifiant d'application, mais ça me permet d'avoir deux versions de l'application sur mon téléphone : la version de prod pour jouer avec tout le monde, et la version de dev pour les tests.
À la base je n'aime pas trop ces paramètres qui modifient le type de build. J'ai toujours une légère crainte de me retrouver à publier une version de dev non signée, ou bien d'avoir un comportement différent de l'app officielle, mais c'est vrai que c'est difficile de faire sans.
Garde-fous sur le déploiement du serveur
Le script de déploiement du serveur était tout bête : il copiait les fichiers sur l'hôte, éteignait l'ancien serveur, remplaçait les fichiers, puis lançait le nouveau serveur.
Je n'ai jamais été très à l'aise avec ce script ; ça ressemble à quelque chose que je vais finir par lancer par inadvertance et qui va m'éteindre le serveur de prod.
Dans l'idée de contrer une éventuelle mauvaise manip, j'ai modifié le script pour ajouter des garde-fous. D'une part il attendra maintenant quelques secondes avant de déployer, ce qui me laissera le temps de faire un Ctrl+C pour l'interrompre, et d'autre part il refusera de déployer si cela remplace un serveur dans le dossier duquel j'aurais mis un fichier lock
.
Me voilà rassuré.
Activation de LTO sur les builds release.
Ça faisait un moment que cela me travaillait : les builds optimisés de l'application ne l'étaient pas autant qu'ils pouvaient l'être. La situation s'est améliorée puisque le build release utilise maintenant la fonction Link Time Optimization (aussi connue sous le nom d'IPO, InterProcedural Optimization) du compilateur.
Le logiciel libre comme support pédagogique
Ces derniers mois je me suis lancé dans une petite expérience qui me trottait dans la tête depuis un moment. Fréquentant le forum r/cpp je vois régulièrement des posts de personnes cherchant des projets à rejoindre pour apprendre le C++ de manière concrète. Or il s'avère que je développe moi-même un projet en C++ sur lequel je laisse pas mal de choses de côté, notamment parce qu'elles ont une valeur beaucoup plus technique que pour le produit.
Est-ce qu'il n'y aurait pas moyen de mélanger tout cela en quelque chose de positif pour tout le monde ? Du ouine-ouine en quelque sorte.
Je me suis donc fendu d'un petit message sur r/cpp invitant quiconque cherchant un projet pour démarrer en C++ à se pencher sur une des 5 issues écrites pour l'occasion :
- Use
bim::table_2d
in bim::arena - Game feature: invisibility
- Enable LTO in Android release builds
- Display GeoIP-guessed country in server logs
- Add support for server stats
Pour eux, cela permet de pratiquer sur un projet concret, et ils reçoivent par le biais de revues de code des retours de quelqu'un ayant maintenant un paquet d'années d'expérience en développement et en particulier en C++. Pour moi, cela me fait de la main d'œuvre « gratuite » et me permet d'avancer sur des sujet non prioritaires, et en plus j'en profite pour travailler ma pédagogie.
Et bien cette proposition a plutôt été un succès :) J'ai eu une petite dizaine de gens intéressés. Quelques uns ont laissé tomber parce qu'ils avaient du mal à compiler le projet, d'autres ont cessé de donner des nouvelles, et ceux qui restent ont contribué. La première contribution a été l'invisibilité, puis l'utilisation de bim::table_2d
, et entre les deux les contributeurs ont aussi trouvé une source de crash potentiel. Top ! Pour LTO je l'ai fait moi même (c'était vachement dur en fait) et il y a au moment où j'écris ces lignes quelqu'un qui travaille sur les stats. D'ailleurs les specs pour les stats étaient un peu légères et dès la première itération c'est apparu bien plus compliqué que prévu. Un classique. Enfin pour les pays dans les logs il y a eu un candidat mais plus de nouvelles.
Décrit comme cela ça a l'air très positif, mais observe bien que j'ai mis des guillemets en parlant de main d'œuvre « gratuite ». Ce n'était pas que pour le style. Il s'avère en fait que faire une revue de code correcte et de manière pédagogique, c'est à dire en rationalisant les demandes subjectives et en fournissant une analyse sur les problèmes, c'est très chronophage. Au final je pense que je passe autant de temps à faire des revues que si je l'avais codé moi-même, et je fais plutôt passer les revues en priorité devant mes tâches, donc même si ça ne me coûte pas d'argent ça coûte au projet. Cela dit j'ai trouvé ça assez cool d'accompagner des devs qui veulent apprendre sur mon projet, donc 10/10, ça valait le coup.
Quelques mots sur le dev
Les animations
Les animations de Bim! sont faites à l'ancienne, frame à frame. J'ai une image de base dans GIMP, avec les éléments éclatés (i.e. un calque pour chaque bras, un autre pour chaque jambe, un pour la tête, etc.). Ensuite je copie, transforme, et redessine les éléments. Puis je les assemble dans plusieurs images que j'exporte afin de les charger et les afficher dans le jeu. Pour les personnages je fais aussi une rotation de couleur (qui est devenue teeeeeeeellement plus pratique avec les calques d'effets ! Merci Jehan et les devs de GIMP !)
Tout ceci est très long et laborieux. Pour la rotation de couleurs je pourrais m'en sortir avec un shader mais à terme j'aimerais bien avoir des personnages différents, et donc le shader sera peu utile. Et ça ne simplifie pas l'animation.
Idéalement j'aimerais bien un outil d'animation par squelette à la Spine ou DragonBones, mais aucun de ces outil n'est libre. Ça n'aurait aucun sens de les utiliser pour un logiciel libre (pour contribuer aux anims de mon jeu il te faut payer une licence à $70, lol). Seul le runtime de DragonBones est libre, et je ne connais malheureusement aucun autre logiciel de ce genre. J'ai lancé l'idée de développer un éditeur de ce type au sein du projet Axmol, je croise les doigts pour que ça intéresse quelqu'un. Même s'il faut payer un dev pour ça je pense que ça vaut le coup.
La galère d'activation de LTO
L'activation de LTO était très laborieuse. J'avais déjà essayé de passer l'option -flto
au compilateur, permettant d'activer cette optimization, sans succès. Ça causait plein d'erreurs de link, que ce soit en utilisant le flag directement ou en passant par CMAKE_INTERPROCEDURAL_OPTIMIZATION
.
Le problème vient de la combinaison de plusieurs facteurs. À la base je souhaite activer LTO sur l'application mais aussi sur ses dépendances, histoire d'en profiter au max, mais ces dépendances sont à la fois utilisées dans un build debug et dans un build release. Par exemple, je compile toujours JsonCpp en release, et donc la même lib statique compilée avec LTO va être utilisée pour le build debug et le build release de Bim!.
Pas de chance, les bibliothèques compilées en activant LTO avec Clang (obligatoire pour Android), ou en activant LTO via le paramètre CMake, ne contiennent par défaut que les données intermédiaires (IR) spécifiques au compilateur, et celui-ci est incapable de les traiter si on ne lui passe pas -flto
. On a donc :
- un build release de JsonCpp avec
-flto
qui produit unlibjsoncpp.a
contenant l'IR de Clang ; - une compilation de Bim! en debug sans
-flto
qui link aveclibjsoncpp.a
: boum ! le compilateur ne s'en sort pas.
La solution ici est d'utiliser -ffat-lto-objects
lors de la compilation des dépendances afin de créer des libs statiques contenant à la fois la représentation intermédiaire du compilateur et la version compilée. Cette option de compilation est disponible depuis toujours avec GCC et depuis relativement récemment dans Clang.
Pas de chance, un bug de Clang dans sa version livrée dans le NDK 27 d'Android causait une erreur de link parce que the class is missing its key function (see https://lld.llvm.org/missingkeyfunction). Heureusement une mise à jour du NDK corrige le problème.
Et bien, ce n'était clairement pas une tâche pour débutant ! Et je n'ose même pas imaginer comment j'aurais fait si j'avais utilisé un gestionnaire de paquets type Conan ou vcpkg…
La grande question de la recherche d'adversaire.
histoire de dette graphique.
tendance à vouloir refacto.
chaque développement amène de nouvelles questions. Par exemple game features: il suffit qu'un joueur le débloque pour que les autres en profitent. N'est-ce pas contre-productif ? Pourquoi les autres joueraient-ils ou achèteraient-ils des pièces ? Possibilité de limiter à quelques features par joueur par partie. Possibilité d'acheter un slot supplémentaire ? Pour une session ou définitivement ?
Quelques stats
Les précédentes versions de Bim! sont sorties le 28 mars, le 1er mai, et la version 8 le 25 mai. Il s'agit là des dates de disponibilités de l'APK sur GitHub mais il faut quelques jours pour que le build fourni à F-Droid et au PlayStore se diffusent.
Sur l'image ci-dessous tu peux voir le nombre de recherches d'adversaire par jour sur les mois d'avril et mai :
Nombre de recherche d'adversaire par jour.
Il y a quand même un peu de monde n'est-ce pas ? Forcément ça augment lors des sorties des nouvelles versions puis ça s'atténue sur la durée. Le post sur Reddit a été publié le 19 avril et n'a visiblement pas eu d'impact sur la masse des joueurs.
Si on regarde maintenant le nombre de parties effectuées par jour (une partie est faite à partir de 2 à 4 recherches d'adversaires), on obtient ceci :
Nombre de parties par jour.
C'est quand même beaucoup moins, et bien que le mois de mai voit plus de recherche d'adversaires, il y a beaucoup moins de parties jouées. Clairement, les gens ne se trouvent pas :(
Niveau répartition du nombre de joueurs par parties, on a :
Nombre de joueurs | Nombre de parties |
---|---|
2 | 1452 |
3 | 184 |
4 | 71 |
Le duel est donc loin devant. Enfin, pour conclure, voici la répartition géographique des joueurs (modulo l'état de ma base de géolocalisation d'IP) :
Pays associés aux IPs des joueurs.
Pas grand chose à dire là dessus ! Il y a du monde d'un peu partout et c'est en France qu'on trouve le plus de joueurs ; sans surprise puisqu'il n'y a qu'ici où je communique sérieusement à propos du jeu.
Rendez-vous dans quelques mois pour des nouveautés et un nouvel état des lieux :)
# stats
Posté par jemore . Évalué à 1 (+0/-0).
Tu as des stats sur l'heure où on a le plus de chance de croiser quelqu'un ?
[^] # Re: stats
Posté par Julien Jorge (site web personnel) . Évalué à 2 (+0/-0).
Voici le nombre de recherches d'adversaire par heure (heure française) :
Rendez-vous à 20 h donc !
# Félicitations
Posté par Tarnyko (site web personnel) . Évalué à 4 (+2/-0).
Salut, c'est moi qui t'avais rapporté un problème de dépendance sur le paquet 0.2 (peut-être ton premier journal sur Bim!).
Juste que tu saches que c'est très intéressant, et que je garde un oeil dessus; pas tant pour jouer que pour "faire du réseau" plus tard sous Android :).
# Pour l'animation
Posté par B r u n o (site web personnel) . Évalué à 1 (+0/-0).
Je ne connais pas le secteur, mais il y a un moment j'étais tombé sur https://www.vgc.io/ qui a un projet de logiciel de dessin et d'animation, le dépôt associé : https://github.com/vgc/vgc C'est un projet en alpha, les binaires sont réservés aux sponsors patreon je crois, mais il y a les instructions de compilation sur le dépôt.
Envoyer un commentaire
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.