extends Node3D

@export var candy_count: int = 600
@export var enemy_count: int = 5
@export var spawn_area: Vector2 = Vector2(70, 70)
@onready var candy_scene = preload("res://candy.tscn")
@onready var enemy_scene = preload("res://vrag.tscn")

var candies:  Array[Node3D] = []
var enemies:  Array[Node3D] = []
var enemy_spawn_timer: Timer
var player_count: int = 0

# Пул для конфет и врагов
var candy_pool:  Array[Node3D] = []
var enemy_pool:  Array[Node3D] = []

func _ready():
	randomize()
	spawn_candies(candy_count)
	spawn_enemies(enemy_count)
		
		# Инициализация таймера для спавна врагов
	enemy_spawn_timer = Timer.new()
	enemy_spawn_timer.wait_time = 10.0
	enemy_spawn_timer.timeout.connect(_on_enemy_spawn_timer_timeout)
	enemy_spawn_timer.autostart = true
	add_child(enemy_spawn_timer)

func _process(_delta):

		# Удаляем освобожденные объекты из массива
	candies = candies.filter(is_instance_valid)
	enemies = enemies.filter(is_instance_valid)

func spawn_candies(count: int):
	for _i in range(count):
		spawn_new_candy()

func spawn_new_candy():
	var new_candy_instance = candy_scene.instantiate()
	var spawn_position = _generate_random_position()
	new_candy_instance.position = spawn_position
		# Изменяем способ подключения сигнала, чтобы передать оба аргумента
	new_candy_instance.candy_collected.connect(_on_candy_collected.bind(new_candy_instance))
	add_child(new_candy_instance)
	candies.append(new_candy_instance)

func spawn_enemies(count: int):
	for _i in range(count):
		var new_position = _generate_random_position()
		if _is_position_valid(new_position):
			var new_enemy_instance = get_enemy_from_pool() if enemy_pool else enemy_scene.instantiate()
			new_enemy_instance.position = new_position
			add_child(new_enemy_instance)
			enemies.append(new_enemy_instance)
			print("новый враг")
			
func _generate_random_position() -> Vector3:
	return Vector3(
		randf_range(-spawn_area.x, spawn_area.x),
		-0.8,  # Устанавливаем Y в 0, если конфеты и враги на земле
		randf_range(-spawn_area.y, spawn_area.y)
	)

func _is_position_valid(new_position: Vector3, min_distance: float = 10.0) -> bool:
	for enemy in enemies:
		if is_instance_valid(enemy) and not enemy.is_queued_for_deletion() and new_position.distance_to(enemy.position) < min_distance:
			return false
	return true

func _on_candy_collected(_player, candy_node):
	if candies.has(candy_node):
		candies.erase(candy_node)
		candy_node.disconnect("candy_collected", Callable(self, "_on_candy_collected"))
		candy_node.queue_free()
		spawn_new_candy()

func _on_enemy_spawn_timer_timeout():
	var enemies_to_spawn = enemy_count - enemies.size()
	if enemies_to_spawn > 0:
		spawn_enemies(enemies_to_spawn)

func remove_enemy(enemy_node):
	if is_instance_valid(enemy_node) and enemies.has(enemy_node):
		enemies.erase(enemy_node)
		return_enemy_to_pool(enemy_node)
	if player_count < 6 and enemy_spawn_timer.time_left == 0:
		_spawn_enemy_far()
		enemy_spawn_timer.start(10)  # Перезапускаем таймер на 10 секунд

func _spawn_enemy_far():
	var attempts = 0
	var max_attempts = 100
	var min_distance_from_others = 50.0  # Увеличиваем минимальное расстояние

	while attempts < max_attempts:
		var new_position = _generate_random_position()
		if _is_position_valid(new_position, min_distance_from_others):
			var new_enemy_instance = get_enemy_from_pool() if enemy_pool else enemy_scene.instantiate()
			new_enemy_instance.position = new_position
			add_child(new_enemy_instance)
			enemies.append(new_enemy_instance)
			print("Spawned new enemy to maintain player count.")
			return
		attempts += 1

	print("Failed to spawn enemy far enough from others after ", max_attempts, " attempts.")

# Функции для работы с пулом объектов
func get_candy_from_pool():
	if candy_pool.size() > 0:
		var candy = candy_pool.pop_back()
		candy.visible = true
		return candy
	return null

func return_candy_to_pool(candy):
	candy.visible = false
	candy_pool.push_back(candy)

func get_enemy_from_pool():
	if enemy_pool.size() > 0:
		var enemy = enemy_pool.pop_back()
		enemy.visible = true
		return enemy
	return null

func return_enemy_to_pool(enemy):
	enemy.visible = false
	enemy_pool.push_back(enemy)
Оптимизируй и улучши код для Godot 4.3