vanburendolphin

MovementSystem

Jul 28th, 2025
1,048
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
GDScript 9.02 KB | Gaming | 0 0
  1. extends Node
  2. class_name MovementSystem
  3.  
  4. # Ссылки на компоненты
  5. @onready var player: CharacterBody3D = get_parent()
  6. @onready var stamina_system: StaminaSystem = get_parent().get_node("StaminaSystem")
  7.  
  8. # Настройки базового движения
  9. @export var base_speed: float = 5.0
  10. @export var sprint_speed_multiplier: float = 1.8
  11. @export var acceleration: float = 20.0
  12. @export var friction: float = 15.0
  13.  
  14. # Настройки прыжка и гравитации
  15. @export var jump_velocity: float = 8.0
  16. @export var gravity: float = 20.0
  17. @export var max_fall_speed: float = 30.0
  18. @export var coyote_time: float = 0.15
  19.  
  20. # Настройки переката
  21. @export var roll_speed: float = 12.0
  22. @export var roll_duration: float = 0.6
  23. @export var roll_stamina_cost: float = 25.0
  24.  
  25. # Настройки дэша
  26. @export var dash_speed: float = 20.0
  27. @export var dash_duration: float = 0.2
  28. @export var dash_stamina_cost: float = 30.0
  29.  
  30. # Настройки спринта
  31. @export var sprint_stamina_cost_per_second: float = 15.0
  32.  
  33. # Внутренние переменные
  34. var velocity: Vector3 = Vector3.ZERO
  35. var is_sprinting: bool = false
  36. var can_move: bool = true
  37. var last_ground_time: float = 0.0
  38. var was_on_floor: bool = false
  39.  
  40. # Состояния специальных движений
  41. var is_rolling: bool = false
  42. var is_dashing: bool = false
  43. var roll_timer: float = 0.0
  44. var dash_timer: float = 0.0
  45. var roll_direction: Vector2 = Vector2.ZERO
  46. var dash_direction: Vector2 = Vector2.ZERO
  47.  
  48. # Сигналы
  49. signal jumped
  50. signal landed
  51. signal sprint_started
  52. signal sprint_stopped
  53. signal roll_started
  54. signal roll_ended
  55. signal dash_started
  56. signal dash_ended
  57.  
  58. func _ready():
  59.     # Подключение к полу для определения приземления
  60.     player.floor_stop_on_slope = false
  61.     player.floor_max_angle = deg_to_rad(45)
  62.  
  63. func process_movement(input_direction: Vector2, delta: float):
  64.     if not can_move:
  65.         return
  66.    
  67.     # Обновление состояния пола
  68.     update_floor_state()
  69.    
  70.     # Применение гравитации
  71.     apply_gravity(delta)
  72.    
  73.     # Обработка специальных движений
  74.     process_special_movements(delta)
  75.    
  76.     # Обработка горизонтального движения
  77.     if not is_rolling and not is_dashing:
  78.         process_horizontal_movement(input_direction, delta)
  79.    
  80.     # Обработка спринта
  81.     process_sprint(input_direction, delta)
  82.  
  83. func apply_gravity(delta: float):
  84.     if not player.is_on_floor():
  85.         velocity.y -= gravity * delta
  86.         velocity.y = max(velocity.y, -max_fall_speed)
  87.  
  88. func update_floor_state():
  89.     var is_on_floor = player.is_on_floor()
  90.    
  91.     if is_on_floor and not was_on_floor:
  92.         # Приземление
  93.         landed.emit()
  94.         last_ground_time = Time.get_ticks_msec() / 1000.0
  95.    
  96.     if is_on_floor:
  97.         last_ground_time = Time.get_ticks_msec() / 1000.0
  98.    
  99.     was_on_floor = is_on_floor
  100.  
  101. func process_horizontal_movement(input_direction: Vector2, delta: float):
  102.     # Преобразование 2D ввода в 3D движение
  103.     var movement_3d = Vector3(input_direction.x, 0, input_direction.y)
  104.    
  105.     if input_direction.length() > 0:
  106.         # Движение
  107.         var target_speed = get_current_speed()
  108.         var target_velocity = movement_3d.normalized() * target_speed
  109.        
  110.         velocity.x = move_toward(velocity.x, target_velocity.x, acceleration * delta)
  111.         velocity.z = move_toward(velocity.z, target_velocity.z, acceleration * delta)
  112.     else:
  113.         # Применение трения
  114.         velocity.x = move_toward(velocity.x, 0, friction * delta)
  115.         velocity.z = move_toward(velocity.z, 0, friction * delta)
  116.  
  117. func get_current_speed() -> float:
  118.     var speed = base_speed
  119.     if is_sprinting:
  120.         speed *= sprint_speed_multiplier
  121.     return speed
  122.  
  123. func process_sprint(input_direction: Vector2, delta: float):
  124.     if is_sprinting:
  125.         if input_direction.length() == 0 or not stamina_system.can_use_stamina(sprint_stamina_cost_per_second * delta, StaminaSystem.StaminaType.MOVEMENT):
  126.             stop_sprint()
  127.         else:
  128.             stamina_system.use_stamina(sprint_stamina_cost_per_second * delta, StaminaSystem.StaminaType.MOVEMENT)
  129.  
  130. func process_special_movements(delta: float):
  131.     # Обработка переката
  132.     if is_rolling:
  133.         roll_timer -= delta
  134.         if roll_timer <= 0:
  135.             end_roll()
  136.         else:
  137.             # Движение во время переката
  138.             var roll_velocity = Vector3(roll_direction.x, 0, roll_direction.y) * roll_speed
  139.             velocity.x = roll_velocity.x
  140.             velocity.z = roll_velocity.z
  141.    
  142.     # Обработка дэша
  143.     if is_dashing:
  144.         dash_timer -= delta
  145.         if dash_timer <= 0:
  146.             end_dash()
  147.         else:
  148.             # Движение во время дэша
  149.             var dash_velocity = Vector3(dash_direction.x, 0, dash_direction.y) * dash_speed
  150.             velocity.x = dash_velocity.x
  151.             velocity.z = dash_velocity.z
  152.  
  153. # Методы действий
  154. func try_jump() -> bool:
  155.     if can_jump():
  156.         velocity.y = jump_velocity
  157.         jumped.emit()
  158.         return true
  159.     return false
  160.  
  161. func can_jump() -> bool:
  162.     # Обычный прыжок или coyote time
  163.     return player.is_on_floor() or (Time.get_ticks_msec() / 1000.0 - last_ground_time <= coyote_time)
  164.  
  165. func toggle_sprint():
  166.     if is_sprinting:
  167.         stop_sprint()
  168.     else:
  169.         start_sprint()
  170.  
  171. func start_sprint():
  172.     if not is_sprinting and stamina_system.can_use_stamina(sprint_stamina_cost_per_second * 0.1, StaminaSystem.StaminaType.MOVEMENT):
  173.         is_sprinting = true
  174.         sprint_started.emit()
  175.  
  176. func stop_sprint():
  177.     if is_sprinting:
  178.         is_sprinting = false
  179.         sprint_stopped.emit()
  180.  
  181. func try_roll(direction: Vector2) -> bool:
  182.     if can_roll() and direction.length() > 0:
  183.         start_roll(direction)
  184.         return true
  185.     return false
  186.  
  187. func can_roll() -> bool:
  188.     return (not is_rolling and
  189.             not is_dashing and
  190.             player.is_on_floor() and
  191.             stamina_system.can_use_stamina(roll_stamina_cost, StaminaSystem.StaminaType.MOVEMENT))
  192.  
  193. func start_roll(direction: Vector2):
  194.     is_rolling = true
  195.     roll_timer = roll_duration
  196.     roll_direction = direction.normalized()
  197.     stamina_system.use_stamina(roll_stamina_cost, StaminaSystem.StaminaType.MOVEMENT)
  198.     roll_started.emit()
  199.  
  200. func end_roll():
  201.     is_rolling = false
  202.     roll_timer = 0.0
  203.     roll_direction = Vector2.ZERO
  204.     roll_ended.emit()
  205.  
  206. func try_dash(direction: Vector2) -> bool:
  207.     if can_dash() and direction.length() > 0:
  208.         start_dash(direction)
  209.         return true
  210.     return false
  211.  
  212. func can_dash() -> bool:
  213.     return (not is_rolling and
  214.             not is_dashing and
  215.             stamina_system.can_use_stamina(dash_stamina_cost, StaminaSystem.StaminaType.DASH))
  216.  
  217. func start_dash(direction: Vector2):
  218.     is_dashing = true
  219.     dash_timer = dash_duration
  220.     dash_direction = direction.normalized()
  221.     stamina_system.use_stamina(dash_stamina_cost, StaminaSystem.StaminaType.DASH)
  222.    
  223.     # Дэш может быть выполнен в воздухе, но не сбрасывает падение полностью
  224.     if not player.is_on_floor():
  225.         velocity.y = max(velocity.y, 0)  # Останавливаем падение, но не добавляем подъем
  226.    
  227.     dash_started.emit()
  228.  
  229. func end_dash():
  230.     is_dashing = false
  231.     dash_timer = 0.0
  232.     dash_direction = Vector2.ZERO
  233.     dash_ended.emit()
  234.  
  235. # Геттеры
  236. func get_velocity() -> Vector3:
  237.     return velocity
  238.  
  239. func is_moving() -> bool:
  240.     var horizontal_velocity = Vector2(velocity.x, velocity.z)
  241.     return horizontal_velocity.length() > 0.1
  242.  
  243. func is_in_air() -> bool:
  244.     return not player.is_on_floor()
  245.  
  246. func is_falling() -> bool:
  247.     return velocity.y < -0.1 and not player.is_on_floor()
  248.  
  249. func get_movement_state() -> String:
  250.     if is_dashing:
  251.         return "dashing"
  252.     elif is_rolling:
  253.         return "rolling"
  254.     elif is_falling():
  255.         return "falling"
  256.     elif not player.is_on_floor():
  257.         return "jumping"
  258.     elif is_sprinting and is_moving():
  259.         return "sprinting"
  260.     elif is_moving():
  261.         return "walking"
  262.     else:
  263.         return "idle"
  264.  
  265. # Методы управления
  266. func set_can_move(can_move_new: bool):
  267.     can_move = can_move_new
  268.     if not can_move:
  269.         stop_sprint()
  270.  
  271. func force_stop_all_movement():
  272.     velocity = Vector3.ZERO
  273.     stop_sprint()
  274.     if is_rolling:
  275.         end_roll()
  276.     if is_dashing:
  277.         end_dash()
  278.  
  279. func add_external_force(force: Vector3):
  280.     velocity += force
  281.  
  282. func set_velocity(new_velocity: Vector3):
  283.     velocity = new_velocity
  284.  
  285. # Настройки (для будущих улучшений)
  286. func modify_speed(multiplier: float, duration: float = -1):
  287.     # Заглушка для временных модификаторов скорости
  288.     pass
  289.  
  290. func modify_jump_height(multiplier: float, duration: float = -1):
  291.     # Заглушка для модификаторов прыжка
  292.     pass
  293.  
  294. # Сохранение состояния
  295. func get_save_data() -> Dictionary:
  296.     return {
  297.         "velocity": velocity,
  298.         "is_sprinting": is_sprinting,
  299.         "base_speed": base_speed,
  300.         "sprint_speed_multiplier": sprint_speed_multiplier
  301.     }
  302.  
  303. func load_save_data(data: Dictionary):
  304.     velocity = data.get("velocity", Vector3.ZERO)
  305.     is_sprinting = data.get("is_sprinting", false)
  306.     base_speed = data.get("base_speed", 5.0)
  307.     sprint_speed_multiplier = data.get("sprint_speed_multiplier", 1.8)
  308.  
Advertisement
Add Comment
Please, Sign In to add comment