Journal Dev update du jeu Bim!

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes : aucune
18
23
mai
2024

Sommaire

La dernière fois je t'ai parlé de la mise en place du développement Bim!, un jeu mobile en PvP que je développe pour jouer avec les copains et aussi pour pratiquer l'approche « Entity Component System ».

Le projet a bien avancé depuis et j'ai envie de faire un petit point bilan, que voici ci-dessous.

Quoi de neuf dans Bim!

Quand nous nous sommes quittés à la fin du dernier journal nous avions un jeu fonctionnel en réseau dans un terminal, ainsi que les base d'une application Android. Ce n'était pas grand chose mais cela permettait de valider l'outillage, le cycle de dev, et les grandes lignes de l'implémentation. Depuis j'ai ajouté pas mal de nouveautés.

Dans le gameplay

Pour commencer, j'ai ajouté le fait d'éliminer les joueurs qui sont en collision avec une flamme. Ensuite j'ai ajouté l'arrêt du jeu quand il ne reste au plus qu'un seul joueur. Oui, c'est tout bête, mais si ce n'est pas codé ça n'arrive pas…

J'ai ensuite ajouté un joystick logiciel pour contrôler le joueur. Je n'aime pas trop cela mais pour l'instant je n'ai pas mieux. D'ailleurs figure-toi que ce n'est pas évident à régler ce truc et j'ai fait beaucoup d'allers-retours entre une simulation de stick analogique ou de croix directionnelle ; le déplacement unidirectionnel ou multidirectionnel quand on pointe plutôt en diagonale ; le contournement automatique des obstacles ou pas… C'est pas simple.

Lorsque je développais le prototype dans un terminal j'avais implémenté le déplacement du joueur case par case. Avec l'application graphique cela ne collait évidemment plus. J'ai donc implémenté le déplacement fractionnel pour cette dernière.

D'ailleurs, puisqu'on parle de cela, j'ai dû laisser de côté la version en ligne de commande. En effet, le joueur ne peut s'y déplacer d'une fraction d'une case, ce qui rendait les deux versions incompatibles. Soit le mouvement était saccadé dans l'application, soit il y avait une grosse latence dans le terminal. J'aurais pu isoler chaque mode (faire jouer les terminaux avec des terminaux) mais pour éviter d'avoir trop de cas à gérer j'ai préféré trancher.

J'ai ensuite ajouté la possibilité de déposer une bombe. Et oui, j'ai implémenté les flammes avant les bombes qui les créent…

Enfin, j'ai ajouté les power-ups de bombe et de flamme, ajoutant chacun une unité respective au joueur.

Et avec ça, on a suffisamment pour faire quelques parties :)

Réseau

Du côté du réseau j'ai eu quelques petites surprises. Déjà quelques messages arrivaient incomplets si je stressais le système, donc il a fallu mettre des gardes pour les ignorer.

J'ai aussi ajouté la connexion au serveur de jeu lorsqu'on lance l'appli. Sans ça, pas de jeu en réseau. Puis, cela en place, j'ai pu ensuite lancer une demande pour une nouvelle partie lorsque l'utilisateur clique sur le bouton « Play ». Ensuite j'ai ajouté la création de la partie du côté serveur, puis la proposition de la partie au joueur. Celui-ci doit la valider puis lorsque tous les joueurs ont validé le serveur donne le signal pour lancer la partie. Tout cela était assez simple puisque le protocole était déjà implémenté pour le client dans un terminal.

Concernant le regroupement des joueurs pour les matchs, j'avais initialement prévu de les réunir dans une salle nommée à leur discrétion. Il s'est avéré que c'était assez galère à gérer, et vu qu'en plus cela demandait un peu d'interface pour saisir le nom de la salle, j'ai finalement mis cela de côté en faveur d'un regroupement au premier venu. En gros, si tu lances une partie, tu joueras avec les une à trois autres personnes qui en lancent en même temps.

Autour du jeu

J'ai ajouté de quoi faire de la localisation en utilisant Gettext. Ce n'était pas hyper simple car je voulais que le fichier .pot ainsi que les .po associés soient mis à jour lors du build. Il y a bien quelques commandes dispos pour utiliser Gettext via CMake mais rien qui ne collait avec ce que je voulais. J'ai donc du bricoler implémenter magistralement, en CMakeScript, une collecte des sources à partir des targets déclarés dans les CMakeLists.txt, puis créer un nouveau target générant le .pot à partir de ces sources. Une fois cela fait le chemin du .pot au fichier de traductions compilé est assez trivial.

Bien évidemment ça aurait été trop simple s'il n'y avait eu que cela. Malheureusement j'ai aussi quelques chaînes à traduire depuis des fichiers de ressources. Pour que cela se mette bien avec xgettext j'ai ajouté une moulinette en Python pour extraire ces textes et les mettre dans un fichier C que xgettext saura lire, tout cela avec les dépendances de build correctes, ça donne:

  ressources
      |
      v
  moulinette    code source
      |              |
      v              |
  xgettext <---------+
      |
      v
    .pot            .po
      |              |
      v              |
   msgmerge <--------+
      |
      v
    msgfmt
      |
      v
     .mo

Et encore, je passe sur le fait que, sans contournement, la génération du .pot déclenchait toute la chaîne de génération des fichiers de traduction car il embarque la date de création du fichier…

Petite surprise avec les tests ThreadSanitizer qui échouent de temps en temps au lancement. Il s'avère que cet outil ainsi que AddressSanitizer n'aiment pas trop ASLR. Si jamais tu rencontres un crash au lancement d'un programme compilé avec ces outils tu sauras que ça se résout avec un sysctl vm.mmap_rnd_bits=28 (cf. le bug #1716 de ces outils).

