You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			171 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			GDScript
		
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			GDScript
		
	
| extends Node3D
 | |
| class_name LevelManager
 | |
| 
 | |
| var target: int
 | |
| var level: Level
 | |
| var cur_level_instance: LevelInstance
 | |
| var level_instance_dict: Dictionary = {}
 | |
| var level_loading_rate: 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
 | |
| 
 | |
| 
 | |
| 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_rate < 1:
 | |
| 		level_loading_rate += delta *2
 | |
| 		if level_loading_rate > 1:
 | |
| 			level_loading_rate = 1
 | |
| 		level.set_level_loading_rate(level_loading_rate)
 | |
| 
 | |
| 
 | |
| 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):
 | |
| 	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_id: Vector3i                  = Util.get_level_id(pos)
 | |
| 	var new_level_instance: LevelInstance = level_instance_dict.get(new_id)
 | |
| 	if not new_level_instance:
 | |
| 		return #todo 不存在的关卡 主角直接死亡
 | |
| 	if cur_level_instance:
 | |
| 		if new_level_instance == cur_level_instance:
 | |
| 			check_level_active(pos)
 | |
| 			return
 | |
| 		cur_level_instance.set_focus_from(true)
 | |
| 
 | |
| 	new_level_instance.set_focus_to(true)
 | |
| 	cur_level_instance = new_level_instance
 | |
| 	enter_level()
 | |
| 
 | |
| 
 | |
| func enter_level() -> void:
 | |
| 	SignalManager.level_loading_start.emit()
 | |
| 	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 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
 | |
| 
 | |
| 	level_loading_rate = 1-level_loading_rate
 | |
| 	level.set_level_loading_rate(level_loading_rate)
 | |
| 	SignalManager.level_size_change.emit(cur_level_instance.get_level_size())
 | |
| 	SignalManager.level_pos_change.emit(cur_level_instance.get_level_pos())
 | |
| 
 | |
| 	SignalManager.level_loading_end.emit()
 | |
| 
 | |
| 
 | |
| 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 = 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
 |