Добрый день, наткнулся на проблему, пока не понимаю где искать решение.
Игрок при получении урона должен проигрывать анимацию и отскакивать от врага.
Почему-то отскок срабатывает только после завершения анимации (на какой бы строке кода она не находилась). Нужно сделать так, чтобы игрок отскакивал и проигрывал анимацию одновременно.
Функция на получение урона у игрока:
func take_damage(damage_amount : int, damage_vector : Vector2): if can_take_damage: enemy_position = damage_vector health -= damage_amount if health > 0: fsm.change_state("take_damage") iframes() else: can_take_damage = false fsm.change_state("die") pass
Функция на нанесение урона у противника:
func _on_spike_entered(area: Area2D) -> void: if area.get_parent() is Player: player_body = area.get_parent() area.get_parent().take_damage(1, self.position) GL.change_hp(-1) $Timer.start() pass
Функция в FSM "take_damage":
func enter(): var impulse_direction = entity.position.x - entity.enemy_position.x if impulse_direction < 0: entity.velocity = Vector2(-200,-200) else: entity.velocity = Vector2(200,-200) entity.animPlayer.play("Anim_Take_Damage")
MalkHadiel
У тебя в func take_damage() нет никаких анимаций, а есть какая-то (предположительно) стейт машина и какие то iframes().
Что это, я понятия не имею.
Не мог бы ты конкретизировать вопрос, чтобы он был по Годо, а не по твоей логике?
Попробую.
Есть player к которому привязан fsm, та самая стейт машина.
Если враг попадает по игроку, то у него вызывается функция "take_damage", которая в качестве аргументов принимает величину урона "damage_amount" и направление урона "damage_vector".
Если после получения урона здоровье больше нуля - игрок переходит в состояние "take_damage" (В самом низу которая).
В нем игроку придаётся импульс entity.velocity с направлением в зависимости от "enemy_position = damage_vector". И потом в этом же состоянии проигрывается анимация.
Непонятно почему сначала играет анимация, и только потом срабатывает импульс.
По сути плеер анимации прерывает выполнение физики игрока.
> > чтобы он был по Годо, а не по твоей логике?
MalkHadiel
> Попробую.
... рассказывает про логику )))
MalkHadiel
> fsm, та самая стейт машина.
Я же сказал, я не знаю, что это, как ты её писал. Нет такого класса в комплекте.
MalkHadiel
> Непонятно почему сначала играет анимация, и только потом срабатывает импульс.
Ты отладчиком запускал?
Или хотя бы print-ов понавставляй, чтобы понимать, чего творится.
Я ведь не могу за тебя это всё делать.
MalkHadiel
> По сути плеер анимации прерывает выполнение физики игрока.
Это невозможно в принципе *
** Сразу вспомнился мемо-шаблон "Anakin and Padme" ))))
Не понимаю тогда как в логике годо это описать)
Я же сказал, я не знаю, что это, как ты её писал. Нет такого класса в комплекте.
В комплекте нету, по сути штука нужна чтобы не писать спагетти код, но она выполнению физики никак не мешает.
Это невозможно в принципе *
Да я знаю, потому и удивлён)))
В анимации только выбирается сама анимация от animSprite и её кадр.
Но если время анимации выставить секунды на 3, то прыжок только после её завершения случится.
Принты уже вешал, по ним импульс срабатывает раньше анимации.
Видео не могу скинуть сейчас(
После обновления движка почему-то запись экрана не работает. Показывает просто серый фон.
MalkHadiel
> Но если время анимации выставить секунды на 3, то прыжок только после её завершения случится.
Значит у тебя что то завязано на типа animation_finished.
MalkHadiel
> Добрый день, наткнулся на проблему, пока не понимаю где искать решение.
> Игрок при получении урона должен проигрывать анимацию и отскакивать от врага.
> Почему-то отскок срабатывает только после завершения анимации (на какой бы строке кода она не находилась). Нужно сделать так, чтобы игрок отскакивал и проигрывал анимацию одновременно.
>
> Функция на получение урона у игрока:
>
> func take_damage(damage_amount : int, damage_vector : Vector2):
> if can_take_damage:
> enemy_position = damage_vector
> health -= damage_amount
> if health > 0:
> fsm.change_state("take_damage")
> iframes()
> else:
> can_take_damage = false
> fsm.change_state("die")
> pass
> Функция на нанесение урона у противника:
>
> func _on_spike_entered(area: Area2D) -> void:
> if area.get_parent() is Player:
> player_body = area.get_parent()
> area.get_parent().take_damage(1, self.position)
> GL.change_hp(-1)
> $Timer.start()
> pass
> Функция в FSM "take_damage":
>
> func enter():
>
> var impulse_direction = entity.position.x - entity.enemy_position.x
> if impulse_direction < 0:
> entity.velocity = Vector2(-200,-200)
> else:
> entity.velocity = Vector2(200,-200)
>
> entity.animPlayer.play("Anim_Take_Damage")
Учись пользоваться AI.
Проблема в том, что в enter() состояния "take_damage" вы устанавливаете velocity, но в движке Godot переменные не применяются мгновенно — движение происходит только в следующем _physics_process(), а анимация начинает проигрываться сразу.
Решение:
Чтобы игрок одновременно отскакивал и проигрывал анимацию, вам нужно добавить move_and_slide() (или move_and_collide(), если используете KinematicBody2D/CharacterBody2D) в момент установки velocity, а не ждать следующего кадра физики.
func enter(): var impulse_direction = entity.position.x - entity.enemy_position.x if impulse_direction < 0: entity.velocity = Vector2(-200,-200) else: entity.velocity = Vector2(200,-200) entity.move_and_slide() # <-- добавляем движение сразу entity.animPlayer.play("Anim_Take_Damage")
Альтернативный вариант (если velocity обрабатывается в _physics_process()):
Если у вас уже есть логика движения в _physics_process(), то вместо мгновенного вызова move_and_slide() можно временно изменить velocity, а код движения сам все обработает.
Пример:
# FSM: take_damage func enter(): var impulse_direction = entity.position.x - entity.enemy_position.x entity.velocity = Vector2(200 * sign(impulse_direction), -200) entity.animPlayer.play("Anim_Take_Damage") # Player.gd (пример кода в _physics_process) func _physics_process(delta): velocity.y += gravity * delta velocity = move_and_slide(velocity, Vector2.UP)
Итог:
Теперь игрок сразу будет отскакивать и одновременно проигрывать анимацию!
Tiranas
> в движке Godot переменные не применяются мгновенно
Эта фраза - бред. Остальное и не читал.
> Учись пользоваться AI.
Программировать надо учиться.
Der FlugSimulator
> Эта фраза - бред. Остальное и не читал.
Читать надо, а то всё будет потоком бреда
вот ещё ответ от другой нейронки
Для решения проблемы нужно изменить последовательность действий таким образом, чтобы игрок начинал отскакивать сразу же после получения урона, а не дожидался окончания анимации. Это можно сделать следующим образом:
Сразу применяем импульс: В функции take_damage передаем направление удара в состояние FSM и добавляем импульс до начала анимации.
Параллельное выполнение анимации и движения: В FSM используем функцию enter, чтобы запустить анимацию и добавить начальное движение одновременно.
Вот пример изменений в коде:
Функция take_damage
Добавляем передачу направления удара в FSM:
func take_damage(damage_amount : int, damage_vector : Vector2): if can_take_damage: enemy_position = damage_vector health -= damage_amount if health > 0: # Передаем направление удара в FSM fsm.set_data("impulse_direction", damage_vector) fsm.change_state("take_damage") iframes() else: can_take_damage = false fsm.change_state("die")
Функция take_damage в FSM
Здесь применим начальный импульс и запустим анимацию одновременно:
func enter(): # Получаем направление удара из данных FSM var impulse_direction = fsm.get_data("impulse_direction") var x_dir = sign(impulse_direction.x - entity.position.x) # Добавляем начальный импульс entity.velocity = Vector2(x_dir * 200, -200) # Запускаем анимацию entity.animPlayer.play("Anim_Take_Damage")
Таким образом, игрок будет получать начальный импульс сразу после получения урона, а анимация начнет воспроизводиться параллельно движению.
Der FlugSimulator
> Лучше учиться программировать.
Сейчас ситуация изменилась: знания уже не в приоритете, а важнее стало умение использовать инструменты.
Der FlugSimulator
А тебе идёт бубен, и в программировании поможет.
Tiranas
> в движке Godot переменные не применяются мгновенно
> Читать надо, а то всё будет потоком бреда
Зачем мне читать остальное, если переменные применяются именно в момент присваивания.
Хоть в Godot, хоть где ещё.
Tiranas
> Сейчас ситуация изменилась: знания уже не в приоритете,
Это бы в перлы.
Der FlugSimulator
> Это бы в перлы.
Через тройку лет и это устареет.
Поразительно конечно.
Один не может толком сформулировать вопрос, логи приложить и полный код.
Второй, нисколько этим не смущаясь, копипастит сюда какие то буквы из интернет бредогенератора, будучи уверен, что они имеют какое то отношение к проблеме.
Тут охотно веришь, что "знания уже не в приоритете".