Итак sprite это целый spritesheets, то есть несколько анимаций на одном спрайте.
Дальше все по старой схеме Animation Player(анимации персонажа), Collision Shape (коллизия персонажа).
Audio Listener не помню зачем я его сюда воткнул(что то тестировал), теперь какой то баг все звуки теперь только в центре локации, если отходить от центра звуки все тише и тише.
Sound - все звуки тут которые привязаны к персонажу.
Спрайт pricel отвечает за спрайт прицела . Кстати вместе DeepSeek сделали разброс пуль и прицел увеличивается когда разброс увеличивается. Но когда делал с нейросетью, то какие то несложные механики еще все хорошо, но стоит только проекту увеличиться, то проект начинается сыпаться и исправляешь какие то моменты и в итоге делаешь своими руками так как надо. Я все таки решил что не буду пользоваться нейросетью.
TimerLight-это таймер вспышки от выстрела.
PointLight-сам свет от выстрела.
Marker - с помощью этого нода указываю начальную точку для патронов.
Bullet Empty-пустой нод в котором собираются все отстреленные патроны.
А дальше пошли кулдауны для выстрела и перезарядки пистолета.
Может кому то пригодиться сам скрипт игрока. Этот скрипт еще в процессе разработки, что то там лишнее что то нужное.
_______________________________________________________
extends CharacterBody2D
var speed_forward = 600 # Быстрая скорость вперёд
var speed_backward = 500 # Медленная скорость назад
var current_speed = 500.0 # Текущая скорость (для плавности)
var acceleration = 30 # Плавность изменения скорости
var can_sprint=true
var stamina=100
var max_stamina=100
var recovery_stamina=0.5
var rashod_stamina=1
#var speed = 400
var current_spread = 0.0
var max_spread = deg_to_rad(15)
var spread_recovery_speed = 0.3
var spread_increase_per_shot = deg_to_rad(10)
var can_shot = true
var reload_pistols =false
var degrees_per_sec = 540
@onready var crosshair = $pricel
@onready var bullet_tscn = preload("res://scene/laser.tscn")
func _ready() -> void:
Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
func _physics_process(delta: float) -> void:
handle_movement(delta)
handle_rotation(delta)
handle_shooting()
update_spread(delta)
move_and_slide()
sprint()
stamina_sprint(delta)
Globals.stamina=stamina
update_crosshair()
hand_reload()
func sprint():
if Input.is_action_pressed("shift")&& can_sprint==true:
speed_forward=1000
speed_backward=800
$AnimationPlayer.play("sprint")
else:
speed_forward=600
speed_backward=500
func stamina_sprint(delta):
var direction=Input.get_vector("left", "right", "forwrd", "back")
# Трата стамины при спринте и движении
if Input.is_action_pressed("shift") && can_sprint && direction != Vector2.ZERO:
stamina -= rashod_stamina * delta * 60 # Нормализация к FPS
stamina = max(stamina, 0) # Не даем уйти ниже 0
# Автоматическое восстановление
else:
var recovery_multiplier = 12.0 if direction == Vector2.ZERO else 1.0 # Быстрее восстанавливаем при стоянии
stamina += recovery_stamina * recovery_multiplier * delta * 60
stamina = min(stamina, max_stamina) # Не даем превысить максимум
# Управление возможностью спринта
if stamina <= 0:
can_sprint = false
elif stamina >= max_stamina * 0.3: # Порог для возобновления спринта
can_sprint = true
func handle_movement(delta):
var direction = Input.get_vector("left", "right", "forwrd", "back")
if direction.length() > 0:
var move_angle = direction.angle()
var face_angle = rotation
var angle_diff = wrapf(move_angle - face_angle, -PI, PI)
var is_moving_forward = abs(angle_diff) < PI / 2
var target_speed = speed_forward if is_moving_forward else speed_backward
# ИЗМЕНЕНО: Улучшенное плавное изменение скорости
current_speed = lerp(current_speed, float(target_speed), acceleration * delta * (2.0 if is_moving_forward else 1.5)) # Быстрее ускоряемся вперед
velocity = direction.normalized() * current_speed # ДОБАВЛЕНО: normalize для сохранения скорости по диагонали
else:
# ИЗМЕНЕНО: Плавное замедление при остановке
current_speed = lerp(current_speed, 0.0, acceleration * delta * 2)
velocity = velocity.normalized() * current_speed if current_speed > 10 else Vector2.ZERO
if velocity == Vector2.ZERO:
$AnimationPlayer.play("idle")
$sound/foot.play()
else:
$AnimationPlayer.play("walk")
func handle_rotation(delta):
var mouse_direction = (get_global_mouse_position() - global_position).normalized()
var target_angle = mouse_direction.angle()
# Более точный расчет угла поворота
var angle_diff = wrapf(target_angle - rotation, -PI, PI)
var rotation_step = deg_to_rad(degrees_per_sec) * delta
if abs(angle_diff) > rotation_step:
rotation += sign(angle_diff) * rotation_step
else:
rotation = target_angle
crosshair.position = get_global_mouse_position()
func handle_shooting():
if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && can_shot==true && reload_pistols==false:
# Логика стрельбы с разбросом
var fire_direction = (crosshair.position - global_position).normalized()
fire_direction = fire_direction.rotated(randf_range(-current_spread, current_spread))
$timerLight.start()
$PointLight2D.enabled=true
var bullet = bullet_tscn.instantiate()
bullet.position = $Marker2D.global_position
bullet.rotation = fire_direction.angle()+80
bullet.direction = fire_direction
$bullet_empty.add_child(bullet)
$sound/shot.play()
Globals.amountBullet-=1
current_spread = min(current_spread + spread_increase_per_shot, max_spread)
can_shot = false
$shotCooldown.start()
if Globals.amountBullet==0:
reload_p()
func update_spread(delta):
current_spread = move_toward(current_spread, 0, spread_recovery_speed * delta)
func _on_shot_timer_timeout() -> void:
can_shot = true
func _on_timer_light_timeout() -> void:
$PointLight2D.enabled=false
func update_crosshair():
$pricel.scale.x=max(4,current_spread*40)
$pricel.scale.y=max(4,current_spread*40)
func reload_p():
$sound/reloadPistolsSound.play()
$reloadPistos.start()
reload_pistols=true
func _on_reload_pistos_timeout() -> void:
Globals.amountBullet=10
reload_pistols=false
func hand_reload():
if Input.is_action_just_pressed("reload_p"):
reload_p()
func _on_shot_cooldown_timeout() -> void:
can_shot = true