khanat_gamedev_guide/README.md

28 KiB
Raw Permalink Blame History

Guide de développement pour Khaganat

Ce manuel est rédigé collaborativement en Markdown à ladresse suivante : https://git.numenaute.org/khaganat/mmorpg_khanat/khanat_gamedev_guide

Sources et inspirations

Très inspiré par et basé sur le « Gamemakin UE4 Style Guide » disponible sur GitHub.

Godot propose quelques conseils sur la façon de travailler pour son propre projet dans une section Les meilleures pratiques ainsi quun Guide de style et un Bonnes pratiques pour les contributeurs au moteur destinés à celles qui souhaitent contribuer au développement du moteur lui-même.

Principes de base

Un manuel vivant

Ce manuel a vocation à rendre la contribution plus efficace, Khaganat est ouvert à la discussion et possède un canal XMPP où on peut échanger sur tout cela : https://khaganat.net/irc/.

Respectez la loi

Khaganat respecte la loi française et vous demande de faire de même, donc merci de ne rien introduire dillégal dans le projet par vos actions. En particulier :

  • ne réemployez pas le travail dautrui si vous nen avez pas reçu lautorisation explicite
  • respectez les licences dusage des éléments que vous souhaitez copier depuis un autre projet, en particulier si lattribution est demandée (comme avec les licences CC BY)
  • avant dy apporter des éléments externes, vérifiez-en la compatibilité avec les licences du projet Khaganat

Terminologie

Identifiants

Un Identifiant est ce quon appelle communément un « nom » : celui dun objet 3D, dun fichier de son, dun répertoire, dune variable ou dun script…

Caractères autorisés dans les identifiants

Dans un Identifiant, jamais on nutilise un de ces caractères :

  • les espaces
  • les barres obliques ou barres obliques inverses \, /
  • des symboles du genre #!@$%
  • des caractères Unicode

Un Identifiant ne doit donc comprendre que les caractères suivants :

  • ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • abcdefghijklmnopqrstuvwxyz
  • 1234567890
  • _ et - (avec parcimonie)

Pour résumer, un Identifiant doit pouvoir répondre à lexpression régulière ^(?:[a-z]++(_|-))*+[a-z]++$)

Ces règles permettent la plus grande compatibilité entre systèmes et pays.

Lusage des casses

Il y a plusieurs façon décrire les Identifiants, dont voici les plus courants (dénommés par leurs désignation en anglais, conventionnelle).

PascalCase

On met une majuscule à chaque mot et on supprime les espaces : Coffre avec poignees devient CoffreAvecPoignees.

camelCase

Cest similaire au PascalCase, sauf que la première lettre du premier mot est en minuscule : Coffre avec poignees devient coffreAvecPoignees.

Plus de précisions sur Wikipédia.

snake_case

Les espaces sont remplacés par des underscores « _ » : Coffre avec poignees devient coffre_avec_poignees

Bien que par convention, on puisse choisir de mettre ou pas des majuscules aux mots, nous retenons lidée de tout mettre en minuscule pour nos usages du snake_case. Coffre avec poignees devient donc coffre_avec_poignees

Plus de précisions sur Wikipédia.

lisp-case / kebab-case

Les espaces sont remplacés par des tirets (le signe moins) « - » : Coffre avec poignees devient coffre-avec-poignees.

La désignation de cette casse nest pas définitive, kebab-case semblant le plus fréquent, mais lisp lutilise aussi depuis de très nombreuses années.

Variables / Propriétés

Les termes Variable et Propriété sont généralement interchangeables, mais si ils sont utilisés dans le même contexte, cela signifie plus précisément :

  • pour Propriété que cela désigne une variable dans une classe.
  • pour Variable, cela désigne généralement un argument de fonction ou une variable locale dans une fonction. Dans une classe, cela peut indiquer un statut à préciser/ définir.

Les types de fichiers

