Accueil logo MakeYourGame gachetteG gachetteD paddleG paddleH paddleD paddleB buttonG buttonH buttonD buttonB

Godot Engine : Un petit détour du côté de la 2.5D

Godot Engine

Dans ce tutoriel, on se propose de mettre en place une mécanique simple et fonctionnelle de jeu en 2.5D avec Godot Engine.
18 min Intermédiaire Dans la famille des jeux vidéos, il existe une catégorie de jeux un peu bâtarde qui celle des jeux en 2.5D. C'est le cas de jeux tels que New Super Mario Bros 2 (sorti sur 3DS), ou encore du jeu Tarzan (sorti sur playstation 1). C'est aussi le cas du jeu Inside, un jeu dont on s'inspirera dans la suite de ce tutoriel. Il existe bien sûr un grand nombre d'autres jeux ayant adopté cette approche. Ces jeux ne sont ni complètement en 3D -car le mouvement est contraint selon un plan- ni plus vraiment en 2D (l’environnement dans lequel nous évoluons est un environnement 3D). Cela dit, ils possèdent deux grands avantages :
  1. Les mouvements du joueurs sont à peu près aussi simples à gérer qu'en 2D.
  2. Les décors 3D apportent un profondeur de champs très intéressante qui peut même parfois rendre ces jeux plus simples à concevoir que des jeux en 2D !
Dans ce tutoriel, on se propose de mettre en place les mécaniques de bases d'un jeu en 2.5D avec Godot Engine.

Mise en place de la scène

La scène de base

Pour ce tutoriel, on ne démarrera pas à partir de rien. La scène de base ressemblera à ceci : https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201009225129-5f8186866f4d6.png Cette scène ne contient aucun modèle 3D complexe, uniquement des cubes de différentes tailles. Ces cubes sont des MeshInstances redimensionnés pour les circonstances. Notez qu'il est inutile de les assigner un quelconque comportement physique (donc inutile de les attacher à un PhysicBody) à l'exception notable du sol qui est un StaticBody. Le sol est en effet le seul élément avec lequel notre personnage interagira. Vous êtes bien sûr libre de concevoir la scène que vous voulez pour ce cours. Ceux qui ne souhaitent pas y passer de temps peuvent retrouver le fichier intégral ici : Main.tscn

Amélioration du rendu

Pour commencer, nous allons améliorer un peu le rendu de notre scène en y ajoutant un nœud de type WorldEnvironment. Ensuite, nous allons redéfinir la propriété Environment de notre WorldEnvironment en cliquant sur [empty] puis New Environment. Quand nous faisons cela, tout devient noir/gris dans notre scène. Beurk. https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201009230453-5f81868187bef.png Pas de panique ! Nous définissons notre environnement à partir de rien, il est normal que ça ne ressemble à rien au début. Nous allons créer une ambiance sombre, proche de ce qu'on peut trouver dans le jeu Inside. Changeons les propriété suivantes dans notre Environment :
  • Background / mode : Color+sky
  • Ambient Light / color : #a9a9a9
  • Fog :
    • Enabled : On
    • Color : #1d1d1d
    • Depth Begin : 7
Nous avons ajouté une lumière ambiante ainsi qu'un petit brouillard. Si nous zoomons un peu, nous obtenons : https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201009231311-5f81867c5ca81.png L'ambiance commence à être plus sympathique. Le brouillard (Fog) permet de faire disparaître les objets desquels nous nous éloignons. Néanmoins, notre décors a parfois du mal à ressortir par rapport au sol. Pour régler ce problème et améliorer le rendu général, nous allons ajouter une lumière directionnelle à notre scène. Ajoutez un noeud DirectionalLight à la scène et donnez à sa Transform les caractéristiques suivantes : https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201009231832-5f818701f00dd.png Nous obtenons : https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201009231928-5f8187295622a.png Notre chemin se détache bien mieux !
Vous pouvez également, si l'effet vous plaît, activer les ombres en cliquant sur Shadow/enabled dans les propriétés de votre lumière.
Notre scène a maintenant une ambiance un peu plus personnelle. Ajoutons notre personnage.

Ajout du personnage

Notre personnage sera un simple cube rouge que nous ajouterons à notre scène au sein d'un KinematicBody. Ajoutons ce KinematicBody et ajoutons-lui comme enfant un MeshInstance ayant pour mesh un CubeMesh. Grossissez ce mesh en jouant sur sa scale https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201009233458-5f8186753a427.png Une fois cela fait, nous pouvons créer une CollisionShape à partir de ce Mesh en sélectionnant notre Mesh puis en cliquant sur https://makeyourgame.fun/upload/users/cevantime/RollTheBall/capturedu20200804181238-5f2ac09cbf168.png puis create single convex collision sibling dans la barre du haut. Déplacez ensuite votre KinematicBody à un endroit quelconque de votre scène (vous pouvez vous aider du bouton https://makeyourgame.fun/upload/users/cevantime/Initiation3d/capturedu20200706231224-5f0dd6f594a43.png puis Snap To Floor afin de poser votre Cube sur le sol). Nous obtenons : https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201009234253-5f81866e27d47.png Nous pouvons aussi changer la couleur de notre cube ajoutant un SpatialMaterial au MeshInstance et en modifiant la color de sa propriété albedo. Un fois cela fait, il est temps de commencer à coder le comportement de notre cube/personnage.

