extends Node3D class_name LevelManager var target: int var level: Level var cur_level_instance: LevelInstance var level_instance_dict: Dictionary = {} var level_loading_time: float var level_active_spots: Array[Node] var level_character_born_spots: Array[LevelInstance.ChacacterBornSpot] var level_enemy_cfgs: Array[CharacterCfg] var level_doors: Array[LevelDoor] var is_level_active: bool var enemy_count: int # 由关卡生成的怪物数量 var current_enmey: Array[int] # 当前存活怪物id var replace_cache: LevelInstance func _ready(): Global.level_mgr = self SignalManager.character_create.connect(on_character_create) SignalManager.character_pos_changed.connect(on_character_pos_changed) SignalManager.character_die.connect(on_character_die) func init(): var level_scene: PackedScene = load("res://scene/level/level.tscn") level = level_scene.instantiate() as Level add_child(level) var level_instance_list: Array[LevelInstance] = level.get_level_instance_list() for level_instance in level_instance_list: var level_id_list: Array[Vector3i] = get_level_id_list(level_instance.get_global_position(), level_instance.size) for level_id in level_id_list: if level_id in level_instance_dict: print("关卡id重复", level_id) level_instance_dict[level_id] = level_instance level.init() func _process(delta) -> void: if not level: return if level_loading_time > 0: level_loading_time -= delta if level_loading_time <= 0: enter_level() SignalManager.level_loading_end.emit() Global.is_level_loading = false func get_born_pos() -> Vector3: return level.get_born_pos() func on_character_create(id: int, type: int, pos: Vector3): if type == Enum.ECharacterType.Player: target = id on_character_pos_changed(id, pos) elif type == Enum.ECharacterType.Monster: current_enmey.append(id) func on_character_pos_changed(id: int, pos: Vector3): if id == target: set_player_position(pos) func on_character_die(id: int) -> void: if id in current_enmey: current_enmey.remove_at(current_enmey.find(id)) #强制战斗关卡通关 if not cur_level_instance.is_force_battle: return if enemy_born(1): return if current_enmey.size() > 0: return for level_door: LevelDoor in level_doors: level_door.set_open(true) func set_player_position(pos: Vector3) -> void: level.set_player_position(pos) var new_level_instance: LevelInstance = get_level_by_pos(pos) if not new_level_instance: return # todo 不存在的关卡 主角直接死亡 var is_first_level: bool = cur_level_instance == null if !is_first_level: if new_level_instance == cur_level_instance: check_level_active(pos) return cur_level_instance = new_level_instance if is_first_level: enter_level() else: SignalManager.level_loading_start.emit() Global.is_level_loading = true level_loading_time = Setting.level_loading_time func enter_level() -> void: cur_level_instance.set_focus() is_level_active = false level_active_spots = [] level_doors = [] #创建关卡内活动部件 for level_active_spot: Node in level_active_spots: level_active_spot.queue_free() for level_active_spot: LevelInstance.LevelActiveSpot in cur_level_instance.get_level_active_spots(): var new_level_active: Node = level_active_spot.scene.instantiate() add_child(new_level_active) new_level_active.global_position = level_active_spot.pos level_active_spots.append(new_level_active) if new_level_active is LevelActive: new_level_active.init() if new_level_active is LevelDoor: level_doors.append(new_level_active) #更新刷怪数据 level_character_born_spots = cur_level_instance.get_character_born_spots() level_enemy_cfgs = cur_level_instance.get_enemy_cfgs() enemy_count = 0 #更新cell if replace_cache: replace_cache.set_replace(false) cur_level_instance.set_replace(true) replace_cache = cur_level_instance SignalManager.level_size_change.emit(cur_level_instance.get_level_size()) SignalManager.level_pos_change.emit(cur_level_instance.get_level_pos()) func check_level_active(pos: Vector3) -> void: if is_level_active: return var is_active: bool = cur_level_instance.is_in_active_area(pos) if not is_active: return is_level_active = true for level_door: LevelDoor in level_doors: level_door.set_open(true) #创建关卡内角色 for character_spot: LevelInstance.ChacacterSpot in cur_level_instance.get_character_spots(): Global.character_mgr.create_character(character_spot.cfg, Enum.ETeam.Monster, character_spot.pos) #强制战斗关门刷怪 if cur_level_instance.is_force_battle: if enemy_born(level_character_born_spots.size()): for level_door: LevelDoor in level_doors: level_door.set_open(false) func get_level_id_list(pos: Vector3, size: Vector3i) -> Array[Vector3i]: var size_basic: Vector3 = Setting.size_basic var ret: Array[Vector3i] = [] for x in range(size.x): for y in range(size.y): for z in range(size.z): var pos_sub: Vector3 = pos + Vector3(x * size_basic.x, y * size_basic.y, z * size_basic.z) ret.append(Util.get_level_id(pos_sub)) return ret func enemy_born(count: int) -> bool: if level_character_born_spots.size() == 0: return false var count_max: int = level_enemy_cfgs.size() count = min(count, count_max - enemy_count) if count == 0: return false var count_start: int = enemy_count for i in count: var cfg_index: int = count_start + i var cfg: CharacterCfg = level_enemy_cfgs[cfg_index] var pos_index: int = enemy_count % level_character_born_spots.size() var character_spot: LevelInstance.ChacacterBornSpot = level_character_born_spots[pos_index] Global.character_mgr.create_character(cfg, Enum.ETeam.Monster, character_spot.pos) enemy_count += 1 return true func get_level_by_pos(pos: Vector3) -> LevelInstance: var level_id: Vector3i = Util.get_level_id(pos) if level_id in level_instance_dict: return level_instance_dict.get(level_id) return null func get_cur_level_name() -> String: if not cur_level_instance: return "" return cur_level_instance.get_name()