Enfin, grosse étape, j'ai ajouté un conteneur Docker et des scripts pour le déploiement du serveur.

En dehors de ces gros morceaux, j'ai ajouté quelques bricoles de rigueur comme la compilation avec -Werror et l'écriture des fichiers .gdb lors du build release,

Note que je n'ai pas eu à retoucher l'environnement de build ni la CI, ce qui est assez chouette.

Pour la suite

Il me reste encore quelques étapes à compléter avant de faire un build public. Déjà il n'y a pas de possibilité de rejouer ; une fois le match terminé il faut relancer l'appli en faire un second. Ensuite il y a quelques ajustements de gameplay à faire : les bombes explosent trop tôt, le ressenti du stick n'est pas très agréable, le joueur devrait être bloqué par les bombes, et deux-trois autres trucs.

Idéalement il faudrait que j'ajoute un peu de latence sur les inputs aussi pour éviter de voir l'autre joueur sauter d'une position à l'autre. Ce n'est pas indispensable pour jouer mais ça serait plus agréable.

La dernière fois une personne très intelligente a laissé ce commentaire :

il y aurait sans doute pas mal de boulot pour savoir ce qu'est un bon test automatique d'un jeu.

Et bien je dois dire que les quelques tests que j'ai mis m'ont pas mal aidé dans le dev en validant le fonctionnel avant de gérer l'affichage. Ce sont des tests assez simples, du genre « flamme + joueur = élimination du joueur », ou encore « flamme + bombe = explosion de la bombe ». J'ai aussi quelques tests qui lancent un serveur et des demandes de parties, pour valider le protocole. De plus, ECS est vraiment confortable pour cela : pas besoin de créer tout un monde pour tester un truc, il suffit de créer les entités avec les bons composants et on peut faire tourner des systèmes indépendamment.

Ces derniers temps j'ai un peu ignoré les tests sur les nouveautés et je dois dire que ça manque rapidement. Je sais que dès que j'aurai à toucher par exemple aux power-ups, je vais craindre de casser quelque chose. Les tests, c'est bien.

Enfin un truc qui manque grandement ce sont de bons graphismes. Là dessus j'aimerais bien laisser la main à quelqu'un qui sait faire !


Garanti dessiné au pad.

Ça se trouve où

Pour l'instant il n'y a pas de build public mais si tu veux tu peux cloner le dépôt et taper ./setup.sh --help. Tu devrais trouver un moyen de sortir un build Linux ou un build Android en debug (pour la release il faut configurer la signature). L'application se connectera alors directement au serveur actuellement déployé.

  • # Je ne te promets rien...

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

    Pour la partie graphique, je peux regarder pour te faire une proposition graphique… malheureusement, j'ai peu temps.

    • [^] # Re: Je ne te promets rien...

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

      Ça serait bien cool :) Est-ce que ça te dirait de contribuer sur l'UI ? Des boutons, des menus, etc. Si ça te dit je te propose de me contacter par mail (qui ne devrait pas être dur à trouver) histoire de discuter du style :)

  • # Intéressant, cependant...

    Posté par  (site web personnel) . Évalué à 3 (+1/-0). Dernière modification le 29 mai 2024 à 05:13.

    Très intéressant…. Ça paraît s'inspirer d'un certain Dynablaster 😉 .

    Après on juge souvent une appli sur pièces…
    … et le problème des applis mobiles, c'est fréquemment l'absence d'APK tout prêt, avec une chaîne de compilation capillotractée en pas-vraiment-un-backup…

    Car là j'ai voulu essayer le fameux ./setup.sh (pour rire un peu), et il est bel et bien perfectible : sur une Ubuntu 22.04 LTS, ça m'a désinstallé GNOME. Je n'ai plus de desktop, juste le terminal au boot. 😁
    (je ne suis pas dérangé, car je le sentais venir et fais toujours ce genre de trucs sur une VM… mais voilà !)

    • [^] # Re: Intéressant, cependant...

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

      Après on juge souvent une appli sur pièces…
      … et le problème des applis mobiles, c'est fréquemment l'absence d'APK tout prêt, avec une chaîne de compilation capillotractée en pas-vraiment-un-backup…

      Bien d'accord ! La publication d'un APK est la priorité. Il me reste à implémenter la possibilité de faire d'autres matchs après le premier et ça devrait le faire :)

      Car là j'ai voulu essayer le fameux ./setup.sh (pour rire un peu), et il est bel et bien perfectible : sur une Ubuntu 22.04 LTS, ça m'a désinstallé GNOME. Je n'ai plus de desktop, juste le terminal au boot. 😁

      Ouch ! Sueurs froides à +11… Tu aurais plus d'info ? Car le script n'est pas sensé installer ou désinstaller quoi que ce soit. Normalement il télécharge tout Internet dans un sous dossier du dépôt (.backroom) et se débrouille avec ça. D'ailleurs la CI se fait entre autres sur Ubuntu 22.04, je suis curieux de savoir ce que j'ai laissé passer.

      • [^] # Re: Intéressant, cependant...

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

        Il me reste à implémenter la possibilité de faire d'autres matchs après le premier et ça devrait le faire :)

        Ce serait cool ouais 😀 !

        Tu aurais plus d'info ?

        Alors le dernier truc que j'aie vu c'est l'installation de "python3.10-venv" et après le téléchargement de gros paquets sans mention (dont "boost" de mémoire… du C++ ? via pip ou bien… ?) J'ai laissé le truc se dérouler 5 minutes de plus, et quand je suis revenu c''était tout noir.

        (je vais voir pour reproduire vendredi ; si j'oublie pas entre-temps…)

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.