Проблема
Вам нужен двухмерный персонаж с движением в 8 направлениях, включая анимацию в Godot.
Решение
Для нашего примера мы будем использовать Изометрического Мини-Крестоносца, который содержит восемь направлений анимации для покоя, бега, атаки и нескольких других состояний.
Анимации организованы в папках, с отдельным изображением для каждого кадра. Мы будем использовать AnimatedSprite2D и мы назовем каждую анимацию в соответствии с ее направлением. Например, idle0 будет указывать вправо и двигаться по часовой стрелке до idle7.
Когда наш персонаж двигается, он выберет анимацию в зависимости от направления движения:
Мы будем использовать мышь для движения — персонаж всегда будет повернут к мыши и бежать в том направлении, когда мы нажимаем кнопку мыши.
Чтобы выбрать, какую анимацию проигрывать, нам нужно получить направление мыши и отобразить его в тот же диапазон от 0 до 7. get_local_mouse_position() дает нам положение мыши относительно персонажа. Затем мы можем использовать snappedf(), чтобы прижать угол вектора мыши к ближайшему кратному 45° (PI/4 радиан), что дает следующий результат:
Разделите каждое значение на 45° (PI/4 радиан):
Наконец, нам нужно отобразить полученный диапазон в диапазон от 0 до 7 с использованием функции wrapi(), чтобы у нас было правильные значения. Добавив это значение в конец имени анимации (“idle”, “run” и так далее), мы получим правильную анимацию:
func _physics_process(delta):
current_animation = "idle"
var mouse = get_local_mouse_position()
angle = snappedf(mouse.angle(), PI/4) / (PI/4)
angle = wrapi(int(angle), 0, 8)
if Input.is_action_pressed("left_mouse") and mouse.length() > 10:
current_animation = "run"
velocity = mouse.normalized() * speed
move_and_slide()
$AnimatedSprite2D.animation = current_animation + str(a)
Если протестировать скрипт мы увидим следующее
Ввод с клавиатуры
Если вы используете управление с клавиатуры вместо мыши, вы можете получить угол движения на основе того, какие клавиши удерживаются. Остальная часть процесса работает так же.
func _process(delta):
current_animation = "idle"
var input_dir = Input.get_vector("left", "right", "up", "down")
if input_dir.length() != 0:
angle = input_dir.angle() / (PI/4)
angle = wrapi(int(a), 0, 8)
current_animation = "run"
velocity = input_dir * speed
move_and_slide()
$AnimatedSprite2D.play(current_animation + str(angle))
Скачайте этот проект
Скачайте код проекта здесь: https://github.com/godotrecipes/8_direction_animation