Godot

  • .escn : Exported Scene Data. Format utilisé pour exporter des scènes depuis Blender vers Godot.
  • .gd : Source Code. Fichiers avec le code source natif de Godot.
  • .gdc : Compiled Script. Fichiers compilés.
  • .gdshader : Shader Data. Shader spécifique à Godot (du GLSL modifié).
  • .godot : *Project. Fichier descriptif du projet.
  • .import : Import Settings Data. Fichier sidecar aux formats externes, qui contient les paramètres dimport.
  • .material: Godot material. Matériau.
  • .mesh : Mesh Data. Informations sur la géométrie dun objet 3D.
  • .meshlib : Mesh Library. Catalogue de meshes.
  • .oggstr : OGG Audio Data. Fichier audio.
  • .pck : Game Package. Paquet de jeu
  • .profile : Feature Profile Data
  • .res : Binary Resource Data. Ressource binaire.
  • .sample : Audio Sample Data. Fichier audio.
  • .scn : Binary Scene Data. Scène sous forme binaire.
  • .stex : Stream Texture Data.
  • .tpz : Export Template Archive.
  • .tres : Text Resource Data. Fichier descriptif dune ressource.
  • .tscn : Text Scene Data. Scène, élément de base dun projet.

Convention de nommage

Noms de fichiers

Indépendamment de leur extension, les fichiers peuvent comporter trois parties, séparées chacune de la précédente par un underscore : préfixe, corps et suffixe. Le préfixe et le suffixe sont déterminés par le type de fichier (son extension donc).

Nommage des éléments internes aux fichiers

Blender

Sauf indication contraire, tous les éléments internes aux fichiers Blender doivent être écrits en kebab-case. Le recours à un préfixe ou suffixe sera indiqué le cas échéant.

Collections

Les objets destinés au jeu Khanat doivent être placés dans une collection nommée « khanat », située à la racine de la collection principale.

Objets

Les Objects doivent être rassemblé dans des sous-collections pertinentes, et il faut veiller à ce que lObject Data qui y est associé soit nommé de façon identique.

Godot

Les signaux doivent avoir un nom avec un verbe au passé, car cela indique un état qui vient dêtre connu par lémetteur.

Les fonctions doivent commencer par un verbe, voire un verbe avec un auxiliaire si elles retournent un booléen (« is_green », « has_been_healed »).

Les variables et les classes commencent généralement plutôt par un nom.

Le suivi de version avec Git

Nous avons choisi de travailler avec un dépôt principal et que les contributions soient possibles via des forks (Forking workflow dans la terminologie Gitlab). Vous aurez donc un dépôt secondaire sur lequel vous aurez tous les droits et depuis lequel vous ferez les merge request (plus de détails dans la documentation GitLab).

Le dépôt principal

Le dépôt de référence et sa branche principale « main » doivent avoir un historique le plus propre possible. Cest la raison pour laquelle il convient de toujours travailler par le biais de forks et de merge requests via la forge gitlab de Khaganat : https://git.numenaute.org/khaganat.

Cela permet à chaque contributrice de travailler en local via son propre fork distant. Elle peut ensuite proposer son code une fois prêt via une merge request qui sera auditée par une autre contributrice ayant laccès au dépôt principal (rôle de developper, maintainer voire owner du dépôt principal). Cest lors de cette étape de validation avant fusion/merge quun contrôle sera opéré non seulement sur le code en lui-même, mais également sur la rédaction du message de commit.

Forker sur gitlab / cloner en local

Forker : copie distante

En cliquant sur le bouton « Fork » sur le projet principal, vous allez créer une copie distante sur la forge Gitlab, ce sera votre dépôt de développement depuis lequel vous pourrez opérer des merge request. Vous pouvez le gérer comme bon vous semble, mais dans le doute, vous pouvez laisser les options proposées par défaut si vous comptez simplement vous en servir comme base pour contribuer au code.

Cloner : copie locale

Une fois votre dépôt distant créé (appelé origin remote dans le jargon Git), vous allez le copier sur votre ordinateur local pour travailler, cela se fait via la commande git clone.

Pour obtenir ladresse à cloner, il faut cliquer sur le bouton « Clone » de linterface gitlab sur la page daccueil du dépôt. Vous pourrez choisir soit par https, soit par ssh. Préférez toujours de passer par ssh.

git clone ssh://git@port.numenaute.org:3543/yannk/khanat_gamedev_guide.git

