Outils pour utilisateurs

Outils du site


dindomoteur_mise_en_place_un_moteur_de_jeu_video

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
dindomoteur_mise_en_place_un_moteur_de_jeu_video [2022/03/13 18:42] Simon Deplatdindomoteur_mise_en_place_un_moteur_de_jeu_video [2022/03/20 11:11] (Version actuelle) – supprimée Simon Deplat
Ligne 1: Ligne 1:
-====== DindoMoteur : Mise en place d'un moteur de jeu vidéo ====== 
  
-=====Contexte===== 
-Cela fait maintenant 5 ans que j'utilise régulièrement **le moteur de jeu vidéo libre [[https://godotengine.org/|Godot]]**. 
- 
-Celui-ci a accompagné ma découverte du développement informatique, et **il prend de l'ampleur**, rejoignant [[https://www.blender.org/|Blender]] dans le registre des outils libres qui agrègent assez de contributeurs et de d'utilisateurs pour devenir **des logiciels équivalents aux alternatives propriétaires**. 
- 
-Au cours de mes recherches, j'ai fini par me rendre compte que **la plupart des jeux vidéos ayant eu un impact culturel ne s'appuient en général pas seulement sur un moteur généraliste**. Ces moteurs, comme //Godot//, //Unity//, //Unreal Engine// ou encore //RPG Maker//, sont **des frameworks dédiés à la création de jeu vidéo mettant en place des outils graphiques et un langage de programmation qui facilite la mise-en-place de certains outils nécessaires au développement du logiciel**. 
- 
-**Si ce sujet vous intéresse, vous devriez essayer de coder un petit jeu vidéo via la librairie python [[https://fr.wikipedia.org/wiki/Pygame|Pygame]], puis en développer un second en utilisant Godot.** Vous vous rendrez alors compte qu'**un grand nombre des fonctionnalités à recoder soi-même en //Pygame// (par exemple les //hitbox//) sont maintenant pleinement intégrés dans //Godot//**, qui, de surcroît, intègre un framework graphique. 
- 
-Ces moteurs généralistes, donc, mettent en place l'ensemble des outils nécessaires à coder rapidement un jeu vidéo, mais **leur aspect généraliste ne les rend pas capables de créer autre chose qu'un clone de jeu vidéo existant**. Ils agrègent d'une certaine manière les algorithmes redondants du monde du jeu vidéo une fois qu'un nombre assez grand de jeux vidéos les proposent. 
- 
-Par exemple, **le jeu [[https://fr.wikipedia.org/wiki/Wolfenstein_3D|Wolfenstein 3D]] était le premier jeu vidéo en trois dimensions**. À son époque, ce sont les développeurs qui ont codé le moteur de 3D qu'il utilise, puis, devant le succès et la prouesse de l'algorithme, de nombreux autres développeurs l'ont copié. **Maintenant, un moteur comme //Godot// intègre nativement cet algorithme.** 
- 
-Or, ce qui fait le charme de nombreux jeux, c'est le caractère unique du //gameplay// qu'ils proposent. Ils ne peuvent se contenter d'utiliser le moteur généraliste : **il est nécessaire de recréer un sous moteur spécialisé à l'aide du moteur généraliste**. 
- 
-À titre d'exemple, on peut penser à l'algorithme de téléportation du jeu [[https://fr.wikipedia.org/wiki/Portal_(jeu_vid%C3%A9o)|Portal]], le système d'énigme de [[https://fr.wikipedia.org/wiki/Baba_Is_You|Baba Is You]], ou encore l'environnement modulable de [[https://fr.wikipedia.org/wiki/Minecraft|Minecraft]]. 
- 
-En réalité, ces exemples sont des exemples assez avancés qui mettent facilement en valeur la nécessité de respécialiser un jeu par rapport à un concept généraliste. **L'utilisation des menus comme espaces de jeu** et non plus comme simple espace de documentation et de paramétrages dans les //RPG//, par exemple dans les premiers [[https://fr.wikipedia.org/wiki/Pok%C3%A9mon_Rouge_et_Bleu|Pokémon]], **est déjà une mise-en-place d'un //gameplay// particulier au sein d'une architecture classique**. 
- 
-=====Objectif===== 
-**Mon objectif est de construire, de manière incrémentale, un moteur de jeu vidéo libre et documenté en français qui permette de cloner des jeux d'aventures de type //[[https://fr.wikipedia.org/wiki/Metroidvania|metroidvania]]//**, comme [[https://fr.wikipedia.org/wiki/Hollow_Knight|Hollow Knight]] ou [[https://fr.wikipedia.org/wiki/Dead_Cells|Dead Cells]]. 
- 
-En prenant soin de documenter le projet, **le but est de pouvoir disposer d'un moteur intégrant déjà les paramètres classiques, modifiables aisément** (si possible via des interfaces graphiques). Une fois ce sous-moteur généraliste en place, le but est de **pouvoir facilement re-spécialiser le //gameplay// en ajoutant du code dédié**. 
- 
-Une fois le moteur en place, il devient possible de **le mettre à disposition de //designer// et d'artistes pour réaliser des versions concrètes de jeux vidéos à chaque point d'étape**. Dans cette optique, chaque jeu vidéo associé au moteur correspond à une spécialisation du moteur. 
- 
- 
-=====Godot : kézako ?===== 
-**Godot est donc un moteur de jeu vidéo libre.** 
- 
-Il intègre à la fois **une interface graphique de programmation et un langage nommé //gdscript//**, basé sur la syntaxe python. Il reste également possible de coder en //C++// directement. 
- 
-**Le langage manipulé est orienté objet**, et c'est ce qui fait la force de Godot : il intègre de nombreuses classes communément utilisées dans la programmation : //sprites//, animations, gestion de collision, parallaxes, entrées utilisateurs, etc... Grâce au système d'héritage, il est alors possible de **créer et instancier ses propres objets, qui, dans la sémantique propre à **Godot**, sont nommés des //scènes//**. 
- 
-Dans la philosophie du moteur, **une //scène// correspond en général à un objet (au sens humain) particulier**. Un exemple typique est l'idée qu'une //scène// Village contiendra une //scène// Maison, qui contiendra une //scène// Table, etc. 
- 
-**Concernant la gestion des coordonnées, c'est le système vectoriel qui est utilisé**, comme à l'accoutumée dans les jeux vidéos. 
- 
-**Les objets étant organisés selon un système d'arbre**, les coordonnées d'une scène sont modifiées par l'ensemble des parents ce qui, dans l'exemple précédent, permet de bouger la Table en même temps que la Maison. 
- 
-Pour plus d'infos sur Godot, [[https://docs.godotengine.org/en/stable/|RTFM]]. 
- 
- 
-=====Base de travail===== 
-**Godot intègre une librairie de ressources (//Asset Library//) qui permet de voir comment utiliser le moteur de manière efficiente à l'aide de projets didactiques.** 
- 
-Dans notre cas, c'est le //2D Platformer Demo (KinematicBody)// qui servira de base de travail pour le développement du sous-moteur. 
- 
-**Celui-ci intègre déjà les fonctionnalités de base d'un //metroidvania// très simple** : personnage contrôlable, plateformes mouvantes, prototype d'AI, objets à ramasser... 
- 
-Nous allons donc commencer par décortiquer cet exemple et en reconstruire les fonctionnalités principales dans un nouveau projet. 
- 
-Mais avant ça... 
- 
-=====Organisation du répertoire===== 
-Dans sa documentation, **Godot conseille d'organiser les scènes et ressources de telle manière à ce que celles-ci soient facilement transférables d'un dossier à l'autre**. 
- 
-Un des problèmes inhérents à l'organisation nodale décentralisée est le fait que **certaines relation d’interdépendance concernent des objets qui ne sont pas localisés au même endroit** : il devient donc difficile de copier-coller certaines scènes dans d'autres projets, et modifier localement une ressource peut avoir des conséquences sur un autre endroit du programme. Il est donc nécessaire de séparer le plus possible les objets les uns des autres et de permettre des mécanismes de sécurité afin de palier au manque d'une ressource externe. 
- 
-Également, il devient difficile de se retrouver dans l'arborescence de fichier dans certains cas. la documentation de //Godot// propose donc de **regrouper les fichiers par thématiques** : un //répertoire// Personnage, un //répertoire// Lieu, un //répertoire// Dialogue, etc. 
- 
-Dans le cas du //Platformer//, **le répertoire principal est lui-même divisé en deux répertoires** : //src// et //assets//. //src// contient les éléments propres à Godot : les scènes et les scripts. //assets// contient les données du jeu, comme les images, les sons, etc. 
- 
-Comme évoqué précédemment, le dossier //src// est lui-même sous-divisé en répertoire thématiques : //Actors//, //Level//, //Main//, etc . 
- 
-**Nous garderons le même principe d'arborescence pour le moteur.** 
- 
-=====Mise en place des systèmes globaux===== 
-Avant même de créer la première scène, il s'agit de **mettre en place certains mécanismes généraux** pour le moteur de jeu. Cela concerne : 
-  * Le **nom des entrées utilisateurs et les boutons qui y sont associés**. 
-  * La **résolution de base** ( 1920 x 1080 ) et **le système de mise à l'échelle utilisé pour les moniteurs plus petits**. 
-  * La **création d'un script global** pour centraliser un certain nombre de paramètres de jeu (en faisant attention au risque d'interdépendance des nœuds ultérieurs). 
- 
-=====Mise en place des entrées utilisateurs===== 
-Le moteur étant particulièrement chauvin, je commence par **utiliser l'interface d'association des entrées utilisateurs ( //Projet > Paramètres du projet... > Contrôles// ) pour associer les touches du clavier aux mots-clefs suivants** : 
- 
-  * q : "gauche" 
-  * d : "droite" 
-  * s : "bas" 
-  * z : "haut" 
-  * espace : "espace" 
- 
-Même s'il est **conseillé d'associer des mot-clefs par action plutôt que par touche**, les différentes utilisations de la touche //espace// possibles m'amènent à garder une balise généraliste pour ce cas particulier. 
- 
-{{ ::dm_inputmapping.jpg?800 |}} 
- 
-=====Paramétrage de la fenêtre===== 
-J'utilise maintenant //Projet > Paramètre du projet... > Général > Window// afin d'assigner la résolution de la fenêtre principal. 
- 
-**De manière générale, les jeux sont maintenant affichés en plein écran avec une résolution de 1920 par 1080 pixels.** Dans notre cas nous voulons néanmoins rester sur un affichage fenêtré afin de faciliter le développement (même si cela peut permettre de ne pas oublier d'arrêter le programme une fois que les vérifications ont été faites). 
- 
-Pour **les questions de redimensionnement**, je modifie, dans l'onglet //Stretch//, les paramètres suivants : 
-  * Mode : 2d 
-  * Aspect : keep 
- 
-Il faudra peut-être revoir ultérieurement ces réglages. 
- 
-=====Création de la scène Main===== 
-Afin de pouvoir tester les réglages graphiques, **il est nécessaire d'avoir une scène principale dans //Godot//**. 
- 
-Je créé donc une scène //Main.tscn// dans le répertoire //src/Main/// . 
- 
-Afin de rester polyvalent, cette scène sera de type //Node//, qui est la //classe// maîtresse dans //Godot//. 
- 
-=====Mise en place d'un nœud global===== 
-Je vais maintenant **utiliser le système d'//AutoLoad// de //Godot// afin de mettre en place un nœud global**. 
- 
-Il est possible dans //Godot// d'**instancier les scènes indépendamment les unes des autres**, ce qui est parfois problématique au cas où celles-ci auraient besoin d'autres scène pour fonctionner correctement. 
- 
-**Ce nœud global sera chargé automatiquement à chaque lancement du programme** ce qui lui permettra de centraliser l'ensemble des ressources nécessaires à chaque scène pour fonctionner. Dans certains cas, il pourra également simuler l'existence de certaines scènes pour résoudre des problèmes de dépendance. 
- 
-Pour autant, **il serait préférable que chaque scène soit dotée d'un mécanisme tel que :** 
-  * si la scène est lancée seule, un mécanisme est mis-en-place pour bloquer les méthodes nécessitant l'accès à des nœuds externes et au nœud global. 
-  * si le nœud global est activé, l'absence de ressources externe peut être substituée par ce nœud global. 
-  * si la ressource externe est chargée également, celle-ci a la priorité sur les méthodes décrite ci-dessus. 
- 
-Pour mettre en place le nœud global, je créé un script global.gd situé dans le répertoire //src/Main/// puis utilise le menu //Projet > Paramètres du projet... > AutoLoad// pour lui assigner le nom //Global//. 
- 
-**Le mot //Global// permet maintenant d'y accéder depuis n'importe quelle scène** ( exemple : //print( Global.attribut )// ). 
- 
- 
-=====Création d'un joueur et d'une plate-forme===== 
-Je souhaite dans un premier temps **avoir un simple joueur contrôlable ainsi qu'une plate-forme sur lequel celui-ci puisse se mouvoir**. 
- 
-Dans un premier temps, **je créé deux répertoire dans //src/// : //Joueur/// et //Niveau/// **. 
- 
-Je remarque que dans //Platformer//, il y a un répertoire //Platform/// dédié aux plate-formes. Nous verrons en temps voulu si c'est pertinent, commençons simplement pour l'instant. 
- 
-Pour l'instant, avant toute logique de déplacement et de collision, **je souhaite simplement que ces deux objets soient affichés à l'écran**. J'utilise donc //Inkscape// pour créer deux //sprites// qui leurs correspondent. 
- 
-À ce stade, **il est important de choisir une unité de référence** pour plus tard : nous serons amenés à utiliser des //tilemaps// pour générer plus facilement les niveaux et ceux-ci supposent que l'écran soit divisés en cases d'une certaine largeur. De manière arbitraire, **cette unité de référence sera la puissance de deux** ( 32 / 64 / 128 / 256 / 512 ). 
- 
-Dans notre cas, **la plate-forme de test fera 512 x 64 pixels**. 
- 
-Pour l'instant, je créerai **un dossier //assets/Dev/// qui contiendra les ressources temporaires liées au développement**. 
- 
-Voici les deux //sprites// utilisés pour l'instant : 
-{{ :joueur.png?128 |}} 
-{{ :plateforme.png?512 |}} 
- 
-Une fois les //sprites// réalisés, **je crée donc les scènes associées** : 
-  * pour le Joueur, un //Kinematic Body 2D// . 
-  * pour la plate-forme, un //Static Body 2D// . 
- 
-De manière intuitive, chacun d'entre eux aura **un nœud //Sprite// et une //Collision Shape 2D// de la bonne taille**. 
- 
-Ensuite, **je les ajoute au nœud Main en les instanciant**. Ils ne bougent pas, mais ils apparaissent à l'écran ! 
- 
-{{ ::dm_hw.jpg?400 |}} 
- 
-=====Mise-en-place des collisions===== 
-On commence par modifier les masques de collision pour faciliter le travail : 
-  * 1 : joueur 
-  * 2 : ennemis 
-  * 3 : objets 
-  * 4 : terrain 
-  * 5 : terrain2 
- 
-**On modifie les nœuds de collision afin qu'ils correspondent.** Pour l'instant, //terrain2// est laissé de côté. 
- 
-Dans les versions précédente de //Godot//, le //PlatFormer// n'utilisait pas de système d'héritage pour mutualiser l'attraction terrestre entre le joueur et les ennemis. C'est maintenant le cas, et le script //Player// hérite d'//Actor//, qui lui-même de //Kinematic Body 2D//. Nous comprenons l'intérêt de ce système, même si les scripts en deviennent moins intuitifs. 
- 
-Nous commençons par mettre en place un système similaire, en créant un répertoire //src/Personnage/// et un script //Personnage.gd// . 
- 
-Après quelques recherches, voici [[https://docs.godotengine.org/fr/stable/tutorials/physics/using_kinematic_body_2d.html|la documentation du système de collision que nous utilisons]]. 
- 
-À ce stade, nous avons donc le script //Personnage.gd// : 
- 
-<code> 
-class_name Personnage 
-extends KinematicBody2D 
- 
-export var masse = 60 
-onready var gravite = ProjectSettings.get( "physics/2d/default_gravity" ) 
- 
-const NORMAL_SOL = Vector2.UP 
- 
-var _velocite = Vector2.ZERO 
- 
-# la fonction _physics_process héritée est appelée 
-# après la fonction _physics_process héritée, parente 
-func _physics_process( delta ): 
- _velocite.y += gravite * masse * delta 
-</code> 
- 
-Ainsi que le script //Joueur.gd// : 
- 
-<code> 
-class_name Joueur 
-extends Personnage 
- 
-const DETECTION_DISTANCE_SOL = 20.0 
- 
-func _physics_process( _delta ): 
- var accrocheVectorielle = Vector2.DOWN * DETECTION_DISTANCE_SOL 
-  
- _velocite = move_and_slide_with_snap( 
- _velocite, 
- accrocheVectorielle, # Accroche au sol 
- NORMAL_SOL, # Direction du sol ( Vector2.UP ) 
- true, # Ne glisse pas sur le sol en cas d'inactivité ? 
- 4, # Nombre de collisions traitées par cycle 
- 0.9, # Angle maximum du sol ( en radians ) 
- false # Inertie infinie ? 
- ) 
-</code> 
- 
-Le personnage, emporté par son propre poids, est attiré vers le sol et s'y accroche à son contact. 
dindomoteur_mise_en_place_un_moteur_de_jeu_video.1647196978.txt.gz · Dernière modification : 2022/03/13 18:42 de Simon Deplat