Journal Sortie de Bim! en version 6

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
19
31
mar.
2025

Sommaire

Bonjour'nal,

Ça fait plaisir de te retrouver. Depuis la dernière fois où je t'ai parlé de mon jeu il s'est passé beaucoup de choses. J'ai même sorti deux versions ! T'as bien lu ; pas une, mais deux !

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.

Allez viens, pendant que ça s'installe on regarde un peu ce qu'il s'est passé durant ces deux mois.

Nouveautés dans le jeu

Zone de contrôles

Le premier gros changement visible est certainement la refonte de la zone de contrôles pendant les parties. C'étaient les derniers gros éléments graphiques provisoires et je suis bien content de les voir disparaître. Maintenant ça ressemble à ça, avec le stick et avec le pad directionnel :

Stick Pad directionnel

En passant dans les paramètres tu pourras choisir entre le stick et le pad, et aussi décider de le mettre d'un côté ou de l'autre.

Il y a eu quelques essais pour aboutir à ça, à commencer par un premier jet dans le carnet de croquis.

Tro stilé, j'ai l'impression d'être un artiste. Autant je n'avais pas trop de doutes sur le pad directionnel et le bouton d'action, si ce n'est cette timide tentative d'un bouton d'action « explosion », autant j'ai eu du mal à habiller l'ensemble. Pour le bouton d'action la version explosive est clairement trop chargée, donc je suis resté sur le rond.

Pour l'habillage je voulais quelque chose qui me permette de rappeler sa couleur au joueur. J'ai tenté diverses bandes, droites ou arrondies, mais c'était toujours trop. Trop gros, trop visible, trop moche. Ce n'est pas facile d'habiller une moitié d'écran sans que ça saute au visage du joueur. Au final après m'être un peu documenté sur les plateaux de contrôles de bornes d'arcade j'ai opté pour un fond vaguement fibre de carbone et j'ai mis un fin liseré autour pour le rappel de couleur.

Enfin, les croquis sur le carnet c'est bien sympa mais à un moment il faut mettre en couleurs. Pour ça je fais des essais avec GIMP. Je passe une heure à faire des formes, à colorier, je fais une moue, puis je demande l'avis d'un tiers :

— T'en penses quoi de mon interface là ?
— Ah c'est… ah… euh…
— C'est un peu moche, non ?
— Oui voilà !

Et hop, je recommence. Après quelques itérations j'arrive à un truc satisfaisant.

Brouillard de guerre

L'autre grosse nouveauté visible est l'arrivée d'un mode de jeu avec un brouillard de guerre. Lorsque la partie commence l'arène est masquée par un gros brouillard, et celui-ci ne se lève que sur les zones visitées par le joueur.

J'aime beaucoup ce mode de jeu et cela pour plusieurs raisons. Déjà, pour autant que je sache, c'est un mode de jeu qu'on ne trouve pas dans les jeux Bomberman ni ses clones, ce qui rend mon jeu un peu original. Idéalement j'aimerais bien m'éloigner de ces inspirations sur la durée pour aller vers quelque chose d'unique, et pour le coup cela s'inscrit bien dans cette démarche. D'autre part c'est un mode de jeu auquel je croyais peu au début et qui s'est avéré hyper marrant en pratique. Clique sur l'image pour voir une vidéo.

C'était un peu galère à implémenter parce que j'ai mis du temps à trouver comment combiner les graphismes pour faire toutes les variantes de cases brouillard en fonction de la présence de brouillard dans les cases voisines.

Au départ c'est assez basique : chaque case a 8 voisines, et chaque voisine a ou n'a pas de brouillard. Ça nous fait 8 booléens, donc 1 octet, soit 256 variantes. Je vais mettre ça dans une bête table voisinage -> sprite, ça sera pratique. Par contre je n'ai pas du tout la capacité pour dessiner 256 sprites, surtout avec ma manie de devoir faire plusieurs itérations à chaque fois pour tomber sur un truc qui me va.

