Communitygithub.com

David-Li0406/meta-skill-evloving

Implements animation systems using AnimationPlayer, AnimationTree, blend trees, and procedural animation. Use when creating character animations and visual effects.

meta-skill-evloving 是什么?

meta-skill-evloving is a Claude Code agent skill that implements animation systems using AnimationPlayer, AnimationTree, blend trees, and procedural animation. Use when creating character animations and visual effects.

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/David-Li0406/meta-skill-evloving/tree/HEAD/skill-flow/data/skills-refined-36k/skillsmp/animation-system

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Godot Animation System

When implementing animations, use these patterns for smooth and responsive character movement.

AnimationPlayer Basics

Playing Animations

extends CharacterBody2D

@onready var anim_player: AnimationPlayer = $AnimationPlayer

func _ready() -> void:
    # Connect to animation finished signal
    anim_player.animation_finished.connect(_on_animation_finished)

func play_animation(anim_name: String, speed: float = 1.0) -> void:
    if anim_player.current_animation != anim_name:
        anim_player.play(anim_name)
        anim_player.speed_scale = speed

func play_backwards(anim_name: String) -> void:
    anim_player.play_backwards(anim_name)

func stop_animation() -> void:
    anim_player.stop()

func pause_animation() -> void:
    anim_player.pause()

func resume_animation() -> void:
    anim_player.play()

func _on_animation_finished(anim_name: String) -> void:
    match anim_name:
        "attack":
            play_animation("idle")
        "death":
            queue_free()

Animation Blending

extends AnimationPlayer

func crossfade_to(anim_name: String, duration: float = 0.2) -> void:
    if current_animation == anim_name:
        return

    # Queue the new animation with crossfade
    queue(anim_name)
    advance(0)  # Start immediately

    # Use AnimationPlayer's built-in blending
    set_blend_time(current_animation, anim_name, duration)

# Manual crossfade using AnimationTree is preferred for complex blending

Animation Callbacks

extends CharacterBody2D

@onready var anim_player: AnimationPlayer = $AnimationPlayer

func _ready() -> void:
    # Add method track call in animation
    # Or use animation_finished signal

    pass

# Called from animation track
func spawn_projectile() -> void:
    var projectile := preload("res://projectile.tscn").instantiate()
    projectile.global_position = $ProjectileSpawn.global_position
    get_parent().add_child(projectile)

func play_sound(sound_name: String) -> void:
    var sound := $Sounds.get_node(sound_name) as AudioStreamPlayer2D
    if sound:
        sound.play()

func enable_hitbox() -> void:
    $Hitbox/CollisionShape2D.disabled = false

func disable_hitbox() -> void:
    $Hitbox/CollisionShape2D.disabled = true

AnimationTree

State Machine Setup

extends CharacterBody2D

@onready var anim_tree: AnimationTree = $AnimationTree
@onready var state_machine: AnimationNodeStateMachinePlayback = \
    anim_tree.get("parameters/playback")

func _ready() -> void:
    anim_tree.active = true

func travel_to_state(state_name: String) -> void:
    state_machine.travel(state_name)

func force_state(state_name: String) -> void:
    state_machine.start(state_name)

func get_current_state() -> String:
    return state_machine.get_current_node()

func is_playing(state_name: String) -> bool:
    return state_machine.get_current_node() == state_name

func _physics_process(_delta: float) -> void:
    update_animation_state()

func update_animation_state() -> void:
    if not is_on_floor():
        if velocity.y < 0:
            travel_to_state("Jump")
        else:
            travel_to_state("Fall")
    elif velocity.length() > 10:
        travel_to_state("Run")
    else:
        travel_to_state("Idle")

Blend Tree Setup

extends CharacterBody2D

@onready var anim_tree: AnimationTree = $AnimationTree

func _physics_process(_delta: float) -> void:
    update_blend_parameters()

func update_blend_parameters() -> void:
    # For BlendSpace2D (8-directional movement)
    var input := Input.get_vector("left", "right", "up", "down")
    anim_tree.set("parameters/Move/blend_position", input)

    # For BlendSpace1D (speed-based)
    var speed_ratio := velocity.length() / max_speed
    anim_tree.set("parameters/Speed/blend_position", speed_ratio)

    # For animation transitions
    anim_tree.set("parameters/conditions/is_jumping", not is_on_floor() and velocity.y < 0)
    anim_tree.set("parameters/conditions/is_falling", not is_on_floor() and velocity.y > 0)
    anim_tree.set("parameters/conditions/is_grounded", is_on_floor())

One-Shot Animations

extends CharacterBody2D

@onready var anim_tree: AnimationTree = $AnimationTree