Déplacer le personnage le long d'un chemin

Configurer notre chemin

Pour que notre cube se déplace en mode 2.5D, il faut lui définir un chemin à suivre. Godot possède dans sa boîte à outil intégrée un nœud des plus utile appelé Path. Ce nœud, comme son nom l'indique, permettra de définir le chemin que doit emprunter notre cube. Ajoutez ce nœud Path à votre scène. Vous avez maintenant la possibilité d'ajouter/supprimer/déplacer des points à votre chemin à l'aide des boutons dédiées situés dans la barre du haut :  https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201010112426-5f81863ad63c6.png https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201009235230-5f818666158ea.png L'enjeu maintenant est de déplacer notre personnage le long de ce chemin. Il existe plusieurs manières de faire. La nôtre va consister à privilégier l'emploi des nœuds au maximum afin de bien visualiser ce qu'on fait. Nous allons donc ajouter un nœud PathFollow  à notre Path ainsi qu'un nœud Position3D  dans ce PathFollow. Cette Position3D est contrainte par le PathFollow à suivre le chemin Path. Vous pouvez essayer de faire varier la propriété offset de votre PathFollow et visualiser que la position3D parcoure le chemin. L'idée est que notre Cube suive cette position tout en restant libre de ses mouvements verticaux (selon l'axe des y) pour les sauts. Voyons comment scripter ceci.  

Scripter le déplacement du cube

Ajoutons un script à notre cube et plaçons-y le code inital suivant :
extends KinematicBody


func _physics_process(delta):
   var input_h = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
Ce code récupère les entrées gauche et droite de l'utilisateur (les touches gauche et droite du clavier par exemple) au sein d'une fonction _physics_process. Cette fonction _physics_process est généralement le meilleur endroit pour gérer le déplacement d'un KinematicBody.

Déplacement en 2D pure

Mettons en place le code minimal pour le contrôle de notre Kinematic dans un jeu purement 2D.
extends KinematicBody

export(float) var SPEED = 15.0

var velocity = Vector3.ZERO

func _physics_process(delta):
   
   var input_h = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
   
   velocity.x = input_h * SPEED
   
   velocity = move_and_slide(velocity)
Ce code permet purement et simplement de déplacer notre Cube selon l'axe horizontal (l'axe des X). Il est quasiment transposable en l'état à un contexte de jeu en 2D (en remplaçant le Vector3 par un Vector2).
Nous utilisons la fonction move_and_slide de notre Kinematic afin de gérer d'office les collisions. Cette fonction prend en paramètre une vélocité dont elle retourne un valeur corrigée. Pour l'instant, nous nous contentons de faire varier cette vélocité selon l'axe des x ce qui a pour effet de déplacer notre cube horizontalement. Nous pouvons également prendre en compte le saut en faisant varier la vélocité selon l'axe vertical (axe des Y). Le code suivant, qui prend en compte le saut, est tout autant utilisable en 2D :
extends KinematicBody

export(float) var SPEED = 15.0
export(float) var JUMP = 10.0
export(float) var GRAVITY = 9.81

var velocity = Vector3.ZERO

func _physics_process(delta):
   
   if Input.is_action_just_pressed("ui_accept"):
      velocity.y += JUMP
      
   velocity.y -= GRAVITY * delta
   
   var input_h = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
   
   velocity.x = input_h * SPEED
   
   velocity = move_and_slide(velocity)
Avec ce code, vous pouvez déjà gérer certains jeux en 2.5D sans notion de profondeur de déplacement. Voyons comment gérer un cas plus complexe ou notre personnage doit suivre notre chemin.

Suivre le chemin

Pour vérifier que nous pouvons nous déplacer, nous devons ajouter une Camera à notre scène. Nous pouvons pour l'instant l'ajouter à notre Kinematic afin qu'elle suive ce dernier. Repositionnez-la dans votre scène à l'endroit qui vous paraît le plus judicieux. https://makeyourgame.fun/upload/users/cevantime/25d/capturedu20201010003154-5f81865f235f2.png Si vous lancez votre scène maintenant, vous constatez que le cube se déplace et saute, ce qui est bien, mais pas selon le chemin que nous avons défini ! Faisons en sorte que ce soit le cas. Pour cela, commençons par récupérer les noeuds dont nous aurons besoin, à savoir le PathFollow et la Position3D, au sein de notre script !
# ...
var velocity = Vector3.ZERO