Heureusement on peut s'en sortir avec moins de dessins. Pour chaque coin on a besoin de 5 variantes, par exemple pour celui en haut à gauche :

  • aucun voisin,
  • un voisin uniquement au dessus,
  • uniquement à gauche,
  • au dessus et à gauche mais pas dans le coin
  • un voisin partout.

Pour une case x ça correspond à ces cas :

00 01 00 01 11
0x 0x 1x 1x 1x

Ce qui graphiquement donne

Ça ne fait que 20 dessins à faire, dont un carré monochrome commun à tous les coins, c'est déjà mieux. Ensuite en combinant tout ça avec ImageMagick on peu générer toutes les variantes. Mais là encore il y a des économies à faire. En effet tu te demandes peut-être pourquoi ces cas là ne sont pas listés ci-dessus :

10 11 10
0x 0x 1x

Et bien c'est très simple. Comme il n'y a pas de connexion graphique directement de coin à coin alors la présence d'un voisin dans le coin ne change pas le dessin pour ces cas là. Au final on peut ramener l'ensemble des configurations à 47 variantes, générées donc à partir des 20 dessins précédents. Et voilà !

Reste à faire une illustration pour le bouton qui permet d'activer cette fonctionnalité depuis la recherche d'adversaire. On refait un petit tour dans le carnet de croquis pour essayer de choper une idée.

Puis après un vote et quelques essais sur la variante choisie, on sort ça :

Plein de petites améliorations

Beaucoup de nouveautés moins visibles sont arrivées dans les deux versions qui nous séparent de la dernière annonce. Moins visibles mais qui font néanmoins une vraie différence.

Les fausses options de l'écran de recherche d'adversaire ont disparu. Il n'y a maintenant que deux options : blocs qui tombent en fin de partie, et brouillard de guerre. Ces options se débloquent en jouant, que l'on gagne ou que l'on perde, mais il faut plus de défaites que de victoires pour les débloquer ;)

En parlant de recherche d'adversaire, l'affichage du nombre de joueurs est mis à jour même après pression sur le bouton « Go ». Un bouton pour revenir à l'écran principal a aussi été ajouté dans le cas où aucun adversaire n'est disponible.

La fréquence de rafraîchissement de l'interface lorsque l'on est dans les menus est maintenant réduite à 30 fps, ce qui permet de réduire l'effet hand warmer. Lorsqu'un match se lance on repasse à 60 fps, pour ensuite revenir à 30 sur l'écran de fin de partie.

L'effet de ralentissement appliqué par le client quand le joueur est trop en avance par rapport au serveur bénéficie de deux changements. Premièrement un bug causant de forts ralentissements a été corrigé. Deuxièmement la force de l'effet de ralentissement a aussi été réduite. C'est à dire que le client va plus vite quand il va moins vite. Enfin qu'il est ralentit mais plus vite. Il va plus rapidement lentement. Il modère le temps qu'il prend à ralentir sa précipitation. Rhâââ c'est galère à formuler. Il est ralentit mais pas autant qu'auparavant. Voilà. Point.

L'écran de paramètres a reçu de nouveaux boutons pour me joindre, par e-mail ou sur Bluesky (j'y poste parfois des infos sur le dev), un bouton pour retrouver le projet sur GitHub, et un bouton pour inviter des contacts à essayer le jeu.

Un message annonçant l'existence d'une nouvelle version sera dorénavant affichée au lancement du jeu, le cas échéant. Comme le jeu est installable hors magasins d'applications, la mise à jour n'est pas automatique pour tout le monde. Ce message devrait encourager la mise à jour et me simplifier la maintenance.

Et pour finir côté client j'ai corrigé un petit bug d'affichage au lancement de la partie qui causait une frame ou on voyait toute l'arène avant l'effet d'introduction ; et j'ai aussi corrigé le bug qui causait le dépôt d'une bombe dès le début de la partie, entraînant la défaite immédiate de celui qui subissait le bug.