Cela va copier le dépôt dans un sous-répertoire de lendroit où vous avez tapé la commande. Il vous faudra alors vous y déplacer pour travailler.

Une étape essentielle est ensuite dajouter le dépôt principal sur une branche locale de façon à pouvoir récupérer la dernière version du code du dépôt principal quand vous travaillez sur vos propres implémentations. Cela se fait en ajoutant une référence, appelée conventionnellement upstream et pointant vers le dépôt principal, dont ladresse est indiquée par le même bouton « Clone » sur sa page gitlab.

git remote add upstream ssh://git@port.numenaute.org:3543/khaganat/mmorpg_khanat/khanat_gamedev_guide.git
git fetch upstream

Ces commandes passées lors de la création vous permettront de mettre à jour toute branche de votre dépôt local en tapant :

git pull --rebase upstream main

Loption rebase nest généralement pas obligatoire, mais sera nécessaire dans notre flux de travail.

Et si jamais vous souhaitez ensuite mettre à jour votre dépôt distant (votre fork) :

git push

Cela enverra les modifications du dépôt principal que vous avez récupérées en local (via upstream) vers votre dépôt distant, ce qui le mettra à jour avec le dépôt du projet.

Le travail en local

Vous avez par défaut sur votre dépôt local la branch main. Vous pouvez le vérifier en tapant la commande :

git branch

et vous obtenez :

* main

Ce qui signifie quil nexiste que la branche main et que vous êtes actuellement positionné dessus (présence de lastérique devant)

Il faudra veiller à sa mise à jour régulière en tapant la commande :

git pull --rebase upstream main

Gestion des branches

Pour implémenter votre code, il va falloir créer une branche dédiée, depuis la branche main. Vérifiez que vus êtes bien sur la bnranche main avant de la créer car cest de celle-ci, la plus à jour possible depuis upstream (la branche main distante du dépôt principal), que vous devez travailler :

git branch preference-file-creation

Vous pouvez ensuite basculer dessus pour commencer le travail

git checkout preference-file-creation

Mise à jour de la branche

Pensez à la mettre à jour régulièrement avec upstream afin de garantir la compatibilité de votre code avec les derniers ajouts :

git pull --rebase upstream main

Loption rebase permet de garantir que les changements que vous avez apportés seront intégrés à la fin de la branche, ce qui fait que seuls vos commits vous feront dévier du code de la branche main du dépôt officiel, sans occasionner de merge préalable. Cela simplifiera le merge ultérieur.

Si jamais lors du rebase, des conflits apparaissent, git sarrêtera et vous demandera de régler le conflit (comme lors dun merge classique), ce que vous ferez avec votre éditeur habituel. Puis vous reprendrez la suite du rebase avec la commande :

git rebase --continue

Recommencez autant de fois que nécessaire la gestion des conflits jusquà la fin de lopération.

En cas de doute, si vous pensez avoir fait une erreur, vous pouvez annuler toute lopération très aisément pour retrouver votre dépôt dans son état précédant le rebase avec la commande :

git rebase --abort

Le merge request

Envoyer ses modifications locales sur son propre dépôt de fork, distant

Une fois vos modifications réalisées sur votre branche, si cela fait un moment quelle na pas été mise à jour par rapport au projet principal, vous pouvez vous assurer que vos modifications sont prises en compte en dernier (et ne provoquent pas de conflit) en tapant :

git pull --rebase upstream main

Vous pouvez ensuite envoyer vos modifications locales sur votre dépôt distant origin dans la branche sur laquelle vous travaillez :

git push origin preference-file-creation

Faire la demande de merge request

Vous devez vous connecter avec votre compte sur le serveur gitlab, aller dans votre fork distant et là, cliquer sur « merge request » dans la colonne de gauche. Puis vous cliquez sur « New merge request ».

