Shader 特效系统

版本 v0.5.6 | 2026-01-29

一、技术演进路径

早期方案:组合方案(已归档)

Player
├── AnimatedSprite2D + ShaderMaterial    ← Shader层(描边+色差)
├── AuraEffect (Node2D)                  ← 绘制层(火焰)
└── GPUParticles2D                       ← 粒子层

局限:Shader 只能在精灵纹理范围内绘制,描边/火焰会被裁切。

当前方案:SubViewport 系统

核心突破:创建比角色大的虚拟画布,让特效"冲出"角色边界

Player (CharacterBody2D)
├── CharacterEffectSystem (Node2D)
│   ├── SubViewportContainer (288×288)  ← Shader 应用在此!
│   │   └── SubViewport (透明背景)
│   │       └── EffectSprite (角色精灵副本)
│   └── EnergyParticles (GPUParticles2D)
└── AnimatedSprite2D (原始精灵,效果激活时隐藏)

二、SSJ 阶段升级系统

阶段 触发方式 视觉效果
0 (基础) 按攻击键 金黄色描边 + 基础火焰
1 预输入连击 + 橙色外圈火焰(随机边缘)
2 再次预输入 + 橙红色外圈火焰
3 (最高) 再次预输入 + 鲜红色外圈火焰(延伸至刀尖前方)

阶段衰减:攻击结束后 1.5 秒无操作,阶段逐级降低


三、Shader 技术细节

ssj_viewport.gdshader 参数

参数 类型 默认值 说明
intensity float 0.0 效果强度 (0-1)
ssj_stage float 0.0 当前阶段 (0-3)
glow_color_inner vec3 金黄 内层发光颜色
base_outline_width float 5.0 基础描边宽度
flame_speed float 6.0 火焰动画速度
pulse_speed float 4.0 脉冲速度

火焰随机边缘算法

// 噪声函数产生火焰般的随机边缘
float flame_noise(vec2 uv, float time, float scale) {
    float n1 = sin(uv.x * scale + time * 2.0) * 0.5 + 0.5;
    float n2 = sin(uv.y * scale * 0.7 - time * 1.5) * 0.5 + 0.5;
    float n3 = sin((uv.x + uv.y) * scale * 0.5 + time * 2.5) * 0.5 + 0.5;
    return (n1 * 0.4 + n2 * 0.3 + n3 * 0.3);
}

四、使用方法

# 开启 SSJ 效果
character_effect_system.start_ssj()

# 升级阶段(预输入时调用)
character_effect_system.upgrade_ssj_stage()

# 关闭效果
character_effect_system.stop_ssj()

# 获取当前阶段
var stage = character_effect_system.get_ssj_stage()

# 桑德维斯坦(始终使用旧方案)
shader_controller.start_sandevistan()
shader_controller.stop_sandevistan()

五、文件索引

核心文件(SubViewport 方案)

文件 说明
character_effect_system.gd SubViewport 特效系统核心
ssj_viewport.gdshader SSJ 效果 Shader(带阶段)
CharacterEffectSystem.tscn 可复用场景

仍在使用的旧文件

文件 说明
shader_controller.gd 桑德维斯坦控制器
afterimage_system.gd 残影系统
sandevistan.gdshader 桑德维斯坦 Shader

六、技术总结

解决的问题

  1. 边界限制 → SubViewport 提供 288×288 画布,火焰可延伸 60+ 像素
  2. 效果单调 → 阶段系统让连击有视觉反馈
  3. 火焰死板 → 噪声函数产生自然的"冲破"感
  4. 粒子割裂 → 小而精的火星与火焰融为一体