init
This commit is contained in:
124
scripts/parabolic_projectile.gd
Normal file
124
scripts/parabolic_projectile.gd
Normal 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
|
||||
|
||||
# Не проверяем столкновения при полете - только движение
|
||||
Reference in New Issue
Block a user