[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HSFBSTAD4XNP7QD67WT6V8":3,"skill-same:01M6HSFBSTAD4XNP7QD67WT6V8":82},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":61,"commitSha":62,"skillDirectory":63,"forksCount":64,"repositoryHtmlUrl":65,"repositoryHomepageUrl":6,"ownerHtmlUrl":66,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":67,"install":68,"resources":81},"01M6HSFBSTAD4XNP7QD67WT6V8","audio-system",null,"音频系统技能。管理游戏音频播放，包括背景音乐、音效、语音等。 支持音频池、淡入淡出、3D 音效等功能。","welflau\u002Fai-dev-system","welflau","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F7010385?v=4","01M6HPTDGF18RFY07M229P8CTM","01M6HPTDMRMZCJPYBFEA9XVVYT",3,"MIT","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Fgodot-mcp\u002Fskills\u002Fgodot-dev\u002Flevel-2-modules\u002Faudio-system\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"audio system","Audio","system","false","sfx","manager","autoload","ambient","STRING","scripts","godot","core","type","music","voice","3D","file","2026-11-10 10:12:30",false,"---\nname: audio-system\ndescription: >\n  音频系统技能。管理游戏音频播放，包括背景音乐、音效、语音等。\n  支持音频池、淡入淡出、3D 音效等功能。\nversion: 1.0.0\ndependencies:\n  - godot-core\ntriggers:\n  - pattern: \"音频|音乐|音效|BGM|SFX|AudioManager\"\ninputs:\n  - name: audio_type\n    type: string\n    enum: [\"music\", \"sfx\", \"voice\", \"ambient\"]\n    required: false\noutputs:\n  - name: audio_manager\n    type: file\n    path_pattern: \"res:\u002F\u002Fscripts\u002Fautoload\u002Faudio_manager.gd\"\n---\n\n# 音频系统技能\n\n管理游戏中的所有音频播放。\n\n## 音频总线配置\n\n在 Godot 中配置以下音频总线：\n\n```\nMaster\n├── Music      # 背景音乐\n├── SFX        # 音效\n├── Voice      # 语音\n└── Ambient    # 环境音\n```\n\n---\n\n## 音频管理器\n\n### audio_manager.gd (Autoload)\n\n```gdscript\n## 音频管理器\n##\n## 统一管理所有音频播放\n## @author AI Generated\n## @version 1.0.0\nclass_name AudioManager\nextends Node\n\n# region 信号\nsignal music_started(track_name: String)\nsignal music_stopped\nsignal music_changed(old_track: String, new_track: String)\n# endregion\n\n# region 常量\nconst MUSIC_BUS = \"Music\"\nconst SFX_BUS = \"SFX\"\nconst VOICE_BUS = \"Voice\"\nconst AMBIENT_BUS = \"Ambient\"\n# endregion\n\n# region 导出变量\n@export var sfx_pool_size: int = 16\n@export var default_music_fade_time: float = 1.0\n# endregion\n\n# region 节点引用\nvar _music_player: AudioStreamPlayer\nvar _music_player_2: AudioStreamPlayer  # 用于交叉淡化\nvar _voice_player: AudioStreamPlayer\nvar _ambient_player: AudioStreamPlayer\nvar _sfx_pool: Array[AudioStreamPlayer] = []\nvar _sfx_pool_3d: Array[AudioStreamPlayer3D] = []\n# endregion\n\n# region 状态\nvar current_music: String = \"\"\nvar _music_volume: float = 1.0\nvar _sfx_volume: float = 1.0\nvar _voice_volume: float = 1.0\nvar _is_music_fading: bool = false\nvar _active_player: AudioStreamPlayer = null\n# endregion\n\n# region 预加载音频缓存\nvar _audio_cache: Dictionary = {}\n# endregion\n\n# region 生命周期\nfunc _ready() -> void:\n    _setup_music_players()\n    _setup_sfx_pool()\n    _setup_voice_player()\n    _setup_ambient_player()\n\nfunc _setup_music_players() -> void:\n    _music_player = AudioStreamPlayer.new()\n    _music_player.bus = MUSIC_BUS\n    add_child(_music_player)\n    \n    _music_player_2 = AudioStreamPlayer.new()\n    _music_player_2.bus = MUSIC_BUS\n    add_child(_music_player_2)\n    \n    _active_player = _music_player\n\nfunc _setup_sfx_pool() -> void:\n    for i in range(sfx_pool_size):\n        var player = AudioStreamPlayer.new()\n        player.bus = SFX_BUS\n        add_child(player)\n        _sfx_pool.append(player)\n        \n        var player_3d = AudioStreamPlayer3D.new()\n        player_3d.bus = SFX_BUS\n        add_child(player_3d)\n        _sfx_pool_3d.append(player_3d)\n\nfunc _setup_voice_player() -> void:\n    _voice_player = AudioStreamPlayer.new()\n    _voice_player.bus = VOICE_BUS\n    add_child(_voice_player)\n\nfunc _setup_ambient_player() -> void:\n    _ambient_player = AudioStreamPlayer.new()\n    _ambient_player.bus = AMBIENT_BUS\n    add_child(_ambient_player)\n# endregion\n\n# region 音乐播放\n## 播放背景音乐\nfunc play_music(track_path: String, fade_time: float = -1, loop: bool = true) -> void:\n    if fade_time \u003C 0:\n        fade_time = default_music_fade_time\n    \n    var stream = _get_audio_stream(track_path)\n    if not stream:\n        push_error(\"Music not found: \" + track_path)\n        return\n    \n    var old_track = current_music\n    current_music = track_path\n    \n    if fade_time > 0 and _active_player.playing:\n        _crossfade_music(stream, fade_time, loop)\n    else:\n        _active_player.stream = stream\n        _active_player.play()\n    \n    music_started.emit(track_path)\n    if old_track != track_path:\n        music_changed.emit(old_track, track_path)\n\n## 停止背景音乐\nfunc stop_music(fade_time: float = -1) -> void:\n    if fade_time \u003C 0:\n        fade_time = default_music_fade_time\n    \n    if fade_time > 0:\n        _fade_out_music(fade_time)\n    else:\n        _active_player.stop()\n    \n    current_music = \"\"\n    music_stopped.emit()\n\n## 暂停背景音乐\nfunc pause_music() -> void:\n    _active_player.stream_paused = true\n\n## 继续背景音乐\nfunc resume_music() -> void:\n    _active_player.stream_paused = false\n\n## 交叉淡化\nfunc _crossfade_music(new_stream: AudioStream, duration: float, loop: bool) -> void:\n    _is_music_fading = true\n    \n    var old_player = _active_player\n    var new_player = _music_player if _active_player == _music_player_2 else _music_player_2\n    \n    new_player.stream = new_stream\n    new_player.volume_db = -80\n    new_player.play()\n    \n    var tween = create_tween()\n    tween.set_parallel(true)\n    tween.tween_property(old_player, \"volume_db\", -80, duration)\n    tween.tween_property(new_player, \"volume_db\", linear_to_db(_music_volume), duration)\n    \n    await tween.finished\n    \n    old_player.stop()\n    old_player.volume_db = linear_to_db(_music_volume)\n    _active_player = new_player\n    _is_music_fading = false\n\nfunc _fade_out_music(duration: float) -> void:\n    var tween = create_tween()\n    tween.tween_property(_active_player, \"volume_db\", -80, duration)\n    await tween.finished\n    _active_player.stop()\n    _active_player.volume_db = linear_to_db(_music_volume)\n# endregion\n\n# region 音效播放\n## 播放 2D 音效\nfunc play_sfx(sound_path: String, volume: float = 1.0, pitch: float = 1.0) -> AudioStreamPlayer:\n    var stream = _get_audio_stream(sound_path)\n    if not stream:\n        push_error(\"SFX not found: \" + sound_path)\n        return null\n    \n    var player = _get_available_sfx_player()\n    if player:\n        player.stream = stream\n        player.volume_db = linear_to_db(volume * _sfx_volume)\n        player.pitch_scale = pitch\n        player.play()\n    \n    return player\n\n## 播放带随机音高的音效\nfunc play_sfx_pitched(sound_path: String, pitch_range: Vector2 = Vector2(0.9, 1.1), volume: float = 1.0) -> AudioStreamPlayer:\n    var pitch = randf_range(pitch_range.x, pitch_range.y)\n    return play_sfx(sound_path, volume, pitch)\n\n## 播放 3D 音效\nfunc play_sfx_3d(sound_path: String, position: Vector3, volume: float = 1.0, pitch: float = 1.0) -> AudioStreamPlayer3D:\n    var stream = _get_audio_stream(sound_path)\n    if not stream:\n        push_error(\"SFX not found: \" + sound_path)\n        return null\n    \n    var player = _get_available_sfx_player_3d()\n    if player:\n        player.stream = stream\n        player.global_position = position\n        player.volume_db = linear_to_db(volume * _sfx_volume)\n        player.pitch_scale = pitch\n        player.play()\n    \n    return player\n\n## 播放 3D 音效（附加到节点）\nfunc play_sfx_at_node(sound_path: String, node: Node3D, volume: float = 1.0) -> AudioStreamPlayer3D:\n    return play_sfx_3d(sound_path, node.global_position, volume)\n\nfunc _get_available_sfx_player() -> AudioStreamPlayer:\n    for player in _sfx_pool:\n        if not player.playing:\n            return player\n    \n    # 如果所有都在使用，返回第一个（会被覆盖）\n    return _sfx_pool[0]\n\nfunc _get_available_sfx_player_3d() -> AudioStreamPlayer3D:\n    for player in _sfx_pool_3d:\n        if not player.playing:\n            return player\n    \n    return _sfx_pool_3d[0]\n# endregion\n\n# region 语音播放\n## 播放语音\nfunc play_voice(voice_path: String, on_finished: Callable = Callable()) -> void:\n    var stream = _get_audio_stream(voice_path)\n    if not stream:\n        push_error(\"Voice not found: \" + voice_path)\n        return\n    \n    # 停止当前语音\n    if _voice_player.playing:\n        _voice_player.stop()\n    \n    _voice_player.stream = stream\n    _voice_player.play()\n    \n    if on_finished.is_valid():\n        await _voice_player.finished\n        on_finished.call()\n\n## 停止语音\nfunc stop_voice() -> void:\n    _voice_player.stop()\n\n## 检查语音是否在播放\nfunc is_voice_playing() -> bool:\n    return _voice_player.playing\n# endregion\n\n# region 环境音\n## 播放环境音\nfunc play_ambient(ambient_path: String, fade_time: float = 1.0) -> void:\n    var stream = _get_audio_stream(ambient_path)\n    if not stream:\n        return\n    \n    _ambient_player.stream = stream\n    _ambient_player.volume_db = -80\n    _ambient_player.play()\n    \n    var tween = create_tween()\n    tween.tween_property(_ambient_player, \"volume_db\", 0, fade_time)\n\n## 停止环境音\nfunc stop_ambient(fade_time: float = 1.0) -> void:\n    var tween = create_tween()\n    tween.tween_property(_ambient_player, \"volume_db\", -80, fade_time)\n    await tween.finished\n    _ambient_player.stop()\n# endregion\n\n# region 音量控制\nfunc set_master_volume(volume: float) -> void:\n    var bus_index = AudioServer.get_bus_index(\"Master\")\n    AudioServer.set_bus_volume_db(bus_index, linear_to_db(volume))\n\nfunc set_music_volume(volume: float) -> void:\n    _music_volume = volume\n    var bus_index = AudioServer.get_bus_index(MUSIC_BUS)\n    AudioServer.set_bus_volume_db(bus_index, linear_to_db(volume))\n\nfunc set_sfx_volume(volume: float) -> void:\n    _sfx_volume = volume\n    var bus_index = AudioServer.get_bus_index(SFX_BUS)\n    AudioServer.set_bus_volume_db(bus_index, linear_to_db(volume))\n\nfunc set_voice_volume(volume: float) -> void:\n    _voice_volume = volume\n    var bus_index = AudioServer.get_bus_index(VOICE_BUS)\n    AudioServer.set_bus_volume_db(bus_index, linear_to_db(volume))\n\nfunc get_music_volume() -> float:\n    return _music_volume\n\nfunc get_sfx_volume() -> float:\n    return _sfx_volume\n\nfunc get_voice_volume() -> float:\n    return _voice_volume\n\n## 静音\u002F取消静音\nfunc mute_bus(bus_name: String, muted: bool) -> void:\n    var bus_index = AudioServer.get_bus_index(bus_name)\n    AudioServer.set_bus_mute(bus_index, muted)\n\nfunc is_bus_muted(bus_name: String) -> bool:\n    var bus_index = AudioServer.get_bus_index(bus_name)\n    return AudioServer.is_bus_mute(bus_index)\n# endregion\n\n# region 音频缓存\nfunc preload_audio(paths: Array) -> void:\n    for path in paths:\n        _get_audio_stream(path)\n\nfunc _get_audio_stream(path: String) -> AudioStream:\n    if _audio_cache.has(path):\n        return _audio_cache[path]\n    \n    if ResourceLoader.exists(path):\n        var stream = load(path)\n        _audio_cache[path] = stream\n        return stream\n    \n    return null\n\nfunc clear_audio_cache() -> void:\n    _audio_cache.clear()\n# endregion\n```\n\n---\n\n## 音效触发器组件\n\n### sfx_trigger.gd\n\n```gdscript\n## 音效触发器\n##\n## 在特定事件时播放音效\nclass_name SFXTrigger\nextends Node\n\n@export var sound_path: String\n@export var volume: float = 1.0\n@export var pitch_variation: Vector2 = Vector2(1.0, 1.0)\n@export var trigger_on_ready: bool = false\n@export var cooldown: float = 0.0\n\nvar _can_play: bool = true\n\nfunc _ready() -> void:\n    if trigger_on_ready:\n        play()\n\nfunc play() -> void:\n    if not _can_play:\n        return\n    \n    var pitch = randf_range(pitch_variation.x, pitch_variation.y)\n    AudioManager.play_sfx(sound_path, volume, pitch)\n    \n    if cooldown > 0:\n        _can_play = false\n        await get_tree().create_timer(cooldown).timeout\n        _can_play = true\n```\n\n### 区域音效触发器\n\n```gdscript\n## 区域音效触发器\nclass_name AreaSFXTrigger\nextends Area3D\n\n@export var sound_path: String\n@export var volume: float = 1.0\n@export var one_shot: bool = true\n\nvar _triggered: bool = false\n\nfunc _ready() -> void:\n    body_entered.connect(_on_body_entered)\n\nfunc _on_body_entered(body: Node3D) -> void:\n    if one_shot and _triggered:\n        return\n    \n    if body.is_in_group(\"player\"):\n        AudioManager.play_sfx_3d(sound_path, global_position, volume)\n        _triggered = true\n```\n\n---\n\n## 音乐区域\n\n### music_zone.gd\n\n```gdscript\n## 音乐区域\n##\n## 进入区域时切换背景音乐\nclass_name MusicZone\nextends Area3D\n\n@export var music_path: String\n@export var fade_time: float = 2.0\n@export var priority: int = 0\n\nvar _previous_music: String = \"\"\n\nfunc _ready() -> void:\n    body_entered.connect(_on_body_entered)\n    body_exited.connect(_on_body_exited)\n\nfunc _on_body_entered(body: Node3D) -> void:\n    if body.is_in_group(\"player\"):\n        _previous_music = AudioManager.current_music\n        AudioManager.play_music(music_path, fade_time)\n\nfunc _on_body_exited(body: Node3D) -> void:\n    if body.is_in_group(\"player\"):\n        if _previous_music:\n            AudioManager.play_music(_previous_music, fade_time)\n```\n\n---\n\n## 随机音效播放器\n\n### random_sfx_player.gd\n\n```gdscript\n## 随机音效播放器\n##\n## 从列表中随机播放音效\nclass_name RandomSFXPlayer\nextends Node\n\n@export var sounds: Array[String] = []\n@export var volume: float = 1.0\n@export var pitch_variation: Vector2 = Vector2(0.9, 1.1)\n@export var avoid_repeat: bool = true\n\nvar _last_played_index: int = -1\n\nfunc play() -> void:\n    if sounds.is_empty():\n        return\n    \n    var index = randi() % sounds.size()\n    \n    if avoid_repeat and sounds.size() > 1:\n        while index == _last_played_index:\n            index = randi() % sounds.size()\n    \n    _last_played_index = index\n    \n    var pitch = randf_range(pitch_variation.x, pitch_variation.y)\n    AudioManager.play_sfx(sounds[index], volume, pitch)\n\nfunc play_at_position(position: Vector3) -> void:\n    if sounds.is_empty():\n        return\n    \n    var index = randi() % sounds.size()\n    if avoid_repeat and sounds.size() > 1:\n        while index == _last_played_index:\n            index = randi() % sounds.size()\n    \n    _last_played_index = index\n    \n    var pitch = randf_range(pitch_variation.x, pitch_variation.y)\n    AudioManager.play_sfx_3d(sounds[index], position, volume, pitch)\n```\n\n---\n\n## 脚步声系统\n\n### footstep_system.gd\n\n```gdscript\n## 脚步声系统\nclass_name FootstepSystem\nextends Node\n\n@export var character: CharacterBody3D\n@export var step_interval: float = 0.5\n@export var run_step_interval: float = 0.3\n\nvar _step_timer: float = 0.0\nvar _surface_detector: RayCast3D\n\n# 表面类型 -> 音效列表\nvar _surface_sounds: Dictionary = {\n    \"default\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fconcrete_01.ogg\"],\n    \"grass\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fgrass_01.ogg\"],\n    \"wood\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fwood_01.ogg\"],\n    \"metal\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fmetal_01.ogg\"],\n    \"water\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fwater_01.ogg\"]\n}\n\nfunc _ready() -> void:\n    _setup_surface_detector()\n\nfunc _setup_surface_detector() -> void:\n    _surface_detector = RayCast3D.new()\n    _surface_detector.target_position = Vector3(0, -1, 0)\n    character.add_child(_surface_detector)\n\nfunc _physics_process(delta: float) -> void:\n    if not character.is_on_floor():\n        return\n    \n    var velocity = character.velocity\n    var speed = Vector2(velocity.x, velocity.z).length()\n    \n    if speed \u003C 0.1:\n        return\n    \n    _step_timer += delta\n    var interval = run_step_interval if speed > 5.0 else step_interval\n    \n    if _step_timer >= interval:\n        _step_timer = 0.0\n        _play_footstep()\n\nfunc _play_footstep() -> void:\n    var surface = _detect_surface()\n    var sounds = _surface_sounds.get(surface, _surface_sounds[\"default\"])\n    var sound = sounds[randi() % sounds.size()]\n    \n    AudioManager.play_sfx_pitched(sound, Vector2(0.9, 1.1), 0.7)\n\nfunc _detect_surface() -> String:\n    if _surface_detector.is_colliding():\n        var collider = _surface_detector.get_collider()\n        if collider.has_meta(\"surface_type\"):\n            return collider.get_meta(\"surface_type\")\n    \n    return \"default\"\n```\n\n---\n\n## 配置示例\n\n### audio_config.json\n\n```json\n{\n  \"music\": {\n    \"main_menu\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fmain_menu.ogg\",\n    \"gameplay\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fgameplay.ogg\",\n    \"boss\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fboss.ogg\",\n    \"victory\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fvictory.ogg\",\n    \"game_over\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fgame_over.ogg\"\n  },\n  \"sfx\": {\n    \"ui\": {\n      \"click\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fui\u002Fclick.ogg\",\n      \"hover\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fui\u002Fhover.ogg\",\n      \"confirm\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fui\u002Fconfirm.ogg\",\n      \"cancel\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fui\u002Fcancel.ogg\"\n    },\n    \"player\": {\n      \"jump\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fjump.ogg\",\n      \"land\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fland.ogg\",\n      \"hurt\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fhurt.ogg\",\n      \"attack\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fattack_01.ogg\", \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fattack_02.ogg\"]\n    }\n  },\n  \"ambient\": {\n    \"forest\": \"res:\u002F\u002Fassets\u002Faudio\u002Fambient\u002Fforest.ogg\",\n    \"cave\": \"res:\u002F\u002Fassets\u002Faudio\u002Fambient\u002Fcave.ogg\",\n    \"rain\": \"res:\u002F\u002Fassets\u002Faudio\u002Fambient\u002Frain.ogg\"\n  }\n}\n```\n\n---\n\n## 使用示例\n\n```gdscript\n# 播放背景音乐\nAudioManager.play_music(\"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fgameplay.ogg\")\n\n# 带淡入淡出切换音乐\nAudioManager.play_music(\"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fboss.ogg\", 2.0)\n\n# 播放音效\nAudioManager.play_sfx(\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fexplosion.ogg\")\n\n# 播放带随机音高的音效\nAudioManager.play_sfx_pitched(\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fhit.ogg\")\n\n# 播放 3D 音效\nAudioManager.play_sfx_3d(\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fexplosion.ogg\", enemy.global_position)\n\n# 播放语音\nAudioManager.play_voice(\"res:\u002F\u002Fassets\u002Faudio\u002Fvoice\u002Fgreeting.ogg\", func():\n    print(\"Voice finished\")\n)\n\n# 调整音量\nAudioManager.set_music_volume(0.5)\nAudioManager.set_sfx_volume(0.8)\n```\n","# 音频系统技能\n\n管理游戏中的所有音频播放。\n\n## 音频总线配置\n\n在 Godot 中配置以下音频总线：\n\n```\nMaster\n├── Music      # 背景音乐\n├── SFX        # 音效\n├── Voice      # 语音\n└── Ambient    # 环境音\n```\n\n---\n\n## 音频管理器\n\n### audio_manager.gd (Autoload)\n\n```gdscript\n## 音频管理器\n##\n## 统一管理所有音频播放\n## @author AI Generated\n## @version 1.0.0\nclass_name AudioManager\nextends Node\n\n# region 信号\nsignal music_started(track_name: String)\nsignal music_stopped\nsignal music_changed(old_track: String, new_track: String)\n# endregion\n\n# region 常量\nconst MUSIC_BUS = \"Music\"\nconst SFX_BUS = \"SFX\"\nconst VOICE_BUS = \"Voice\"\nconst AMBIENT_BUS = \"Ambient\"\n# endregion\n\n# region 导出变量\n@export var sfx_pool_size: int = 16\n@export var default_music_fade_time: float = 1.0\n# endregion\n\n# region 节点引用\nvar _music_player: AudioStreamPlayer\nvar _music_player_2: AudioStreamPlayer  # 用于交叉淡化\nvar _voice_player: AudioStreamPlayer\nvar _ambient_player: AudioStreamPlayer\nvar _sfx_pool: Array[AudioStreamPlayer] = []\nvar _sfx_pool_3d: Array[AudioStreamPlayer3D] = []\n# endregion\n\n# region 状态\nvar current_music: String = \"\"\nvar _music_volume: float = 1.0\nvar _sfx_volume: float = 1.0\nvar _voice_volume: float = 1.0\nvar _is_music_fading: bool = false\nvar _active_player: AudioStreamPlayer = null\n# endregion\n\n# region 预加载音频缓存\nvar _audio_cache: Dictionary = {}\n# endregion\n\n# region 生命周期\nfunc _ready() -> void:\n    _setup_music_players()\n    _setup_sfx_pool()\n    _setup_voice_player()\n    _setup_ambient_player()\n\nfunc _setup_music_players() -> void:\n    _music_player = AudioStreamPlayer.new()\n    _music_player.bus = MUSIC_BUS\n    add_child(_music_player)\n    \n    _music_player_2 = AudioStreamPlayer.new()\n    _music_player_2.bus = MUSIC_BUS\n    add_child(_music_player_2)\n    \n    _active_player = _music_player\n\nfunc _setup_sfx_pool() -> void:\n    for i in range(sfx_pool_size):\n        var player = AudioStreamPlayer.new()\n        player.bus = SFX_BUS\n        add_child(player)\n        _sfx_pool.append(player)\n        \n        var player_3d = AudioStreamPlayer3D.new()\n        player_3d.bus = SFX_BUS\n        add_child(player_3d)\n        _sfx_pool_3d.append(player_3d)\n\nfunc _setup_voice_player() -> void:\n    _voice_player = AudioStreamPlayer.new()\n    _voice_player.bus = VOICE_BUS\n    add_child(_voice_player)\n\nfunc _setup_ambient_player() -> void:\n    _ambient_player = AudioStreamPlayer.new()\n    _ambient_player.bus = AMBIENT_BUS\n    add_child(_ambient_player)\n# endregion\n\n# region 音乐播放\n## 播放背景音乐\nfunc play_music(track_path: String, fade_time: float = -1, loop: bool = true) -> void:\n    if fade_time \u003C 0:\n        fade_time = default_music_fade_time\n    \n    var stream = _get_audio_stream(track_path)\n    if not stream:\n        push_error(\"Music not found: \" + track_path)\n        return\n    \n    var old_track = current_music\n    current_music = track_path\n    \n    if fade_time > 0 and _active_player.playing:\n        _crossfade_music(stream, fade_time, loop)\n    else:\n        _active_player.stream = stream\n        _active_player.play()\n    \n    music_started.emit(track_path)\n    if old_track != track_path:\n        music_changed.emit(old_track, track_path)\n\n## 停止背景音乐\nfunc stop_music(fade_time: float = -1) -> void:\n    if fade_time \u003C 0:\n        fade_time = default_music_fade_time\n    \n    if fade_time > 0:\n        _fade_out_music(fade_time)\n    else:\n        _active_player.stop()\n    \n    current_music = \"\"\n    music_stopped.emit()\n\n## 暂停背景音乐\nfunc pause_music() -> void:\n    _active_player.stream_paused = true\n\n## 继续背景音乐\nfunc resume_music() -> void:\n    _active_player.stream_paused = false\n\n## 交叉淡化\nfunc _crossfade_music(new_stream: AudioStream, duration: float, loop: bool) -> void:\n    _is_music_fading = true\n    \n    var old_player = _active_player\n    var new_player = _music_player if _active_player == _music_player_2 else _music_player_2\n    \n    new_player.stream = new_stream\n    new_player.volume_db = -80\n    new_player.play()\n    \n    var tween = create_tween()\n    tween.set_parallel(true)\n    tween.tween_property(old_player, \"volume_db\", -80, duration)\n    tween.tween_property(new_player, \"volume_db\", linear_to_db(_music_volume), duration)\n    \n    await tween.finished\n    \n    old_player.stop()\n    old_player.volume_db = linear_to_db(_music_volume)\n    _active_player = new_player\n    _is_music_fading = false\n\nfunc _fade_out_music(duration: float) -> void:\n    var tween = create_tween()\n    tween.tween_property(_active_player, \"volume_db\", -80, duration)\n    await tween.finished\n    _active_player.stop()\n    _active_player.volume_db = linear_to_db(_music_volume)\n# endregion\n\n# region 音效播放\n## 播放 2D 音效\nfunc play_sfx(sound_path: String, volume: float = 1.0, pitch: float = 1.0) -> AudioStreamPlayer:\n    var stream = _get_audio_stream(sound_path)\n    if not stream:\n        push_error(\"SFX not found: \" + sound_path)\n        return null\n    \n    var player = _get_available_sfx_player()\n    if player:\n        player.stream = stream\n        player.volume_db = linear_to_db(volume * _sfx_volume)\n        player.pitch_scale = pitch\n        player.play()\n    \n    return player\n\n## 播放带随机音高的音效\nfunc play_sfx_pitched(sound_path: String, pitch_range: Vector2 = Vector2(0.9, 1.1), volume: float = 1.0) -> AudioStreamPlayer:\n    var pitch = randf_range(pitch_range.x, pitch_range.y)\n    return play_sfx(sound_path, volume, pitch)\n\n## 播放 3D 音效\nfunc play_sfx_3d(sound_path: String, position: Vector3, volume: float = 1.0, pitch: float = 1.0) -> AudioStreamPlayer3D:\n    var stream = _get_audio_stream(sound_path)\n    if not stream:\n        push_error(\"SFX not found: \" + sound_path)\n        return null\n    \n    var player = _get_available_sfx_player_3d()\n    if player:\n        player.stream = stream\n        player.global_position = position\n        player.volume_db = linear_to_db(volume * _sfx_volume)\n        player.pitch_scale = pitch\n        player.play()\n    \n    return player\n\n## 播放 3D 音效（附加到节点）\nfunc play_sfx_at_node(sound_path: String, node: Node3D, volume: float = 1.0) -> AudioStreamPlayer3D:\n    return play_sfx_3d(sound_path, node.global_position, volume)\n\nfunc _get_available_sfx_player() -> AudioStreamPlayer:\n    for player in _sfx_pool:\n        if not player.playing:\n            return player\n    \n    # 如果所有都在使用，返回第一个（会被覆盖）\n    return _sfx_pool[0]\n\nfunc _get_available_sfx_player_3d() -> AudioStreamPlayer3D:\n    for player in _sfx_pool_3d:\n        if not player.playing:\n            return player\n    \n    return _sfx_pool_3d[0]\n# endregion\n\n# region 语音播放\n## 播放语音\nfunc play_voice(voice_path: String, on_finished: Callable = Callable()) -> void:\n    var stream = _get_audio_stream(voice_path)\n    if not stream:\n        push_error(\"Voice not found: \" + voice_path)\n        return\n    \n    # 停止当前语音\n    if _voice_player.playing:\n        _voice_player.stop()\n    \n    _voice_player.stream = stream\n    _voice_player.play()\n    \n    if on_finished.is_valid():\n        await _voice_player.finished\n        on_finished.call()\n\n## 停止语音\nfunc stop_voice() -> void:\n    _voice_player.stop()\n\n## 检查语音是否在播放\nfunc is_voice_playing() -> bool:\n    return _voice_player.playing\n# endregion\n\n# region 环境音\n## 播放环境音\nfunc play_ambient(ambient_path: String, fade_time: float = 1.0) -> void:\n    var stream = _get_audio_stream(ambient_path)\n    if not stream:\n        return\n    \n    _ambient_player.stream = stream\n    _ambient_player.volume_db = -80\n    _ambient_player.play()\n    \n    var tween = create_tween()\n    tween.tween_property(_ambient_player, \"volume_db\", 0, fade_time)\n\n## 停止环境音\nfunc stop_ambient(fade_time: float = 1.0) -> void:\n    var tween = create_tween()\n    tween.tween_property(_ambient_player, \"volume_db\", -80, fade_time)\n    await tween.finished\n    _ambient_player.stop()\n# endregion\n\n# region 音量控制\nfunc set_master_volume(volume: float) -> void:\n    var bus_index = AudioServer.get_bus_index(\"Master\")\n    AudioServer.set_bus_volume_db(bus_index, linear_to_db(volume))\n\nfunc set_music_volume(volume: float) -> void:\n    _music_volume = volume\n    var bus_index = AudioServer.get_bus_index(MUSIC_BUS)\n    AudioServer.set_bus_volume_db(bus_index, linear_to_db(volume))\n\nfunc set_sfx_volume(volume: float) -> void:\n    _sfx_volume = volume\n    var bus_index = AudioServer.get_bus_index(SFX_BUS)\n    AudioServer.set_bus_volume_db(bus_index, linear_to_db(volume))\n\nfunc set_voice_volume(volume: float) -> void:\n    _voice_volume = volume\n    var bus_index = AudioServer.get_bus_index(VOICE_BUS)\n    AudioServer.set_bus_volume_db(bus_index, linear_to_db(volume))\n\nfunc get_music_volume() -> float:\n    return _music_volume\n\nfunc get_sfx_volume() -> float:\n    return _sfx_volume\n\nfunc get_voice_volume() -> float:\n    return _voice_volume\n\n## 静音\u002F取消静音\nfunc mute_bus(bus_name: String, muted: bool) -> void:\n    var bus_index = AudioServer.get_bus_index(bus_name)\n    AudioServer.set_bus_mute(bus_index, muted)\n\nfunc is_bus_muted(bus_name: String) -> bool:\n    var bus_index = AudioServer.get_bus_index(bus_name)\n    return AudioServer.is_bus_mute(bus_index)\n# endregion\n\n# region 音频缓存\nfunc preload_audio(paths: Array) -> void:\n    for path in paths:\n        _get_audio_stream(path)\n\nfunc _get_audio_stream(path: String) -> AudioStream:\n    if _audio_cache.has(path):\n        return _audio_cache[path]\n    \n    if ResourceLoader.exists(path):\n        var stream = load(path)\n        _audio_cache[path] = stream\n        return stream\n    \n    return null\n\nfunc clear_audio_cache() -> void:\n    _audio_cache.clear()\n# endregion\n```\n\n---\n\n## 音效触发器组件\n\n### sfx_trigger.gd\n\n```gdscript\n## 音效触发器\n##\n## 在特定事件时播放音效\nclass_name SFXTrigger\nextends Node\n\n@export var sound_path: String\n@export var volume: float = 1.0\n@export var pitch_variation: Vector2 = Vector2(1.0, 1.0)\n@export var trigger_on_ready: bool = false\n@export var cooldown: float = 0.0\n\nvar _can_play: bool = true\n\nfunc _ready() -> void:\n    if trigger_on_ready:\n        play()\n\nfunc play() -> void:\n    if not _can_play:\n        return\n    \n    var pitch = randf_range(pitch_variation.x, pitch_variation.y)\n    AudioManager.play_sfx(sound_path, volume, pitch)\n    \n    if cooldown > 0:\n        _can_play = false\n        await get_tree().create_timer(cooldown).timeout\n        _can_play = true\n```\n\n### 区域音效触发器\n\n```gdscript\n## 区域音效触发器\nclass_name AreaSFXTrigger\nextends Area3D\n\n@export var sound_path: String\n@export var volume: float = 1.0\n@export var one_shot: bool = true\n\nvar _triggered: bool = false\n\nfunc _ready() -> void:\n    body_entered.connect(_on_body_entered)\n\nfunc _on_body_entered(body: Node3D) -> void:\n    if one_shot and _triggered:\n        return\n    \n    if body.is_in_group(\"player\"):\n        AudioManager.play_sfx_3d(sound_path, global_position, volume)\n        _triggered = true\n```\n\n---\n\n## 音乐区域\n\n### music_zone.gd\n\n```gdscript\n## 音乐区域\n##\n## 进入区域时切换背景音乐\nclass_name MusicZone\nextends Area3D\n\n@export var music_path: String\n@export var fade_time: float = 2.0\n@export var priority: int = 0\n\nvar _previous_music: String = \"\"\n\nfunc _ready() -> void:\n    body_entered.connect(_on_body_entered)\n    body_exited.connect(_on_body_exited)\n\nfunc _on_body_entered(body: Node3D) -> void:\n    if body.is_in_group(\"player\"):\n        _previous_music = AudioManager.current_music\n        AudioManager.play_music(music_path, fade_time)\n\nfunc _on_body_exited(body: Node3D) -> void:\n    if body.is_in_group(\"player\"):\n        if _previous_music:\n            AudioManager.play_music(_previous_music, fade_time)\n```\n\n---\n\n## 随机音效播放器\n\n### random_sfx_player.gd\n\n```gdscript\n## 随机音效播放器\n##\n## 从列表中随机播放音效\nclass_name RandomSFXPlayer\nextends Node\n\n@export var sounds: Array[String] = []\n@export var volume: float = 1.0\n@export var pitch_variation: Vector2 = Vector2(0.9, 1.1)\n@export var avoid_repeat: bool = true\n\nvar _last_played_index: int = -1\n\nfunc play() -> void:\n    if sounds.is_empty():\n        return\n    \n    var index = randi() % sounds.size()\n    \n    if avoid_repeat and sounds.size() > 1:\n        while index == _last_played_index:\n            index = randi() % sounds.size()\n    \n    _last_played_index = index\n    \n    var pitch = randf_range(pitch_variation.x, pitch_variation.y)\n    AudioManager.play_sfx(sounds[index], volume, pitch)\n\nfunc play_at_position(position: Vector3) -> void:\n    if sounds.is_empty():\n        return\n    \n    var index = randi() % sounds.size()\n    if avoid_repeat and sounds.size() > 1:\n        while index == _last_played_index:\n            index = randi() % sounds.size()\n    \n    _last_played_index = index\n    \n    var pitch = randf_range(pitch_variation.x, pitch_variation.y)\n    AudioManager.play_sfx_3d(sounds[index], position, volume, pitch)\n```\n\n---\n\n## 脚步声系统\n\n### footstep_system.gd\n\n```gdscript\n## 脚步声系统\nclass_name FootstepSystem\nextends Node\n\n@export var character: CharacterBody3D\n@export var step_interval: float = 0.5\n@export var run_step_interval: float = 0.3\n\nvar _step_timer: float = 0.0\nvar _surface_detector: RayCast3D\n\n# 表面类型 -> 音效列表\nvar _surface_sounds: Dictionary = {\n    \"default\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fconcrete_01.ogg\"],\n    \"grass\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fgrass_01.ogg\"],\n    \"wood\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fwood_01.ogg\"],\n    \"metal\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fmetal_01.ogg\"],\n    \"water\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Ffootsteps\u002Fwater_01.ogg\"]\n}\n\nfunc _ready() -> void:\n    _setup_surface_detector()\n\nfunc _setup_surface_detector() -> void:\n    _surface_detector = RayCast3D.new()\n    _surface_detector.target_position = Vector3(0, -1, 0)\n    character.add_child(_surface_detector)\n\nfunc _physics_process(delta: float) -> void:\n    if not character.is_on_floor():\n        return\n    \n    var velocity = character.velocity\n    var speed = Vector2(velocity.x, velocity.z).length()\n    \n    if speed \u003C 0.1:\n        return\n    \n    _step_timer += delta\n    var interval = run_step_interval if speed > 5.0 else step_interval\n    \n    if _step_timer >= interval:\n        _step_timer = 0.0\n        _play_footstep()\n\nfunc _play_footstep() -> void:\n    var surface = _detect_surface()\n    var sounds = _surface_sounds.get(surface, _surface_sounds[\"default\"])\n    var sound = sounds[randi() % sounds.size()]\n    \n    AudioManager.play_sfx_pitched(sound, Vector2(0.9, 1.1), 0.7)\n\nfunc _detect_surface() -> String:\n    if _surface_detector.is_colliding():\n        var collider = _surface_detector.get_collider()\n        if collider.has_meta(\"surface_type\"):\n            return collider.get_meta(\"surface_type\")\n    \n    return \"default\"\n```\n\n---\n\n## 配置示例\n\n### audio_config.json\n\n```json\n{\n  \"music\": {\n    \"main_menu\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fmain_menu.ogg\",\n    \"gameplay\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fgameplay.ogg\",\n    \"boss\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fboss.ogg\",\n    \"victory\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fvictory.ogg\",\n    \"game_over\": \"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fgame_over.ogg\"\n  },\n  \"sfx\": {\n    \"ui\": {\n      \"click\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fui\u002Fclick.ogg\",\n      \"hover\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fui\u002Fhover.ogg\",\n      \"confirm\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fui\u002Fconfirm.ogg\",\n      \"cancel\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fui\u002Fcancel.ogg\"\n    },\n    \"player\": {\n      \"jump\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fjump.ogg\",\n      \"land\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fland.ogg\",\n      \"hurt\": \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fhurt.ogg\",\n      \"attack\": [\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fattack_01.ogg\", \"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fplayer\u002Fattack_02.ogg\"]\n    }\n  },\n  \"ambient\": {\n    \"forest\": \"res:\u002F\u002Fassets\u002Faudio\u002Fambient\u002Fforest.ogg\",\n    \"cave\": \"res:\u002F\u002Fassets\u002Faudio\u002Fambient\u002Fcave.ogg\",\n    \"rain\": \"res:\u002F\u002Fassets\u002Faudio\u002Fambient\u002Frain.ogg\"\n  }\n}\n```\n\n---\n\n## 使用示例\n\n```gdscript\n# 播放背景音乐\nAudioManager.play_music(\"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fgameplay.ogg\")\n\n# 带淡入淡出切换音乐\nAudioManager.play_music(\"res:\u002F\u002Fassets\u002Faudio\u002Fmusic\u002Fboss.ogg\", 2.0)\n\n# 播放音效\nAudioManager.play_sfx(\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fexplosion.ogg\")\n\n# 播放带随机音高的音效\nAudioManager.play_sfx_pitched(\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fhit.ogg\")\n\n# 播放 3D 音效\nAudioManager.play_sfx_3d(\"res:\u002F\u002Fassets\u002Faudio\u002Fsfx\u002Fexplosion.ogg\", enemy.global_position)\n\n# 播放语音\nAudioManager.play_voice(\"res:\u002F\u002Fassets\u002Faudio\u002Fvoice\u002Fgreeting.ogg\", func():\n    print(\"Voice finished\")\n)\n\n# 调整音量\nAudioManager.set_music_volume(0.5)\nAudioManager.set_sfx_volume(0.8)\n```\n",{"name":5,"inputs":45,"outputs":50,"version":54,"triggers":55,"description":58,"dependencies":59},[46],{"enum":47,"name":48,"type":49,"required":41},[36,27,37,30],"audio_type","string",[51],{"name":52,"type":39,"path_pattern":53},"audio_manager","res:\u002F\u002Fscripts\u002Fautoload\u002Faudio_manager.gd","1.0.0",[56],{"pattern":57},"音频|音乐|音效|BGM|SFX|AudioManager","音频系统技能。管理游戏音频播放，包括背景音乐、音效、语音等。 支持音频池、淡入淡出、3D 音效等功能。\n",[60],"godot-core","main","18d0e63d1313ca87098f614aa7c1e2dcf6de79c7","backend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Fgodot-mcp\u002Fskills\u002Fgodot-dev\u002Flevel-2-modules\u002Faudio-system",1,"https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system","https:\u002F\u002Fgithub.com\u002Fwelflau","2026-11-12 14:55:20",{"source":8,"skillName":5,"commands":69,"prompt":79,"zipAvailable":80},[70,73,76],{"tool":71,"command":72},"npx","npx skills add welflau\u002Fai-dev-system --skill audio-system",{"tool":74,"command":75},"bunx","bunx skills add welflau\u002Fai-dev-system --skill audio-system",{"tool":77,"command":78},"pnpm","pnpm dlx skills add welflau\u002Fai-dev-system --skill audio-system","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Fgodot-mcp\u002Fskills\u002Fgodot-dev\u002Flevel-2-modules\u002Faudio-system\u002FSKILL.md",true,[],[83,115,147,172,198,222],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":87,"licenseFileUrl":88,"sourceHtmlUrl":89,"categories":90,"keywords":94,"publishedAt":40},"01M6HSTDP4M3JFXEBK91VFB4PA","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Fweb-artifacts-builder\u002FSKILL.md",[91],{"categoryNo":92,"categoryName":93,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",[95,96,97,98,99,100,101,102,103,104,105,106,39,107,108,109,110,111,112,113,114],"web artifacts builder","web","artifacts","artifacts builder","builder","frontend","css","components","react","routing","state management","state","Tailwind","use","single-file","simple","ui components","multi","for","single",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":87,"licenseFileUrl":119,"sourceHtmlUrl":120,"categories":121,"keywords":131,"publishedAt":40},"01M6HSDXH0JSP8R3QTNY9XZ8HN","frontend-design","Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML\u002FCSS layouts, or when styling\u002Fbeautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Ffrontend-design\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Ffrontend-design\u002FSKILL.md",[122,123,126],{"categoryNo":92,"categoryName":93,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":124,"categoryName":125,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":127,"categoryName":128,"taxonomyType":129,"taxonomyTypeDesc":130},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[100,132,133,101,96,102,103,134,135,136,97,137,138,139,108,140,141,142,143,144,145,146],"design","frontend design","react components","create","code","examples","applications","landing","ui design","pages","aesthetics","web ui","with","generic","when",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":87,"licenseFileUrl":151,"sourceHtmlUrl":152,"categories":153,"keywords":155,"publishedAt":40},"01M6HSA77QYVP7A72HREGTDN2C","algorithmic-art","Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Falgorithmic-art\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fplugins\u002Falgorithmic-art\u002FSKILL.md",[154],{"categoryNo":124,"categoryName":125,"taxonomyType":20,"taxonomyTypeDesc":21},[156,157,158,135,136,159,160,161,162,108,163,164,165,166,144,167,168,169,170,171,146],"algorithmic art","Art","algorithmic","flow","js","work","interactive","generative art","exploration","systems","users","Existing","request","generative","copyright","fields",{"skillNo":173,"name":174,"nameZh":6,"description":175,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":87,"licenseFileUrl":176,"sourceHtmlUrl":177,"categories":178,"keywords":180,"publishedAt":40},"01M6HS9HE0X390Y6RQKTY1YNGJ","theme-factory","Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors\u002Ffonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fexternal_plugins\u002Ftheme-factory\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fexternal_plugins\u002Ftheme-factory\u002FSKILL.md",[179],{"categoryNo":124,"categoryName":125,"taxonomyType":20,"taxonomyTypeDesc":21},[181,182,183,184,185,186,97,187,188,189,139,190,191,141,192,144,193,194,195,113,196,197],"theme factory","factory","theme","docs","toolkit","generate","SET","fly","slides","styling","artifact","themes","you","fonts","can","apply","new",{"skillNo":199,"name":200,"nameZh":6,"description":201,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":202,"categories":203,"keywords":207,"publishedAt":40},"01M6HS74GASM6FJ77F83EY679E","browsing","Use when you need direct browser control - teaches Chrome DevTools Protocol for controlling existing browser sessions, multi-tab management, form automation, and content extraction via use_browser MCP tool","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fexternal_plugins\u002Fsuperpowers-chrome\u002Fskills\u002Fbrowsing\u002FSKILL.md",[204],{"categoryNo":205,"categoryName":206,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[200,208,209,210,211,212,213,214,215,216,217,108,218,219,220,221,112,193,113,167],"MCP","automation","chrome","sessions","protocol","browser","devtools","chrome devtools","tool","direct","browser control","control","via","form",{"skillNo":223,"name":224,"nameZh":6,"description":225,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":87,"licenseFileUrl":226,"sourceHtmlUrl":227,"categories":228,"keywords":233,"publishedAt":40},"01M6HS6BZT2CKDNQ6YF20DXN4T","slack-gif-creator","Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\"","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fexternal_plugins\u002Fslack-gif-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fwelflau\u002Fai-dev-system\u002Fblob\u002Fmain\u002Fbackend\u002Fskills\u002Fmarketplace\u002Fcodebuddy-plugins-official\u002Fexternal_plugins\u002Fslack-gif-creator\u002FSKILL.md",[229,232],{"categoryNo":230,"categoryName":231,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000005","邮件与沟通",{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[234,235,236,237,238,239,240,241,242,108,243,166,244,245,246,113,168,146],"slack gif creator","slack","gif","creator","validation","Tools","constraints","Animation","knowledge","me","make","Utilities","concepts"]