Côté serveur, la position initiale des joueurs est maintenant choisie aléatoirement, parmi des positions prédéfinies. Cela permet d'introduire un peu de variation quand on enchaîne les parties. J'avais précédemment forcé la position des joueurs en fonction de leur arrivée dans la partie car on avait tendance autrement à ne pas savoir ou on était au début de la partie, mais avec l'ajout du liseré pour le rappel de la couleur ainsi que l'effet d'introduction du match, on a suffisamment gagné en lisibilité pour faire sauter cette contrainte.

Toujours côté serveur, la déconnexion des clients trop lents ou trop rapides a été revue. Ceci combiné avec une meilleur gestion de l'état de la connexion sur le client devrait causer moins de situations de déconnexion.

Présence sur les stores

Le jeu est maintenant présent sur F-Droid et sur le PlayStore. Il est aussi listé sur OpenAPK et AndroidFreeware. Je ne connais pas ces deux derniers mais la personne qui m'a annoncé l'ajout m'a écrit

I'm running a repo for Android open source apps at https://www.openapk.net and can say that it is a pleasure to have such a gem like Bim!, listed in the repo.
[…]
When I tried the most recent version I found it quite fun and engaging.

Franchement, ça fait plaiz. Si tu connais ces dépôts, parles-en nous dans les commentaires.

Ci-dessous je te raconte le travail fourni pour publier sur le PlayStore et F-Droid. Si tu développes une app pour ces magasins, ça t'aidera peut-être à t'organiser en amont.

PlayStore

Elle est loin l'époque où on pouvait publier tout et n'importe quoi sur le PlayStore ! Dans la dernière annonce je t'expliquais qu'il me fallait 12 testeurs en tests fermés pendant 14 jours avant d'avoir le droit de publier en production. C'est pas évident de trouver autant de testeurs en fait mais grâce aux amis, à la famille, et à des lecteurs de LinuxFr.org, j'ai pu passer le seuil. Un grand et sincère merci à eux tous.

J'ai cru pouvoir publier une fois les 14 jours passés, mais en fait ça mène juste à un formulaire pour demander l'accès à la prod, avec des questions telles que :

  • Où avez-vous trouvé vos testeurs ?
  • Comment ce sont passés les tests ?
  • Quels problèmes les testeurs ont-ils rencontré ? Comment les avez-vous reçu ?
  • Pourquoi pensez-vous que c'est le bon moment pour publier en production ?

