Les collisions sont une des bases du Game Design et un élément qui représente une somme de travail assez conséquente lors de la phase de conception d’un jeu.

Nous allons voir à quel point le système de collision est simple et hautement intégré dans Godot via GDScript.

Qu’est ce que la collision

Avant toute chose, il convient de se poser un instant pour comprendre ce qu’est une collision et quel sont les éléments qui entrent en jeu.

Une collision est donc, bien entendu, le fait que des surfaces ou des volumes partage un même espace au même moment.

Les éléments qui compose une collision sont donc :

  • Des surfaces ou des volumes, au minimum deux.
  • Une notion de temps.
  • Une notion d’espace et de déplacements (pas de collision possible avec des objets statiques).

Dans Godot, on retrouve donc ces notions sous ces formes :

  • Les surfaces sont gérées par des nodes Collision* (CollisionShape2D, CollisionPolygon2D, etc.). Une fois pris en compte dans le code, deux nodes de ce type ne pourront plus partager un espace commun.
  • Une vélocité, exprimée en Vecteur2 qui sera géré automatiquement (donc égale à zéro en cas de collision) par la méthode move_and_slide() dans une class KinematicBody2D.
  • La notion de temps et la même que pour l’ensemble du jeu.

Exemple concret de collision 2D

Voyons donc un exemple concret sur un jeu 2D extrêmement simple qui consiste à simplement déplacer un player avec les touches flèches droite et gauche du clavier. Nous voulons simplement gérer une collision pour que le joueur ne puisse pas sortir de l’écran.

Nous avons :

  • Un node2D comme node principale.
  • Un node StaticBody2D en enfant du node principale.
  • Un node CollisionPolygon2D en enfant du StaticBody2D pour définir les zones de collisions.
  • Un « player » qui est une Branch scene.

Cette branch scene contient :

  • Un node principale de type KinematicBody2D.
  • Des sprites enfants.
  • Un node CollsionShapes2D pour définir l’espace de collision du joueur.

Nous allons gérer les collisions directement dans le node principale de Player de sorte que le code soit réutilisable plus tard si ce Player est utilisé dans un autre environnement 2D.

Code GDScript de gestion de collision 2D

C’est partie pour le script, on commence par créer deux variables:

  • Une variable « speed » de type int pour la vitesse de déplacement,
  • Une variable « vel » de type Vector2 pour la vélocité. On peut écrire également Vector2() comme ceci, sans argument, pour créer un vecteur avec des valeurs null.
extends KinematicBody2D

var speed = 100
var vel = Vector2(0, 0)

func _process(delta):
	pass

Ensuite, nous allons définir une action pour créer un mouvement. Bien entendu, afin que la méthode move_and_slide() puisse gérer les collisions, nous allons déplacer notre Player grâce à la vélocité et non pas grâce à la position.

extends KinematicBody2D

var speed = 100
var vel = Vector2(0, 0)

func _process(delta):
	if Input.is_action_pressed("ui_right"):
		vel.x += speed
	if Input.is_action_pressed("ui_left"):
		vel.x -= speed

Il ne reste plus qu’à insérer la méthode move_and_slide() et de lui passer notre vélocité en argument. La méthode se chargera seule de modifier la vélocité (en la passant à zéro) en cas de collision :

extends KinematicBody2D

var speed = 100
var vel = Vector2(0, 0)

func _process(delta):
	if Input.is_action_pressed("ui_right"):
		vel.x += speed
	if Input.is_action_pressed("ui_left"):
		vel.x -= speed
	move_and_slide(vel)
	pass

Maintenant testons notre jeu et observons ce que nous obtenons :

Le comportement n’est pas tout à fait celui escompté. En effet dès lorsque nous appuyons sur une touche, le personnage ne bouge quasiment pas puis accélère très rapidement.

Si on observe le code ci-dessus, ce comportement est normal : à chaque tick de jeu, la variable « vel » additionne et accumule la variable speed. Il faut donc la remettre à zéro à chaque tick en la déplaçant dans la fonction _process()

extends KinematicBody2D

var speed = 600

func _process(delta):
	var vel = Vector2(0, 0)
	if Input.is_action_pressed("ui_right"):
		vel.x += speed
	if Input.is_action_pressed("ui_left"):
		vel.x -= speed
	move_and_slide(vel).normalized()
	pass

Noter qu’on en profite pour prendre la bonne habitude de normaliser notre vecteur grâce à la méthode .normalized(). En effet, si l’on souhaite gérer des mouvements diagonaux, il est nécessaire de prendre cette habitude : la diagonale d’un vecteur à une valeur plus grande que ces autres composante. Il en résulterait une vitesse supérieur lors des mouvements en diagonale.

Comme nous gérons maintenant la vitesse de déplacement par un vecteur normalisé (de 0 à 1 donc), il est nécessaire d’augmenter drastiquement la valeur de la variable vitesse.

Résultat :

Et voila pour les bases de la gestion des collisions dans Godot via GDScripts.


0 commentaire

Laisser un commentaire