Une nouvelle page souvre alors. Normalement vous aurez les deux dépôts corrects indiqués, à savoir votre dépôt de fork distant dans la partie gauche et le dépôt originel du projet dans la partie droite. Si ce nest pas le cas, veillez à bien indiquer les dépôts et branches pertinents dans lorigine (à gauche) et la destination (à droite) : vous devez indiquer dans la partie gauche votre dépôt sur gitlab avec votre branche de travail (preference-file-creation dans notre exemple) et ce sera la branche main du projet principal qui sera la cible. Vous pouvez ensuite cliquer sur « compare branch and continue ».

Il est possible de bloquer la validation dune merge request durant un temps damélioration (afin ditérer après un premier retour par exemple). Dans ce cas, il faut indiquer Draft: à son début de titre. Il faudra alors appuyer sur le bouton Mark as ready pour permettre sa validation (détails dans la documentation Gitlab).

Page « New merge request »

Vous pouvez laisser le titre de votre commit ou le changer pour permettre de comprendre plus rapidement ce dont il sagit. Vous pouvez compléter la description également. Il faut cocher squash commits when merge request is accepted pour faire en sorte que lhistorique des commits du dépôt principal soit plus simple, avec seulement le commit de merge. Vous pouvez laisser le reste tel quindiqué par défaut.

Puis vous cliquez sur « create merge request ».

À partir de là, vous pourrez échanger avec les responsables du dépôt principal dans lespace « Activity ». Vous avez les onglets « Overview », « Commits », « Pipelines » et « Changes » qui permettent de suivre ce que la Merge request comporte comme contenu.

Valider une « merge request » dune contributrice

Si vous êtes suffisament impliquées dans le projet, vous aurez la possibiltié de valider des Merge request pour que la contribution soit ajoutée au dépôt principal. Vous pouvez voir les Merge requests en attente sur le dépôt principal du projet avec la section à gauche « Merge requests ». Vous avez sur la page plusieurs onglets, « Open », « Merged », « Closed » et « All ». Cest le premier quil convient de consulter pour les demandes en cours. Cela vous fournit une liste, vous pouvez cliquer sur celle que vous souhaitez étudier.

Vous pourrez échanger avec la contributrice et les autres mainteneuses du dépôt principal dans lespace « Activity ». Vous avez les onglets « Overview », « Commits », « Pipelines » et « Changes » qui permettent de suivre ce que la Merge request comporte comme contenu. Les réponses, remarques etc. apparaissent dans leur ordre chronologique par défaut, mais cela peut se filtrer/changer avec les paramètres dans le menu déroulant à droite.

Les éléments à vérifier

La emrge request doit avoir sa case squash commits when merge request is accepted afin de réduire tous les ajouts à un seul commit dans lhistorique de la branche principale.

Une merge request doit avoir un message de commit qui respecte les conventions (voir la section Les commits).

Lorsque le contenu vous semble correct pour une fusion dans la base principale, mais que vous ne souhaitez attendre dautres avis, vous pouvez cliquer sur « Approve ». Cela signalera juste aux autres utilisatrices que vous êtes daccord pour le merge.

Lorsque vous pensez que la contribution doit être intégrée au projet, vous pouvez cliquer sur « Merge », en laissant les autres options telles que par défaut. Vous pouvez également estimer quil faut dautres validations / « Approvals » avant de faire cette opération.

Si vous estimez que la contribution nest pas adaptée et doit être refusée, vous pouvez cliquer sur « Close merge request » qui fermera la demande sans intégrer son contenu au dépôt principal.

Les commits

Généralités

Les messages de commit se rédigent en anglais de façon à faciliter la collaboration internationale.

Rédaction des commits

La rédaction des commits se base sur les conventionnal commits avec des spécificités.

Structure dun message de commit :

<type>(portée, facultative): sujet
<ligne vide> (si élément suivant présent)
Corps de description plus complète (un ou plusieurs paragraphes), facultatif
<ligne vide> (si élément suivant présent)
<pied de page>, facultatif
Les types

