Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extends Node
- class_name MovementSystem
- # Ссылки на компоненты
- @onready var player: CharacterBody3D = get_parent()
- @onready var stamina_system: StaminaSystem = get_parent().get_node("StaminaSystem")
- # Настройки базового движения
- @export var base_speed: float = 5.0
- @export var sprint_speed_multiplier: float = 1.8
- @export var acceleration: float = 20.0
- @export var friction: float = 15.0
- # Настройки прыжка и гравитации
- @export var jump_velocity: float = 8.0
- @export var gravity: float = 20.0
- @export var max_fall_speed: float = 30.0
- @export var coyote_time: float = 0.15
- # Настройки переката
- @export var roll_speed: float = 12.0
- @export var roll_duration: float = 0.6
- @export var roll_stamina_cost: float = 25.0
- # Настройки дэша
- @export var dash_speed: float = 20.0
- @export var dash_duration: float = 0.2
- @export var dash_stamina_cost: float = 30.0
- # Настройки спринта
- @export var sprint_stamina_cost_per_second: float = 15.0
- # Внутренние переменные
- var velocity: Vector3 = Vector3.ZERO
- var is_sprinting: bool = false
- var can_move: bool = true
- var last_ground_time: float = 0.0
- var was_on_floor: bool = false
- # Состояния специальных движений
- var is_rolling: bool = false
- var is_dashing: bool = false
- var roll_timer: float = 0.0
- var dash_timer: float = 0.0
- var roll_direction: Vector2 = Vector2.ZERO
- var dash_direction: Vector2 = Vector2.ZERO
- # Сигналы
- signal jumped
- signal landed
- signal sprint_started
- signal sprint_stopped
- signal roll_started
- signal roll_ended
- signal dash_started
- signal dash_ended
- func _ready():
- # Подключение к полу для определения приземления
- player.floor_stop_on_slope = false
- player.floor_max_angle = deg_to_rad(45)
- func process_movement(input_direction: Vector2, delta: float):
- if not can_move:
- return
- # Обновление состояния пола
- update_floor_state()
- # Применение гравитации
- apply_gravity(delta)
- # Обработка специальных движений
- process_special_movements(delta)
- # Обработка горизонтального движения
- if not is_rolling and not is_dashing:
- process_horizontal_movement(input_direction, delta)
- # Обработка спринта
- process_sprint(input_direction, delta)
- func apply_gravity(delta: float):
- if not player.is_on_floor():
- velocity.y -= gravity * delta
- velocity.y = max(velocity.y, -max_fall_speed)
- func update_floor_state():
- var is_on_floor = player.is_on_floor()
- if is_on_floor and not was_on_floor:
- # Приземление
- landed.emit()
- last_ground_time = Time.get_ticks_msec() / 1000.0
- if is_on_floor:
- last_ground_time = Time.get_ticks_msec() / 1000.0
- was_on_floor = is_on_floor
- func process_horizontal_movement(input_direction: Vector2, delta: float):
- # Преобразование 2D ввода в 3D движение
- var movement_3d = Vector3(input_direction.x, 0, input_direction.y)
- if input_direction.length() > 0:
- # Движение
- var target_speed = get_current_speed()
- var target_velocity = movement_3d.normalized() * target_speed
- velocity.x = move_toward(velocity.x, target_velocity.x, acceleration * delta)
- velocity.z = move_toward(velocity.z, target_velocity.z, acceleration * delta)
- else:
- # Применение трения
- velocity.x = move_toward(velocity.x, 0, friction * delta)
- velocity.z = move_toward(velocity.z, 0, friction * delta)
- func get_current_speed() -> float:
- var speed = base_speed
- if is_sprinting:
- speed *= sprint_speed_multiplier
- return speed
- func process_sprint(input_direction: Vector2, delta: float):
- if is_sprinting:
- if input_direction.length() == 0 or not stamina_system.can_use_stamina(sprint_stamina_cost_per_second * delta, StaminaSystem.StaminaType.MOVEMENT):
- stop_sprint()
- else:
- stamina_system.use_stamina(sprint_stamina_cost_per_second * delta, StaminaSystem.StaminaType.MOVEMENT)
- func process_special_movements(delta: float):
- # Обработка переката
- if is_rolling:
- roll_timer -= delta
- if roll_timer <= 0:
- end_roll()
- else:
- # Движение во время переката
- var roll_velocity = Vector3(roll_direction.x, 0, roll_direction.y) * roll_speed
- velocity.x = roll_velocity.x
- velocity.z = roll_velocity.z
- # Обработка дэша
- if is_dashing:
- dash_timer -= delta
- if dash_timer <= 0:
- end_dash()
- else:
- # Движение во время дэша
- var dash_velocity = Vector3(dash_direction.x, 0, dash_direction.y) * dash_speed
- velocity.x = dash_velocity.x
- velocity.z = dash_velocity.z
- # Методы действий
- func try_jump() -> bool:
- if can_jump():
- velocity.y = jump_velocity
- jumped.emit()
- return true
- return false
- func can_jump() -> bool:
- # Обычный прыжок или coyote time
- return player.is_on_floor() or (Time.get_ticks_msec() / 1000.0 - last_ground_time <= coyote_time)
- func toggle_sprint():
- if is_sprinting:
- stop_sprint()
- else:
- start_sprint()
- func start_sprint():
- if not is_sprinting and stamina_system.can_use_stamina(sprint_stamina_cost_per_second * 0.1, StaminaSystem.StaminaType.MOVEMENT):
- is_sprinting = true
- sprint_started.emit()
- func stop_sprint():
- if is_sprinting:
- is_sprinting = false
- sprint_stopped.emit()
- func try_roll(direction: Vector2) -> bool:
- if can_roll() and direction.length() > 0:
- start_roll(direction)
- return true
- return false
- func can_roll() -> bool:
- return (not is_rolling and
- not is_dashing and
- player.is_on_floor() and
- stamina_system.can_use_stamina(roll_stamina_cost, StaminaSystem.StaminaType.MOVEMENT))
- func start_roll(direction: Vector2):
- is_rolling = true
- roll_timer = roll_duration
- roll_direction = direction.normalized()
- stamina_system.use_stamina(roll_stamina_cost, StaminaSystem.StaminaType.MOVEMENT)
- roll_started.emit()
- func end_roll():
- is_rolling = false
- roll_timer = 0.0
- roll_direction = Vector2.ZERO
- roll_ended.emit()
- func try_dash(direction: Vector2) -> bool:
- if can_dash() and direction.length() > 0:
- start_dash(direction)
- return true
- return false
- func can_dash() -> bool:
- return (not is_rolling and
- not is_dashing and
- stamina_system.can_use_stamina(dash_stamina_cost, StaminaSystem.StaminaType.DASH))
- func start_dash(direction: Vector2):
- is_dashing = true
- dash_timer = dash_duration
- dash_direction = direction.normalized()
- stamina_system.use_stamina(dash_stamina_cost, StaminaSystem.StaminaType.DASH)
- # Дэш может быть выполнен в воздухе, но не сбрасывает падение полностью
- if not player.is_on_floor():
- velocity.y = max(velocity.y, 0) # Останавливаем падение, но не добавляем подъем
- dash_started.emit()
- func end_dash():
- is_dashing = false
- dash_timer = 0.0
- dash_direction = Vector2.ZERO
- dash_ended.emit()
- # Геттеры
- func get_velocity() -> Vector3:
- return velocity
- func is_moving() -> bool:
- var horizontal_velocity = Vector2(velocity.x, velocity.z)
- return horizontal_velocity.length() > 0.1
- func is_in_air() -> bool:
- return not player.is_on_floor()
- func is_falling() -> bool:
- return velocity.y < -0.1 and not player.is_on_floor()
- func get_movement_state() -> String:
- if is_dashing:
- return "dashing"
- elif is_rolling:
- return "rolling"
- elif is_falling():
- return "falling"
- elif not player.is_on_floor():
- return "jumping"
- elif is_sprinting and is_moving():
- return "sprinting"
- elif is_moving():
- return "walking"
- else:
- return "idle"
- # Методы управления
- func set_can_move(can_move_new: bool):
- can_move = can_move_new
- if not can_move:
- stop_sprint()
- func force_stop_all_movement():
- velocity = Vector3.ZERO
- stop_sprint()
- if is_rolling:
- end_roll()
- if is_dashing:
- end_dash()
- func add_external_force(force: Vector3):
- velocity += force
- func set_velocity(new_velocity: Vector3):
- velocity = new_velocity
- # Настройки (для будущих улучшений)
- func modify_speed(multiplier: float, duration: float = -1):
- # Заглушка для временных модификаторов скорости
- pass
- func modify_jump_height(multiplier: float, duration: float = -1):
- # Заглушка для модификаторов прыжка
- pass
- # Сохранение состояния
- func get_save_data() -> Dictionary:
- return {
- "velocity": velocity,
- "is_sprinting": is_sprinting,
- "base_speed": base_speed,
- "sprint_speed_multiplier": sprint_speed_multiplier
- }
- func load_save_data(data: Dictionary):
- velocity = data.get("velocity", Vector3.ZERO)
- is_sprinting = data.get("is_sprinting", false)
- base_speed = data.get("base_speed", 5.0)
- sprint_speed_multiplier = data.get("sprint_speed_multiplier", 1.8)
Advertisement
Add Comment
Please, Sign In to add comment