Up to date
This page is up to date for Godot 4.3.
If you still find outdated information, please open an issue.
Vue d'ensemble du mouvement 2D
Introduction
Tous les débutants se demandent : "Comment déplacer mon personnage ?". Selon le style de jeu que vous réalisez, vous pouvez avoir des exigences particulières, mais en général, les mouvements de la plupart des jeux en 2D sont basés sur un petit nombre de dessins.
Nous utiliserons CharacterBody2D pour ces exemples, mais les principes s'appliqueront tout autant aux autres types de nœuds (Area2D, RigidBody2D).
Configuration
Chaque exemple ci-dessous utilise la même configuration de scène. Commencez avec un CharacterBody2D avec deux enfants : Sprite2D et CollisionShape2D. Vous pouvez utiliser l'icône Godot ("icon.png") pour la texture du Sprite2D ou utiliser n'importe quelle autre image 2D que vous avez.
Ouvrez Projet -> Paramètres du projet et sélectionnez l'onglet "Plan des entrées". Ajoutez les actions d'entrées suivantes (voir InputEvent pour les détails) :
Mouvement 8 directions
Dans ce scénario, vous souhaitez que l'utilisateur appuie sur les quatre touches directionnelles (haut/gauche/bas/droite ou Z/Q/S/D) et se déplace dans la direction sélectionnée. Le nom "mouvement à 8 directions" vient du fait que le joueur peut se déplacer en diagonale en appuyant sur deux touches simultanément.
Ajoutez un script au character body et ajoutez le code suivant :
extends CharacterBody2D
@export var speed = 400
func get_input():
var input_direction = Input.get_vector("left", "right", "up", "down")
velocity = input_direction * speed
func _physics_process(delta):
get_input()
move_and_slide()
using Godot;
public partial class Movement : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 400;
public void GetInput()
{
Vector2 inputDirection = Input.GetVector("left", "right", "up", "down");
Velocity = inputDirection * Speed;
}
public override void _PhysicsProcess(double delta)
{
GetInput();
MoveAndSlide();
}
}
In the get_input() function, we use Input get_vector() to check for the
four key events and sum return a direction vector.
Nous pouvons alors définir notre vitesse en multipliant ce vecteur de direction, qui a une longueur de 1, par notre vitesse souhaitée.
Astuce
Si vous n'avez jamais utilisé de calcul vectoriel auparavant ou avez besoin d'une remise à niveau, vous pouvez voir une explication de l'utilisation des vecteurs dans Godot sur Mathématiques des vecteurs.
Note
Si le code ci-dessus ne fait rien lorsque vous appuyez sur les touches, vérifiez que vous avez correctement configuré les actions d'entrée comme décrit dans la partie Configuration de ce tutoriel.
Rotation + Mouvement
Ce type de mouvement est parfois appelé "style Asteroids" car il ressemble à la façon dont ce jeu d'arcade classique fonctionnait. Appuyez sur les touches gauche/droite pour faire pivoter le personnage, tandis que haut/bas le déplace vers l'avant ou l'arrière dans toute direction vers laquelle il fait face.
extends CharacterBody2D
@export var speed = 400
@export var rotation_speed = 1.5
var rotation_direction = 0
func get_input():
rotation_direction = Input.get_axis("left", "right")
velocity = transform.x * Input.get_axis("down", "up") * speed
func _physics_process(delta):
get_input()
rotation += rotation_direction * rotation_speed * delta
move_and_slide()
using Godot;
public partial class Movement : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 400;
[Export]
public float RotationSpeed { get; set; } = 1.5f;
private float _rotationDirection;
public void GetInput()
{
_rotationDirection = Input.GetAxis("left", "right");
Velocity = Transform.X * Input.GetAxis("down", "up") * Speed;
}
public override void _PhysicsProcess(double delta)
{
GetInput();
Rotation += _rotationDirection * RotationSpeed * (float)delta;
MoveAndSlide();
}
}
Ici, nous avons ajouté deux nouvelles variables pour suivre notre direction et notre vitesse de rotation. La rotation est appliquée directement à la propriété rotation du corps.
Pour définir la vitesse, nous utilisons le transform.x du corps qui est un vecteur pointant dans la direction "avant" du corps, et multiplions celui-ci par la vitesse.
Rotation + Mouvement (souris)
Ce style de mouvement est une variation du précédent. Cette fois, la direction est définie par la position de la souris au lieu du clavier. Le personnage "regardera" toujours vers le pointeur de la souris. Les entrées avant/arrière restent toutefois les mêmes.
extends CharacterBody2D
@export var speed = 400
func get_input():
look_at(get_global_mouse_position())
velocity = transform.x * Input.get_axis("down", "up") * speed
func _physics_process(delta):
get_input()
move_and_slide()
using Godot;
public partial class Movement : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 400;
public void GetInput()
{
LookAt(GetGlobalMousePosition());
Velocity = Transform.X * Input.GetAxis("down", "up") * Speed;
}
public override void _PhysicsProcess(double delta)
{
GetInput();
MoveAndSlide();
}
}
Nous utilisons ici la méthode look_at() de Node2D pour diriger le joueur vers la position de la souris. Sans cette fonction, vous pourriez obtenir le même effet en définissant l'angle comme suit :
rotation = get_global_mouse_position().angle_to_point(position)
var rotation = GetGlobalMousePosition().AngleToPoint(Position);
Cliquer-et-déplacer
Ce dernier exemple utilise uniquement la souris pour contrôler le personnage. En cliquant sur l'écran, le joueur se déplacera à l'emplacement cible.
extends CharacterBody2D
@export var speed = 400
var target = position
func _input(event):
# Use is_action_pressed to only accept single taps as input instead of mouse drags.
if event.is_action_pressed(&"click"):
target = get_global_mouse_position()
func _physics_process(delta):
velocity = position.direction_to(target) * speed
# look_at(target)
if position.distance_to(target) > 10:
move_and_slide()
using Godot;
public partial class Movement : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 400;
private Vector2 _target;
public override void _Input(InputEvent @event)
{
// Use IsActionPressed to only accept single taps as input instead of mouse drags.
if (@event.IsActionPressed("click"))
{
_target = GetGlobalMousePosition();
}
}
public override void _PhysicsProcess(double delta)
{
Velocity = Position.DirectionTo(_target) * Speed;
// LookAt(_target);
if (Position.DistanceTo(_target) > 10)
{
MoveAndSlide();
}
}
}
Notez la vérification distance_to() que nous faisons avant le mouvement. Sans ce test, le corps "gigoterait" lorsqu'il atteindrait la position cible, car il se déplace légèrement au-delà de la position et essaie de reculer, se déplace trop loin et répète ce schéma encore et encore.
Décommenter la ligne look_at() amènera le corps à pointer dans la direction de son mouvement si vous préférez.
Astuce
Cette technique peut également être utilisée comme base du personnage "suivant". La position cible peut être celle de n'importe quel objet vers lequel vous voulez déplacer.
Résumé
Vous pouvez trouver ces exemples de code utiles comme points de départ pour vos propres projets. N'hésitez pas à les utiliser et à les expérimenter pour voir ce que vous pouvez faire.
Vous pouvez télécharger ce projet d'exemple ici : 2d_movement_starter.zip