Les types de commits possibles sont les suivants (par ordre alphabétique):

  • ci : concerne le fonctionnement de la CI du dépôt (entraîne un changement de type bugfix dans le versionnement).
  • docs : reprise de la documentation du code sans toucher aux fonctionnalités (entraîne un changement de type bugfix dans le versionnement).
  • feat : ajoute une fonctionnalité qui doit être mentionnée dans le pied de page avec un hashtag et son numéro de ticket (entraîne un changement de type minor ou major, selon le cas, dans le versionnement).
  • fix : résoud un bug qui doit être mentionné dans le pied de page avec un hashtag et son numéro de ticket (entraîne un changement de type bugfix dans le versionnement).
  • refactor : refactorisation du code sans modifier son comportement, ajouter une fonctionnalité ou réparer un bug (entraîne un changement de type bugfix dans le versionnement).
  • removed : effacement dune partie jugée inutile, redondante ou obsolète (entraîne un changement de type minor ou major, selon le cas, dans le versionnement).
  • security : gestion dune vulnérabilité (entraîne un changement de type minor ou major, selon le cas dans le versionnement).
  • style : reprise formelle du code sans en modifier le fonctionnement (typos, espacements, tabulations etc.) (entraîne un changement de type bugfix dans le versionnement).

Le cas échéant, il est possible dajouter de nouveaux types selon les besoins (se référer à la convention Angular ou Keep a Changelog par exemple). Il faut alors penser à modifier les scripts de génération de changelog en conséquence (ainsi que les conséquences sur les séquences de versionnement).

Le type doit être écrit en minuscule, sans espace.

La portée (facultatif)

Indiquée entre parenthèses, en minuscule sans espace, elle permet de préciser éventuellement sur quel partie du code la modification porte.

Elle peut être choisie dans cette liste :

  • core : concerne le code de base, les systèmes essentiels au fonctionnement du jeu
  • ui : concerne linterface utilisateur
  • shading : concerne les shaders daffichage
  • ia : concerne lintelligence artificielle des créatures en jeu

Dautres portées peuvent être ajoutées à la liste au fur et à mesure des besoins.

Rupture de compatibilité

Si le commit entraîne une rupture de compatibilité dans le code, le type doit se voir accoler un point dexclamation avant les deux points, quel que soit son type (entraîne un changement de type majeur dans le versionnement).Il faut alors également lui ajouter un pied de page avec la mention « BREAKING CHANGE: » suivi de la mention de lendroit où la rupture sopère.

Le sujet

Laissant une espace après les deux points, il ne comporte pas de majuscule au début ni de point à la fin.

Le sujet doit décrire en peu de mot le changement quopère le nouveau code.

Exemples de première ligne correcte :

    feat(ui)!: change methods for IG windows, close #18
    fix(core): address collision problems for player, close #37
    feat: add color wheel for windows background, close #16
Corps de description

Facultatif, il permet de décrire de façon détaillée ce qui a motivé les choix opérés et mettre lemphase sur les améliorations espérées par rapport à lancien état.

Pied de page

Il peut comporter deux éléments :

  • si le commit clôt un ticket, il faut indiquer sur une ligne son numéro de la façon suivante : « Close #58 »
  • si le commit entraîne une rupture de compatibilité, il doit comporter une ligne avec la mention « BREAKING CHANGES » en majuscules.

Projets Godot

Il nest pas utile de versionner le répertoire .import/ situé à la racine dun projet car son contenu peut être généré depuis les fichiers originaux et leur fichier de configuration annexe (avec lextension .import, par exemple pour icone.png cela donne icone.png.import). Il convient donc dajouter le répertoire .import/ dans le .gitignore comme cest proposé dans la documentation Godot.

Pipeline Blender vers Godot

Export glTF par défaut (objets inanimés)

Les objets à destination du moteur de jeu Godot doivent être exportés au format glTF. Il faut pour cela sélectionner tous les objets à exporter puis aller dans File > Export > glTF, avec les options suivantes à vérifier particulièrement :

  • Format > glTF Embeddded.
  • Copyright : Khaganat.
  • On peut cocher Remember export settings pour ne pas avoir à revérifier à chaque export de ces modèles.
  • Include > Limit to Selected Objects coché.
  • Data > Mesh > Apply modifiers coché.

Les autres options par défaut conviennent.

Le pipeline pour les objets animés

