This commit is contained in:
Redsandy
2026-01-18 20:56:24 +03:00
commit 7980e0add8
68 changed files with 1605294 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
extends Projectile
class_name ParabolicProjectile
# Параболический снаряд для броска
@export var projectile_gravity: float = 200
@export var arc_height: float = 15.0 # Увеличена высота параболы
var target_position: Vector3 = Vector3.ZERO
var start_position: Vector3 = Vector3.ZERO
var travel_time: float = 0.0
var total_time: float = 0.0
func _ready():
start_position = global_position
# Проверяем, что target_position установлен
if target_position == Vector3.ZERO:
# Если не установлен, используем направление вперед
target_position = start_position + Vector3(0, 0, -10.0)
target_position.y = start_position.y
# Вычисляем горизонтальное расстояние
var horizontal_distance = Vector3(start_position.x, 0, start_position.z).distance_to(Vector3(target_position.x, 0, target_position.z))
# Вычисляем правильную траекторию для попадания в цель
var horizontal_dir = (target_position - start_position)
horizontal_dir.y = 0
# Если цель слишком близко (включая клик на самого игрока), устанавливаем минимальное расстояние и направление
if horizontal_distance < 1.0:
# Если направление нулевое или очень маленькое, используем направление вперед от игрока
if horizontal_dir.length() < 0.1:
# Используем направление камеры или направление вперед
var camera = get_viewport().get_camera_3d()
if camera:
var forward = -camera.global_transform.basis.z
forward.y = 0
horizontal_dir = forward.normalized()
else:
horizontal_dir = Vector3(0, 0, -1) # Направление по умолчанию
else:
horizontal_dir = horizontal_dir.normalized()
# Устанавливаем минимальное расстояние
horizontal_distance = 1.0
# Обновляем target_position на минимальном расстоянии от стартовой позиции
target_position = start_position + horizontal_dir * horizontal_distance
target_position.y = 0.0
else:
horizontal_dir = horizontal_dir.normalized()
# Время подъема до максимальной высоты
var time_to_peak = sqrt(2 * arc_height / projectile_gravity)
# Время полета вниз (примерно такое же)
var time_to_fall = time_to_peak
# Общее время полета по вертикали
var vertical_time = time_to_peak + time_to_fall
# Горизонтальная скорость должна обеспечить попадание в цель за время полета
var horizontal_speed = horizontal_distance / vertical_time
# Начальная вертикальная скорость для достижения нужной высоты
var vertical_speed = sqrt(2 * projectile_gravity * arc_height)
# Общее время полета
total_time = vertical_time
# Устанавливаем начальную скорость
velocity = horizontal_dir * horizontal_speed + Vector3.UP * vertical_speed
# Вызываем super._ready() после установки velocity
super._ready()
# Отключаем мониторинг коллизий при полете
monitoring = false
func _physics_process(delta):
if has_hit:
return
# Если velocity не установлена, не двигаемся
if velocity == Vector3.ZERO:
return
# Проверяем время жизни
lifetime_timer -= delta
if lifetime_timer <= 0:
if is_explosive:
explode(global_position)
else:
queue_free()
return
travel_time += delta
# Сохраняем предыдущую позицию для raycast (если понадобится)
previous_position = global_position
# Применяем гравитацию
velocity.y -= projectile_gravity * delta
# Движение снаряда
global_position += velocity * delta
# Проверяем, достигли ли цели
# Проверяем по Y координате (приземление) и по времени полета
# НЕ проверяем горизонтальное расстояние, так как это может сработать сразу при близких целях
if (global_position.y <= target_position.y + 0.3) and (travel_time >= total_time * 0.5):
# Включаем коллизию только при приземлении
monitoring = true
# Устанавливаем позицию точно в целевую точку
global_position = target_position
on_hit(target_position)
return
# Дополнительная проверка по времени полета (на случай, если снаряд не достиг земли)
if travel_time >= total_time * 1.2:
monitoring = true
global_position = target_position
on_hit(target_position)
return
# Не проверяем столкновения при полете - только движение