Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Огляд руху в 2D просторі
Вступ
Кожен початківець стикався з питанням: "Як я буду переміщувати свого персонажа?" Залежно від стилю гри, яку ви робите, ви можете мати особливі вимоги, але загалом рух у більшості 2D-ігор базується на невеликій кількості конструкцій.
Ми будемо використовувати CharacterBody2D для цих прикладів, але принципи також стосуватимуться інших типів вузлів (Area2D, RigidBody2D).
Налаштування
Each example below uses the same scene setup. Start with a CharacterBody2D with two
children: Sprite2D and CollisionShape2D. You can use the Godot icon (icon.svg)
for the Sprite2D's texture or use any other 2D image you have.
Відкрийте Проект -> Налаштування проекту та виберіть вкладку "Мапа вводу". Додайте наступні дії вводу (докладніше див. InputEvent):
8-бічний рух
У цьому випадку ви хочете, щоб користувач користувався чотирма клавішами (стрілками вгору/вліво/вниз/вправо, або W/A/S/D) для переміщення у вибраному напрямку. Назва «8-бічний рух» походить від того, що гравець може рухатися по діагоналі, натискаючи дві клавіші одночасно.
Додайте скрипт до тіла символу та додайте такий код:
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();
}
}
У функції get_input() ми використовуємо Input get_vector(), щоб перевірити наявність чотирьох ключових подій і підсумувати вектор напрямку.
Потім ми можемо встановити нашу швидкість, помноживши цей вектор напрямку, який має довжину 1, на бажану швидкість.
Порада
Якщо ви ніколи раніше не використовували векторну математику або вам потрібно освіжити знання, ви можете переглянути пояснення використання вектора у Godot на Векторна математика.
Примітка
Якщо вищенаведений код нічого не робить під час натискання клавіш, перевірте, чи правильно ви налаштували дії введення, як описано в частині Налаштування цього урока.
Обертання + рух
Цей тип руху іноді називають "Астероїдним стилем", оскільки він нагадує роботу цієї класичної аркадної гри. Натискання вліво/вправо обертає персонажа, тоді як вгору/вниз рухає його вперед, або назад, у будь-якому напрямку, до якого він спрямований.
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();
}
}
Тут ми додали дві змінні для відстеження нашого напрямку та швидкості обертання. Поворот застосовується безпосередньо до властивості обертання тіла.
Щоб встановити швидкість, ми використовуємо transform.x тіла, який є вектором, що вказує в напрямку тіла «вперед», і множимо його на швидкість.
Обертання + рух (мишкою)
Цей стиль руху є різновидом попереднього. Цього разу напрямок задається положенням мишки, замість клавіатури. Персонаж завжди буде "дивитись" на курсор мишки. Однак вхідні дані вперед/назад залишаються незмінними.
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();
}
}
Тут ми використовуємо метод Node2D look_at(), щоб вказати гравцеві на позицію миші. Без цієї функції ви могли б отримати той самий ефект, встановивши кут таким чином:
rotation = get_global_mouse_position().angle_to_point(position)
var rotation = GetGlobalMousePosition().AngleToPoint(Position);
Клацай і рухайся
Цей останній приклад використовує лише мишку для управління персонажем. Натискання на екрані призведе до переміщення гравця до цільового місця.
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();
}
}
}
Зверніть увагу на перевірку distance_to(), яку ми робимо перед переміщенням. Без цього тесту тіло буде "тремтіти", досягнувши цільового положення, коли воно просунеться трохи задалеко, спробує повернутися назад, знову проскочивши цільове положення, і так без кінця.
Знявши коментар з рядка look_at(), ви також повернете тіло в напрямку руху, якщо вам так більше подобається.
Порада
Цей метод також можна використовувати як основу для «наступного» символу. target позицією може бути будь-який об’єкт, до якого ви хочете переміститися.
Підсумок
Ці зразки коду можуть стати корисними в якості основи для ваших власних проєктів. Сміливо використовуйте їх і експериментуйте з ними, щоб побачити, що ви можете зробити.
Ви можете завантажити цей приклад проекту тут: 2d_movement_starter.zip