Les objets animés avec une armature de déformation sont modélisés et conçus dans Blender, puis exportés vers Godot. Les principes appliqués proviennent des méthodes initiées par Richard Lico, en particulier pour le développement du jeu Moss. Il sagit de différencier les ressources et les outils, et de ne pas se préoccuper de ces derniers tant quils permettent aux intervenants de travailler efficacement avec leurs outils propres et, surtout, façons personnelles. La documentation ne comporte que des instructions pour travailler sous Blender.

Le mesh de base

Le mesh de base est sauvegardé dans son propre fichier, et sera inséré avec un Link depuis le fichier où se trouve son armature de déformation. Il doit se situer à la racine de la collection Khanat, avec un weight painting adapté à son armature de déformation.

Larmature de déformation

Larmature de déformation est conservée dans son propre fichier, sans rien dautre dans sa collectionKhanat. Elle peut être ainsi être utilisée par plusieurs meshes en créant un Link.

Les animations

Les animations sont conservées uniquement sous format glTF, avec une seule animation par fichier.

Importer une animation dans Blender

Afin de travailler une animation, il est possible de la récupérer dans le dépôt, où elle est sous format glTF. Une fois le fichier à récupérer identifié, il faut limporter avec les préférences suivantes : Import d’une animation glTF dans Blender

Éditer/ créer une animation dans Blender

Une animation peut être éditée depuis nimporte quel fichier local, avec ses propre préférences de travail. Il suffit dy importer le mesh avec son armature de déformation, puis dappliquer à ce dernier le rig de contrôle souhaité qui permettra de procéder au travail de création/édition souhaité. Chaque animateur pourra recourir à la méthode quil préfère, comme le propose Richard Lico dans une conférence du GDC en 2018 ( Animating Quill: Creating an Emotional Experience). Le studio Dypsloom propose un addon spécialement développé pour ce genre de travail : Rig On the Fly.

Sauvegarder une animation depuis Blender

Pour sauvegarder lanimation créée pour une armature depuis Blender :

  1. sélectionner larmature de déformation en mode objet, puis Object > Animation > Bake action
  2. indiquer les préférences suivantes et valider par OK: Bake action dans Blender
  3. `File > Export > glTF 2.0 (.glb/.gltf)
  4. Les préférences dexportation à indiquer sont les suivantes : Spécifications d’export glTF des animations depuis Blender Il est conseillé de se créer un Operator preset afin de ne renseigner ces éléments quune fois.
  5. Indiquer le nom ainsi que le chemin de destination appropriés et valider (voir Les conventions de nommage)
Importer les animations dans Godot en tant que ressources

Il faut faire en sorte que lanimation devienne une ressource qui pourra être appelée dans un Animation Player. Travailer ainsi permettra de ne plus avoir à se soucier des scènes héritées, nimporte quel élément de ces dernières pouvant avoir été manipulée dans Godot depuis son importation. Appeler des ressources secondaires permet dajouter de nouveaux éléments importés qui se rapportent à dautres éléments anciennement ajoutés également depuis une source externe.

Une fois les fichiers visibles dans larborescence de Godot (fichiers .glb) :

  1. double-cliquer dessus permettra dafficher la fenêtre des paramètres dimportations.
  2. sélectionner à droite laction à importer (bone_turndans lexemple ci-dessous) et paramétrer la partie Save To Fileen cochant Enabledet Keep Custom Trackset en indiquant le chemin où la ressource sera enregistrée dans Path. Importer une animation dans Godot en tant que ressource
Ajouter manuellement une animation dans une node AnimationPlayer sous Godot

Lorsquon a importé un certain nombre de ressources danimations qui peuvent concerner le même objet (typiquement les actions dun mesh avec son armature), il est possible de les ajouter à la node AnimationPlayerqui lanime :

  1. sélectionner la node AnimationPlayerà compléter
  2. aller en bas dans longlet Animationet cliquer sur le menu de cette zone, sélectionner Manage Animations Gérer les animations d’un AnimationPlayer dans Godot
  3. Dans la fenêtre popup qui souvre, cliquer sur licône pour ouvrir une ressource existante et aller là où se trouve laction à ajouter. Ajotuer une animation à un AnimationPlayer dans Godot

License

CC BY SA Khaganat - 2022