(Ce n'était pas exactement ces mots, je te dis tout ça selon mes souvenirs.)

Une fois le formulaire soumis, c'est l'attente, quelques jours, avant d'avoir une réponse : « Déso vieux, on pense que tu devrais tester plus. On se revoit dans 14 jours o/ »

(C'était exactement pas ces mots, je le formule ainsi pour l'effet comique…)

Bon le refus était hyper frustrant mais en même temps j'avais légèrement bâclé le formulaire, un peu amer de rencontrer encore un obstacle avant la publication.

Une petite précision néanmoins : je trouve que c'est une très bonne idée de demander un minimum de tests avant publication. Le processus mis en place sur le PlayStore est très bien.

14 jours plus tard je retente la demande d'accès en production, en précisant cette fois-ci que je voulais surtout y accéder pour pouvoir faire des tests ouverts. C'est tout à fait honnête ; le jeu n'est pas prêt à être publié mais il est prêt à recevoir des retours de testeurs, et le test ouvert est le moyen le plus simple pour avoir des testeurs.

F-Droid

La publication sur F-Droid a été laborieuse aussi mais pour d'autres raisons. Un gros mystère pour moi était la gestion de la signature de l'APK. Pour le PlayStore et les builds via GitHub Actions l'APK est signé avec ma clé. Pour ce dernier il y a un système de variables d'environnement qui permet de passer la clé depuis l'interface web vers l'étape de la CI qui en a besoin, de manière sûre jusqu'à ce que quelqu'un trouve une faille.

Côté F-Droid il n'y a pas moyen d'importer une clé. La pratique est soit de laisser le serveur de build F-Droid signer le build, soit faire produire un build non-signé au serveur et de fournir un APK signé en référence. Dans ce dernier cas le serveur va vérifier que les deux APK ont le même contenu et l'APK de référence sera ensuite diffusé sur F-Droid. Seulement voilà, pour que cela fonctionne il faut que le build soit reproductible, et moi j'en était loin !

Un des éléments qui variait en fonction du build est le chemin correspondant à la macro __FILE__, parfois utilisé pour les logs. Forcément quand le build est fait sur ma machine c'est un chemin du type /home/bogoss69/dev/… qui apparaît dans le binaire, tandis que sur les serveurs F-Droid c'est plutôt /very/serious/path/…, donc forcément, ça coince. Cela est résolu avec l'option -fmacro-prefix-map du compilateur qui permet de remplacer un préfixe du chemin de __FILE__ par quelque chose de fixe.

Une autre source de différence d'un build à l'autre se trouve dans les metadonnées des PNGs. Lors du build je génère quelques images avec ImageMagick, mais le PNG généré contient des metadonnées telles que la date et l'heure d'écriture. Forcément ça change tout le temps ! En utilisant l'option -strip d'ImageMagick on lui demande de ne pas émettre ces données.

D'autres problèmes sont apparus du fait que le build se fasse dans un environnement Debian Bookworm du côté de F-Droid tandis que je m'appuie sur un environnement Ubuntu. Je n'ai rien dans le build qui soit spécifique à Ubuntu mais il y avait néanmoins quelques a priori. Par exemple, j'avais préparé des scripts d'initialisation de l'environnement qui faisaient des apt-get install xyz. Pas de chance, le paquet xyz portait un autre nom du côté de Debian.

Plus compliqué, la version d'ImageMagick fournie par Debian produit des fichiers différents de la version fournie par Ubuntu. Aïe ! Pour éviter les divergences j'ai ajouté ImageMagick dans le lot des dépendances précompilées par mon script de build, ce qui m'assure d'avoir la même partout.

Après tous ces ajustements, et d'autres bricoles pour satisfaire le linter F-Droid, j'ai fini par pouvoir publier. Ça a l'air vachement strict comme ça mais c'est un niveau de rigueur qui me plaît bien. Au final j'ai le sentiment de fournir un meilleur produit en réalisant des builds reproductibles. Et pour vous dire à quel point ils sont sérieux, quelqu'un est même allé voir dans mon code où était l'adresse du serveur de jeu et s'il était possible de la changer. Pas de chance, c'est en dur, et je me prends un label « anti-feature » pour la peine :'(

Un dernier mot sur F-Droid : les personnes qui m'ont accompagné dans mes errances, qui ont répondu à mes questions sur les forums, et qui ont ensuite commenté et étudié la PR étaient très accueillantes, très constructives. Un grand merci à elles, c'est très agréable d'être reçu ainsi quand on débarque dans un projet.

Quelques stats

Pour conclure ce long article je te propose quelques stats sur l'activité des joueurs. Comme je te l'ai dit dans les articles précédents, il n'y a aucun mouchard dans l'application, ce qui fait que je ne sais pas grand chose de ce que font les joueurs. Ma seule source d'info se trouve être les logs du serveur.

Niveau dates importantes, on a le dernier journal le 1er février, ensuite la version F-Droid a été acceptée le 5 mars et a du se propager vers le 8, et enfin la version PlayStore a été publiée le 11 mars. Voyons un peu ce qu'on trouve dans les logs sur les mois de février et mars, à commencer par le nombre de personnes qui souhaitent jouer :


Nombre de recherche d'adversaire par jour.

C'est pas encore la folie mais les chiffres font déjà plaisir. Ce n'est pas assez pour que tous les joueurs trouvent un adversaire cependant, comme le suggère ce graphe du nombre de parties jouées par jour (une partie est faite à partir de 2 à 4 recherches d'adversaires).


Nombre de parties par jour.

Ça ne se voit pas sur ces graphes mais il y a parfois des groupes de gens qui se connectent d'un coup et enchaînent les parties pendant une heure. Vu la synchronicité des connexions je pense qu'ils se sont organisés pour, et ça fait vraiment plaisir. C'est clairement le meilleur moyen de profiter du jeu car il y a très peu de chances que quelqu'un soit en attente quand on fait une recherche d'adversaire. Néanmoins, si tu veux jouer contre un adversaire au hasard, peut-être voudras-tu cibler les heures où il y a le plus de recherches d'adversaires.


Nombre de recherche d'adversaire par heure UTC.

Dans les logs se trouve aussi une IP des joueurs. De cette IP je peux supposer le pays du joueur en la donnant à geoiplookup.


Pays associés aux IPs des joueurs.

Je crois que c'est évident, ce jeu est un gros succès à l'international :)

On se retrouve dans quelques mois pour de nouvelles nouvelles !

  • # Trop cool !

    Posté par  (Mastodon) . Évalué à 4 (+2/-0).

    Ça ne se voit pas sur ces graphes mais il y a parfois des groupes de gens qui se connectent d'un coup et enchaînent les parties pendant une heure. Vu la synchronicité des connexions je pense qu'ils se sont organisés pour, et ça fait vraiment plaisir

    Je te confirme qu'avec les enfants, on se met d'accord pour se connecter en même temps. Début février, on était toujours seul. Cet après-midi, il y avait parfois un intrus. Et ce soir, c'est moi l'intrus, en tout cas, je croise d'autres gens que mes enfants. Il faudra bientôt que tu penses à un système qui permettent de se retrouver même quand il y a plein de monde.

    D'autre part c'est un mode de jeu auquel je croyais peu au début et qui s'est avéré hyper marrant en pratique.

    Je confirme qu'on le trouve très marrant aussi de notre côté

    Ces options se débloquent en jouant, que l'on gagne ou que l'on perde, mais il faut plus de défaites que de victoires pour les débloquer ;)

    Un peu frustrant de ne pas savoir comment il faut faire pour les débloquer. On voulait tester le brouillard mais l'un de nous n'arrivait pas à débloquer l'option => on en était tous privé. Pourtant, il perdait souvent.

    C'est tout à fait honnête ; le jeu n'est pas prêt à être publié mais il est prêt à recevoir des retours de testeurs, et le test ouvert est le moyen le plus simple pour avoir des testeurs.

    Je confirme aussi que tout n'est pas encore parfait. Aujourd'hui, on est tombé sur un bug bizarre où une personne reste seule après que les autres aient succombées à des bombes et la partie ne finit jamais même quand cette dernière personne se fait hara kiri. Cela vient encore de m'arriver (vers 21h48 si cela t'aide à retrouver dans les logs)

    Je crois que je te l'ai déjà écrit mais on s'amuse vraiment bien avec ton jeu.

    Surtout, ne pas tout prendre au sérieux !

    • [^] # Re: Trop cool !

      Posté par  (site web personnel) . Évalué à 4 (+2/-0).

      Merci pour les retours :)

      Aujourd'hui, on est tombé sur un bug bizarre où une personne reste seule après que les autres aient succombées à des bombes et la partie ne finit jamais même quand cette dernière personne se fait hara kiri. Cela vient encore de m'arriver (vers 21h48 si cela t'aide à retrouver dans les logs)

      Je crois que j'ai trouvé la partie problématique. Une partie à 3 joueurs où tout le monde se fait exclure par le serveur pour cause de retard. Effectivement je n'avais pas envisagé ça… Heureusement que la QA est là !

  • # fmacro-prefix-map

    Posté par  (site web personnel) . Évalué à 5 (+3/-0).

    Cela est résolu avec l'option -fmacro-prefix-map du compilateur qui permet de remplacer un préfixe du chemin de FILE par quelque chose de fixe.

    Je connaissais pas ; intéressant !

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.