extends Control class_name CharacterCreation ## 角色创建界面 ## 处理新角色的创建 # UI 元素 var character_name_input: LineEdit var create_button: Button var back_button: Button var customize_button: Button var status_label: Label var container: VBoxContainer var status_timer: Timer # 个性化数据 var character_appearance: Dictionary = {} var character_personality: Dictionary = {} # 自定义界面 var customization_ui: Control # 信号 signal character_created(character_name: String, personalization_data: Dictionary) signal back_requested() func _ready(): """初始化角色创建界面""" _create_ui() _setup_timer() _setup_animations() _initialize_personalization() update_layout() ## 设置动画效果 func _setup_animations(): """设置界面动画效果""" # 为移动设备优化触摸体验 TouchFeedbackManager.optimize_ui_for_touch(self) # 界面入场动画 UIAnimationManager.fade_slide_in(container, "right", 0.4) ## 设置定时器 func _setup_timer(): """设置状态标签自动清除定时器""" status_timer = Timer.new() status_timer.one_shot = true status_timer.timeout.connect(_on_status_timer_timeout) add_child(status_timer) ## 定时器超时 func _on_status_timer_timeout(): """定时器超时,清除状态标签""" clear_status() ## 创建 UI 元素 func _create_ui(): """创建角色创建界面的所有 UI 元素""" # 设置为全屏 anchor_right = 1.0 anchor_bottom = 1.0 # 创建中心容器 container = VBoxContainer.new() container.name = "Container" container.custom_minimum_size = Vector2(300, 0) # 设置容器锚点为居中 container.anchor_left = 0.5 container.anchor_right = 0.5 container.anchor_top = 0.5 container.anchor_bottom = 0.5 container.offset_left = -150 # 容器宽度的一半 container.offset_right = 150 container.offset_top = -200 # 估算容器高度的一半 container.offset_bottom = 200 add_child(container) # 标题 var title = Label.new() title.text = "创建角色" title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER title.add_theme_font_size_override("font_size", 32) container.add_child(title) # 间距 container.add_child(_create_spacer(20)) # 说明文本 var description = Label.new() description.text = "请输入你的角色名称(2-20个字符)" description.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER description.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART container.add_child(description) # 间距 container.add_child(_create_spacer(10)) # 角色名称标签 var name_label = Label.new() name_label.text = "角色名称:" container.add_child(name_label) # 角色名称输入框 character_name_input = LineEdit.new() character_name_input.placeholder_text = "输入角色名称" character_name_input.custom_minimum_size = Vector2(0, 40) character_name_input.max_length = 20 character_name_input.text_changed.connect(_on_name_changed) character_name_input.text_submitted.connect(_on_name_submitted) container.add_child(character_name_input) # 状态标签(放在输入框下方) status_label = Label.new() status_label.text = "" status_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER status_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART status_label.custom_minimum_size = Vector2(0, 30) status_label.add_theme_font_size_override("font_size", 16) container.add_child(status_label) # 间距 container.add_child(_create_spacer(10)) # 自定义按钮(默认禁用) customize_button = Button.new() customize_button.text = "自定义外观(暂未开放)" customize_button.custom_minimum_size = Vector2(0, 50) customize_button.disabled = true # 默认禁用 customize_button.pressed.connect(_on_customize_pressed) container.add_child(customize_button) # 间距 container.add_child(_create_spacer(10)) # 创建按钮 create_button = Button.new() create_button.text = "创建角色" create_button.custom_minimum_size = Vector2(0, 50) create_button.pressed.connect(_on_create_pressed) container.add_child(create_button) # 间距 container.add_child(_create_spacer(10)) # 返回按钮 back_button = Button.new() back_button.text = "返回" back_button.custom_minimum_size = Vector2(0, 50) back_button.pressed.connect(_on_back_pressed) container.add_child(back_button) ## 创建间距 func _create_spacer(height: float) -> Control: """创建垂直间距""" var spacer = Control.new() spacer.custom_minimum_size = Vector2(0, height) return spacer ## 更新布局 func update_layout(): """更新布局以适应窗口大小""" if not container: return # 容器已经通过锚点设置为居中,无需手动计算位置 # 锚点会自动适应窗口大小变化 ## 显示状态消息 func show_status(message: String, is_error: bool = false): """ 显示状态消息 @param message: 消息文本 @param is_error: 是否为错误消息 """ if status_label: status_label.text = message if is_error: status_label.add_theme_color_override("font_color", Color(1, 0.3, 0.3)) else: status_label.add_theme_color_override("font_color", Color(0.3, 1, 0.3)) # 启动定时器,1秒后自动清除(与ErrorNotification保持一致) if status_timer: status_timer.start(1.0) ## 清除状态消息 func clear_status(): """清除状态消息""" if status_timer: status_timer.stop() if status_label: status_label.text = "" ## 验证角色名称 func validate_character_name(char_name: String) -> String: """ 验证角色名称 @param char_name: 角色名称 @return: 错误消息,如果有效则返回空字符串 """ # 使用安全管理器进行验证 var validation_result = SecurityManager.validate_input(char_name, "character_name") if not validation_result.valid: return validation_result.error # 使用 CharacterData 的验证函数作为额外检查 if not CharacterData.validate_name(validation_result.sanitized): return "角色名称格式无效" return "" ## 名称输入变化 func _on_name_changed(new_text: String): """名称输入框内容变化""" # 实时验证 var error = validate_character_name(new_text) if error.is_empty(): clear_status() create_button.disabled = false else: show_status(error, true) create_button.disabled = true ## 创建按钮点击 func _on_create_pressed(): """创建按钮被点击""" var char_name = character_name_input.text # 验证名称 var error = validate_character_name(char_name) if not error.is_empty(): show_status(error, true) # 添加错误动画反馈 UIAnimationManager.shake_error(character_name_input, 8.0, 0.4) return # 获取清理后的名称 var validation_result = SecurityManager.validate_input(char_name, "character_name") var sanitized_name = validation_result.sanitized # 添加成功反馈动画 UIAnimationManager.button_press_feedback(create_button) clear_status() character_created.emit(sanitized_name, get_personalization_data()) ## 返回按钮点击 func _on_back_pressed(): """返回按钮被点击""" back_requested.emit() ## 名称输入框回车 func _on_name_submitted(_text: String): """名称输入框按下回车""" if not create_button.disabled: _on_create_pressed() ## 初始化个性化数据 func _initialize_personalization(): """初始化默认的个性化数据""" var personalization = preload("res://scripts/CharacterPersonalization.gd") character_appearance = personalization.generate_random_appearance() character_personality = personalization.generate_random_personality() ## 自定义按钮点击 func _on_customize_pressed(): """自定义按钮被点击""" # 检查按钮是否被禁用 if customize_button.disabled: show_status("自定义外观功能暂未开放", true) return if customization_ui: customization_ui.queue_free() var CharacterCustomizationClass = preload("res://scripts/CharacterCustomization.gd") customization_ui = CharacterCustomizationClass.new() get_tree().root.add_child(customization_ui) # 创建临时角色数据用于自定义 var temp_data = CharacterData.create("临时角色", "temp") CharacterData.set_appearance(temp_data, character_appearance) temp_data[CharacterData.FIELD_PERSONALITY] = character_personality customization_ui.load_character_data(temp_data) customization_ui.customization_saved.connect(_on_customization_saved) customization_ui.customization_cancelled.connect(_on_customization_cancelled) ## 自定义保存回调 func _on_customization_saved(data: Dictionary): """自定义数据保存回调""" character_appearance = data.get(CharacterData.FIELD_APPEARANCE, {}) character_personality = data.get(CharacterData.FIELD_PERSONALITY, {}) show_status("外观和个性已自定义", false) if customization_ui: customization_ui.queue_free() customization_ui = null ## 自定义取消回调 func _on_customization_cancelled(): """自定义取消回调""" if customization_ui: customization_ui.queue_free() customization_ui = null ## 获取个性化数据 func get_personalization_data() -> Dictionary: """ 获取当前的个性化数据 @return: 个性化数据字典 """ return { CharacterData.FIELD_APPEARANCE: character_appearance, CharacterData.FIELD_PERSONALITY: character_personality } ## 启用/禁用自定义外观功能 func set_customization_enabled(enabled: bool): """ 启用或禁用自定义外观功能 @param enabled: 是否启用 """ if customize_button: customize_button.disabled = not enabled if enabled: customize_button.text = "自定义外观" else: customize_button.text = "自定义外观(暂未开放)"