func play_attack() -> void:
    # Trigger one-shot animation
    anim_tree.set("parameters/Attack/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)

func abort_attack() -> void:
    anim_tree.set("parameters/Attack/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_ABORT)

func is_attacking() -> bool:
    return anim_tree.get("parameters/Attack/active")

func _on_attack_finished() -> void:
    # Called when one-shot completes
    pass

Layered Animations

# AnimationTree structure:
# - AnimationNodeBlendTree
#   - Add2 (blend lower and upper body)
#     - Input 0: State Machine (lower body: idle, walk, run)
#     - Input 1: State Machine (upper body: idle, aim, shoot)
#     - Filter: Upper body bones only

extends CharacterBody2D

@onready var anim_tree: AnimationTree = $AnimationTree

func _ready() -> void:
    # Set up bone filter for upper body layer
    # This is usually done in editor, but can be done in code
    pass

func update_animations() -> void:
    # Lower body follows movement
    var move_state := "idle" if velocity.length() < 10 else "run"
    anim_tree.set("parameters/LowerBody/playback").travel(move_state)

    # Upper body independent
    if is_aiming:
        anim_tree.set("parameters/UpperBody/playback").travel("aim")
    elif is_shooting:
        anim_tree.set("parameters/UpperBody/playback").travel("shoot")
    else:
        anim_tree.set("parameters/UpperBody/playback").travel("idle")

    # Blend amount
    anim_tree.set("parameters/Add2/add_amount", 1.0 if is_aiming else 0.0)

Procedural Animation

Look At / Head Tracking

extends Node3D

@export var head_bone: String = "Head"
@export var max_angle := 70.0
@export var look_speed := 5.0

var skeleton: Skeleton3D
var head_bone_idx: int
var target: Node3D

func _ready() -> void:
    skeleton = $Skeleton3D
    head_bone_idx = skeleton.find_bone(head_bone)

func _process(delta: float) -> void:
    if not target or head_bone_idx < 0:
        return

    var head_transform := skeleton.get_bone_global_pose(head_bone_idx)
    var head_position := skeleton.to_global(head_transform.origin)

    var target_direction := (target.global_position - head_position).normalized()
    var local_direction := skeleton.global_transform.basis.inverse() * target_direction

    # Calculate rotation to look at target
    var target_rotation := Quaternion(Vector3.FORWARD, local_direction)

    # Clamp rotation
    var angle := target_rotation.get_euler()
    angle.x = clamp(angle.x, deg_to_rad(-max_angle), deg_to_rad(max_angle))
    angle.y = clamp(angle.y, deg_to_rad(-max_angle), deg_to_rad(max_angle))

    var clamped_rotation := Quaternion.from_euler(angle)

    # Apply smooth rotation
    var current := skeleton.get_bone_pose_rotation(head_bone_idx)
    var new_rotation := current.slerp(clamped_rotation, look_speed * delta)

    skeleton.set_bone_pose_rotation(head_bone_idx, new_rotation)

Procedural Walk Cycle

extends CharacterBody2D

@export var leg_length := 20.0
@export var step_height := 10.0
@export var step_duration := 0.3

@onready var left_foot: Node2D = $LeftFoot
@onready var right_foot: Node2D = $RightFoot

var left_foot_target: Vector2
var right_foot_target: Vector2
var step_progress := 0.0
var is_left_stepping := true

func _physics_process(delta: float) -> void:
    if velocity.length() > 10:
        update_procedural_walk(delta)
    else:
        reset_feet()

func update_procedural_walk(delta: float) -> void:
    step_progress += delta / step_duration

    if step_progress >= 1.0:
        step_progress = 0.0
        is_left_stepping = not is_left_stepping
        calculate_next_step()

    # Interpolate foot positions
    var stepping_foot := left_foot if is_left_stepping else right_foot
    var grounded_foot := right_foot if is_left_stepping else left_foot
    var target := left_foot_target if is_left_stepping else right_foot_target

    # Arc motion for stepping foot
    var t := step_progress
    var horizontal := stepping_foot.position.lerp(target, t)
    var vertical_offset := sin(t * PI) * step_height

    stepping_foot.position = horizontal + Vector2(0, -vertical_offset)

func calculate_next_step() -> void:
    var forward := velocity.normalized()
    var step_distance := velocity.length() * step_duration

    if is_left_stepping:
        left_foot_target = left_foot.position + forward * step_distance
    else:
        right_foot_target = right_foot.position + forward * step_distance

Squash and Stretch

extends Sprite2D

@export var squash_amount := 0.3
@export var stretch_amount := 0.2
@export var return_speed := 10.0

var target_scale := Vector2.ONE

func squash() -> void:
    target_scale = Vector2(1 + squash_amount, 1 - squash_amount)

func stretch() -> void:
    target_scale = Vector2(1 - stretch_amount, 1 + stretch_amount)

func _process(delta: float) -> void:
    scale = scale.lerp(target_scale, return_speed * delta)
    target_scale = target_scale.lerp(Vector2.ONE, return_speed * delta)

# Usage with physics
extends CharacterBody2D

func _physics_process(delta: float) -> void:
    var was_on_floor := is_on_floor()
    move_and_slide()

    # Landing squash
    if is_on_floor() and not was_on_floor:
        $Sprite2D.squash()

    # Jumping stretch
    if Input.is_action_just_pressed("jump") and is_on_floor():
        $Sprite2D.stretch()

Screen Shake

extends Camera2D

var shake_amount := 0.0
var shake_decay := 5.0

func shake(amount: float, duration: float = 0.2) -> void:
    shake_amount = amount
    var tween := create_tween()
    tween.tween_property(self, "shake_amount", 0.0, duration)

func _process(delta: float) -> void:
    if shake_amount > 0:
        offset = Vector2(
            randf_range(-shake_amount, shake_amount),
            randf_range(-shake_amount, shake_amount)
        )
    else:
        offset = Vector2.ZERO

Sprite Animation

AnimatedSprite2D Controller

extends CharacterBody2D

@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D

func _physics_process(_delta: float) -> void:
    update_animation()
    update_facing()

func update_animation() -> void:
    if not is_on_floor():
        if velocity.y < 0:
            sprite.play("jump")
        else:
            sprite.play("fall")
    elif abs(velocity.x) > 10:
        sprite.play("run")
    else:
        sprite.play("idle")

func update_facing() -> void:
    if velocity.x > 0:
        sprite.flip_h = false
    elif velocity.x < 0:
        sprite.flip_h = true

func play_attack() -> void:
    sprite.play("attack")
    await sprite.animation_finished
    # Return to idle or movement animation

Frame-Based Events

extends AnimatedSprite2D

signal attack_frame
signal step_frame

func _ready() -> void:
    frame_changed.connect(_on_frame_changed)

func _on_frame_changed() -> void:
    var current_anim := animation

    match current_anim:
        "attack":
            if frame == 3:  # Attack connects on frame 3
                attack_frame.emit()
        "run":
            if frame == 2 or frame == 6:  # Footstep frames
                step_frame.emit()

Animation Tips

Animation Speed Based on Movement

extends CharacterBody2D

@onready var anim_player: AnimationPlayer = $AnimationPlayer

@export var walk_speed := 100.0
@export var run_speed := 200.0

func _physics_process(_delta: float) -> void:
    var speed := velocity.length()

    if speed > 10:
        # Scale animation speed with movement speed
        var anim_speed := speed / walk_speed
        anim_player.speed_scale = clamp(anim_speed, 0.5, 2.0)
        anim_player.play("walk")
    else:
        anim_player.speed_scale = 1.0
        anim_player.play("idle")

Root Motion

extends CharacterBody2D

@onready var anim_tree: AnimationTree = $AnimationTree

var root_motion_position := Vector2.ZERO

func _physics_process(delta: float) -> void:
    # Get root motion from animation
    var root_motion := anim_tree.get_root_motion_position()

    # Apply root motion as velocity
    if root_motion.length() > 0:
        velocity = Vector2(root_motion.x, root_motion.z) / delta
    else:
        # Normal movement when no root motion
        apply_movement_input()

    move_and_slide()

Animation Retargeting

# When sharing animations between different skeletons
extends Skeleton3D

@export var source_skeleton: Skeleton3D
@export var bone_mapping: Dictionary  # {source_bone: target_bone}

func _process(_delta: float) -> void:
    if not source_skeleton:
        return

    for source_bone in bone_mapping:
        var target_bone: String = bone_mapping[source_bone]

        var source_idx := source_skeleton.find_bone(source_bone)
        var target_idx := find_bone(target_bone)

        if source_idx >= 0 and target_idx >= 0:
            var pose := source_skeleton.get_bone_pose(source_idx)
            set_bone_pose_rotation(target_idx, pose.basis.get_rotation_quaternion())

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

David-Li0406/meta-skill-evloving

Browser automation with persistent page state. Use when users ask to navigate websites, fill forms, take screenshots, extract web data, test web apps, or automate browser workflows. Trigger phrases include "go to [url]", "click on", "fill out the form", "take a screenshot", "scrape", "automate", "test the website", "log into", or any browser interaction request.

David-Li0406/meta-skill-evloving

Create technical diagrams using Mermaid syntax for architecture, sequences, ERDs, flowcharts, and state machines. Use for visualizing system design, data flows, and processes. Triggers: diagram, mermaid, architecture diagram, sequence diagram, flowchart, ERD, entity relationship, state diagram, C4 model, component diagram, visualize, draw.

David-Li0406/meta-skill-evloving

Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks

David-Li0406/meta-skill-evloving

Complete color manipulation and green screen effects system. PROACTIVELY activate for: (1) Green screen/chromakey removal, (2) Color grading with LUTs, (3) Color correction (levels, curves, white balance), (4) Colorkey/color removal effects, (5) Hue/saturation manipulation, (6) Color space conversions (BT.709, BT.2020, HDR), (7) Color isolation effects, (8) Teal and orange look, (9) Vintage/film looks, (10) Color keying for transparency. Provides: chromakey and colorkey filters, LUT application (lut3d), curves and levels adjustment, color balance, selective color manipulation, color space handling, HDR tone mapping, professional color grading chains.

David-Li0406/meta-skill-evloving

Convert files and office documents to Markdown. Supports PDF, DOCX, PPTX, XLSX, images (with OCR), audio (with transcription), HTML, CSV, JSON, XML, ZIP, YouTube URLs, EPubs and more.

David-Li0406/meta-skill-evloving

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

David-Li0406/meta-skill-evloving

Build with OpenAI's stateless APIs - Chat Completions (GPT-5, GPT-4o), Embeddings, Images (DALL-E 3), Audio (Whisper + TTS), and Moderation. Includes Node.js SDK and fetch-based approaches for Cloudflare Workers. Use when: implementing chat completions with GPT-5/GPT-4o, streaming responses with SSE, using function calling/tools, creating structured outputs with JSON schemas, generating embeddings for RAG (text-embedding-3-small/large), generating images with DALL-E 3, editing images with GPT-Image-1, transcribing audio with Whisper, synthesizing speech with TTS (11 voices), moderating content (11 safety categories), or troubleshooting rate limits (429), invalid API keys (401), function calling failures, streaming parse errors, embeddings dimension mismatches, or token limit exceeded.

David-Li0406/meta-skill-evloving

Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.

David-Li0406/meta-skill-evloving

Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks

David-Li0406/meta-skill-evloving

Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas

David-Li0406/meta-skill-evloving

Download YouTube videos with customizable quality and format options. Use this skill when the user asks to download, save, or grab YouTube videos. Supports various quality settings (best, 1080p, 720p, 480p, 360p), multiple formats (mp4, webm, mkv), and audio-only downloads as MP3.

David-Li0406/meta-skill-evloving

Best practices for Remotion - Video creation in React

David-Li0406/meta-skill-evloving

Provides bidirectional translation (Chinese/English), grammar checking, and sentence polishing. Supports specific tense constraints, context-aware tone adjustment, and natural expression optimization. Outputs direct text without formatting.

David-Li0406/meta-skill-evloving

指导如何通过自定义注解(如@Unicom)标识Dubbo接口,利用BeanDefinitionRegistryPostProcessor在启动时扫描并动态注册ReferenceBean,实现RPC调用的封装。

David-Li0406/meta-skill-evloving

生成Python脚本,利用FFmpeg将图片序列按3x3布局合并,或将合并图拆分。要求使用subprocess模块执行命令,并支持用户交互式输入路径。

David-Li0406/meta-skill-evloving

SOP for extracting and analyzing promotional activity details, handling time formatting, location mapping, payment logic, and step-by-step process validation.

David-Li0406/meta-skill-evloving

Specializes in creating TikTok short video scripts using an anthropomorphic 'Chef' perspective to explain wildlife food chains and survival environments, utilizing real field footage.

David-Li0406/meta-skill-evloving

针对TikTok平台,以拟人化视角(如动物作为厨师)创作系列短视频脚本。重点介绍野生动物、食物链及生态环境,要求使用野外实拍素材,风格幽默且具有教育意义。

David-Li0406/meta-skill-evloving

Generates KWL (Know, Want to know, Learned) charts for educational videos, specifically BrainPOP, using simple 7th-grade language and short, concise bullet points.

David-Li0406/meta-skill-evloving

Tracks complex, multi-session work using the Beads issue tracker and dependency graphs, and provides persistent memory that survives conversation compaction. Use when work spans multiple sessions, has complex dependencies, or needs persistent context across compaction cycles. Trigger with phrases like "create task for", "what's ready to work on", "show task", "track this work", "what's blocking", or "update status".

相关技能