onready var path_follow = get_parent().get_node("Path/PathFollow")
onready var position_ref = path_follow.get_node("Position3D")

func _physics_process(delta):
# ...
Remplaçons cette ligne :
velocity.x = input_h * SPEED
par cette ligne :
path_follow.offset += input_h * SPEED * delta
Nous faisons varier l'offset de notre pathfollow ce qui va avoir pour effet de déplacer notre Position3D de référence. Ceci ne déplace par pour autant notre cube. Pour le déplacer nous devons être en mesure définir notre fameuse velocity puisque c'est elle que nous passerons à move_and_slide.  Pour trouver cette vélocité, nous allons simplement calculer la différence de position entre la position actuelle du cube et la position visée (en excluant la composante y qui est indépendante) :
path_follow.offset += input_h * SPEED * delta
   
var target = position_ref.global_transform.origin
target.y = global_transform.origin.y
   
var diff = target - global_transform.origin
Nous ne pouvons pas définir notre différence de position comme étant notre vélocity (bien que ce soit tentant). En effet, move_and_slide multipliera cette velocité par delta ce qui n'est pas pris en compte par notre diff. D'autre part, diff n'est pas censé impacter la composante y de la vélocité. le code doit donc ressembler à ceci :
path_follow.offset += input_h * SPEED * delta
   
var target = position_ref.global_transform.origin
target.y = global_transform.origin.y
   
var diff = target - global_transform.origin
   
diff /= delta
   
velocity.x = diff.x
velocity.z = diff.z
   
velocity = move_and_slide(velocity)
Maintenant, quand nous exécutons notre programme, nous obtenons : https://makeyourgame.fun/upload/users/cevantime/25d/peek101020201049-5f81865492ed6.gif Magnifique, notre cube suit notre chemin ! Les bases sont posées.

Regarder dans la direction du déplacement

Notre cube se déplace bien sur le chemin mais ne regarde pas dans la direction dans laquelle il va ! Réglons ce problème en utilisant une fonction très utile de nos transforms : looking_at !
# ...
var diff = target - global_transform.origin
   
if diff.length() > 0.01:
    global_transform = global_transform.looking_at(target, Vector3.UP)
   
diff /= delta

# ...
Nous devons au préalable vérifier que notre élément se déplace bien un petit peu, autrement looking_at ne fonctionne pas. Quand nous testons, nous voyons que cela fonctionne mais que nous avons introduit un nouveau "bug". https://makeyourgame.fun/upload/users/cevantime/25d/peek101020201113-5f81864b7a7e0.gif Notre caméra suit la rotation de notre cube. Ce n'est pas inintéressant mais ce n'est pas ce que nous avions en tête. Corrigeons cela en utilisant la petite astuce du RemoteTransform. Voici la procédure :
  • Ajouter un noeud RemoteTransform à notre cube.
  • Ajouter un Spatial à la racine de notre scène, et nommez-le CameraRef.
  • Faire en sorte que le RemoteTransform transmette sa position et uniquement sa position au CameraRef.
  • Déplacer (reparenter) la caméra dans le noeud CameraRef.
Vous devriez avoir maintenant une caméra qui ignore les changements de direction du cube. https://makeyourgame.fun/upload/users/cevantime/25d/peek101020201121-5f81864011ea7.gif? C'est à peu près tout !... Bon, comme vous pouvez le constater, les changements de direction du cube sont un peu abruptes. Vous pouvez régler le problème en adoucissant les angles de votre chemin. Pour ce faire, sélectionnez votre chemin et maintenez le bouton Maj enfoncé tout en cliquant un des points du chemin. Vous devriez voir apparaître deux boutons supplémentaires permettant de fluidifier la courbure du chemin. Vous pouvez vous mettre en vue du dessus (plus pratique) : https://makeyourgame.fun/upload/users/cevantime/25d/peek101020201128-5f8186359904f.gif Bien nous en avons fini avec ce tutoriel. Il nous reste encore plein de pistes d'améllioration qui donneront peut-être lieu à un autre tutoriel :
  • Visualisation du plan dans lequel s'inscrit le personnage (en plus du chemin)
  • Gestion plus fine de la caméra (zoom/dézoom contextuel)
  • Possibilité de changer de chemin en fonction de la zone !
Rendez-vous dans un prochain tutoriel (restez connectés!)
Vues: 99

Connectez-vous pour applaudir applause logo 0 claps

Validation du Tutoriel

Veuillez vous connecter ou créer un compte pour pouvoir valider ce tutoriel et ainsi gagner stardust et XP !

×