说在前面的话

1.矢量动画

矢量动画是一种通过计算机图形学中矢量图形技术来生成和渲染动态影像的方法。其核心在于使用数学公式(而非像素阵列)来定义动画中的所有视觉元素,并通过随时间连续计算和重绘这些公式来创造运动幻觉。在H5小游戏开发中扮演着至关重要的角色。

本章工程源代码:H5下游戏矢量动画管理框架资源-CSDN下载

2.与位图动画的根本区别

特性 ​矢量动画​ ​位图动画(帧动画/精灵动画)​​
​构成基础​ 数学公式(点、线、曲线、方程) 像素阵列(栅格图像)
​存储方式​ 指令集和参数(代码、JSON、XML),数据量小 每个像素的颜色信息(RGB等),数据量大
​缩放表现​ ​无限缩放而不失真​(分辨率无关) 放大后会出现像素化和模糊
​动画原理​ 计算属性的连续插值变化 快速切换一系列静态图片(帧)
​文件体积​ 通常非常小,与复杂度和时长有关 通常很大,与分辨率、帧数、颜色深度直接相关
​修改性​ ​极高。可动态修改任何属性(如通过代码改变颜色) ​极低。修改需重新编辑像素,难以程序化控制

3.技术实现与格式

在专业工作流中,矢量动画通常通过以下方式实现:

  • 格式/标准:

    • SVG(Scalable Vector Graphics):基于XML的开放标准,可直接嵌入HTML,并可通过CSS和JavaScript进行动画控制。

    • Lottie:由Airbnb开发的一种JSON格式的矢量动画数据交换标准。设计师在After Effects中制作动画,通过Bodymovin插件导出为.json文件,开发者可直接在多种平台(Web, iOS, Android)上渲染播放,极大地提升了设计与开发的协作效率。

  • API/技术:

    • Canvas API:通过JavaScript动态指令在画布上绘制矢量图形并制作动画。

    • WebGL:虽然更常用于3D,但也可用于高性能的2D矢量渲染。

一、Windsurf助力实现矢量动画播放框架

提示词:创建一套基于Phaser的矢量动画角色控制框架,通过不断补充角色库基于角色编号实例化角色,通过动画名称播放动画。

Windsurf经过短暂的5s思考,给出了解决方案。

1.工程目录结构

  • 核心文件:

    • index.html:加载 Phaser 与入口模块。

    • src/main.js:创建游戏实例。

    • src/scenes/DemoScene.js:演示场景,注册并创建角色,支持按动画名播放。

    • src/actors/ActorBase.js:角色基类,封装 play/stop/stopAll

    • src/actors/AnimationController.js:动画控制器,按动画名注册与播放。

    • src/actors/ActorRegistry.js:角色注册表(编号 → 构造器)。

    • src/actors/ActorFactory.js:角色工厂(通过编号实例化)。

    • src/actors/examples/VectorStickMan.js:示例矢量角色(idle/wave/walk)。

    • README.md:使用说明。

2.各文件的主要作用

  • index.html用于引入phaser3.9,并且引入main.js。

  • main.js文件作为应用入口,负责创建 Phaser 游戏实例并加载场景列表。场景仅在这里进行集中声明,便于统一管理与按需裁剪。

  • DemoScene.js该文件用于演示场景,注册、生成、销毁 Actor角色,绑定键盘与点击交互,UI。

  • ActorBase.js作为可视容器是矢量角色基类,提供统一的构建/动画注册与播放接口。

  • ActorRegistry.js的作用是全局静态注册表,维护“角色编号 → 构造器/元信息”的映射。

  • AnimationController.js管理按名称注册与播放的动画;保证矢量动画角色同一时刻仅有一个激活动画。

  • ActorFactory.js根据编号从 `ActorRegistry` 取得构造器,创建 Actor 实例并注入 `AnimationController`。

  • examples目录中维护了所有的矢量动画Actor。

    • VectorStickMan.js定义了一个简单的火柴人矢量角色;

    • VectorCar.js定义了一个简单的侧视小汽车矢量角色。

3.核心 API

  • ActorRegistry.register(id, Ctor, meta?)注册角色。

  • ActorFactory.create(scene, id, x, y, config?)创建角色实例。config 可包含 scale 等参数。

  • ActorBase.play(name, opts?)播放动画。opts 支持 { loop, onComplete }

4.扩展新角色

  • 新建文件:src/actors/examples/MyVectorActor.js,继承 ActorBase
  • build() 中用

    • Graphics/Container 搭建矢量部件;

    • createAnimations() 中使用 this.animations.add(name, playFn) 注册动画。

      • playFn({ loop, onComplete }) 需要返回一个 stop() 函数,用于停止动画(清理 tweens/timeline)。

  • 在使用前注册编号:

// 某处(如 DemoScene.create)
import MyVectorActor from '../actors/examples/MyVectorActor.js';
import { ActorRegistry } from '../actors/ActorRegistry.js';
ActorRegistry.register(2001, MyVectorActor, { name: 'MyActor' });
  • 用工厂创建并播放动画:
import { ActorFactory } from '../actors/ActorFactory.js';
const actor = ActorFactory.create(this, 2001, 400, 300, { scale: 1 });
actor.play('idle');

5.详细设计说明

  • 架构概览

    • ActorRegistry:注册编号 → 构造器/元信息。

    • ActorFactory:按编号创建 Actor,注入 AnimationController 并建立回引用。

    • ActorBase:矢量角色基类,定义 build()createAnimations() 扩展点,封装 play/stop/stopAll

    • AnimationController:以“单活策略”管理动画名到播放函数的映射与切换。

    • 示例角色(examples/):按约定注册动画,返回 stop() 完成资源清理。

  • 架构关系图

  • 动画设计与清理契约

    • 动画注册:this.animations.add(name, playFn)

    • 播放函数:playFn({ loop, onComplete }) => stopFn

    • 清理要求:stopFn 必须移除 Tweens/Timeline/事件监听/计时器,保证切换动画或销毁时无泄漏。

  • 场景与 UI

    • DemoScene 提供演示外壳:

      • 下拉选择不同样例;

      • 按键 1/2/3 触发当前角色的不同动画;

      • 动态帮助文案:随样例切换,展示仅与当前样例相关的动作提示。

  • 简化多分辨率问题

    • 以代码画矢量(Graphics)更易参数化和动态生成,但相对位图更耗 CPU;

    • 统一使用 Phaser.Scale.FIT 适配,简化多分辨率问题。

6.示例

6.1火柴人

  • 火柴人(VectorStickMan)层级结构

  • 动画演示

6.2小汽车

  • 小汽车(VectorCar)组成

  • 动画演示

6.3剑侠

  • VectorSwordsman(层级结构)
    • 层级(从父到子):

      • root(本体)

      • torso(躯干,决定整体朝向与轻微起伏)

      • shoulder(肩枢纽,手臂与披风的共同旋转基点)

      • rightArmsword

      • leftArm

      • hip(可与 torso 合并)→ leftLeg / rightLeg

      • cape(受肩部与躯干运动带动,末端附加延迟/摆动)

      • shadow(仅作地面投影,跟随本体 X/Y)

    • 锚点/局部坐标:

      • shoulder 放置在躯干上缘偏右位置,作为右臂与披风的主要旋转中心;

      • rightArm 的 pivot 位于肩点,sword 的 pivot 位于握把处;

      • cape 起点在肩背后,末端若拆成两段,可分别在段尾做轻微角度延迟,营造拖拽感;

      • 腿部 leftLeg/rightLeg 的 pivot 位于髋部,便于步态对摆。

  • 主要动作实现算法说明
    • idle(待机呼吸 + 披风轻摆 + 右臂/剑轻颤):

      • 躯干:y[-2, +2] 范围内往返;或 scaleY[0.98, 1.02] 之间缓慢呼吸;

      • 披风:以肩点为基,根段角度在 [-6°, -2°],末段相对根段附加 [-3°, +3°] 的缓慢相位延迟;

      • 右臂:在 [-8°, +8°] 内小幅来回;

      • 剑:相对右臂增加 [-4°, +4°] 的细微抖动(不同相位和更快的 duration);

      • 建议缓动:Sine.inOutSine.yoyoduration 1.2~2.0s。

    • move(移动步态,对摆 + 轻微起伏):

      • 躯干:y 以 0.6~0.8s 周期作 ±3~5px 起伏;

      • 腿部:leftLeg.rotation = A*sin(t)rightLeg.rotation = -A*sin(t),A≈18°;

      • 手臂:与腿部相反相位,A≈12°,右臂略小以保持持剑稳定;

      • 披风:在 shoulder.rotation 基础上叠加较小幅度延迟;

      • 场景移动:不强制水平位移,由 DemoScene 的点击位移统一控制。

    • attack(普攻斩击:提剑→下劈,带短斩光):

      • 预备(0.12~0.18s):torso 轻后仰(-4°),rightArm 抬起至约 -70°sword 反向预摆 +10°;

      • 发力(0.10~0.16s):rightArm-70° 快速到 +40°sword 叠加 +20~+30°,缓动 Expo.out

      • 收势(0.12~0.20s):逐步回到 idle 范围;

      • 斩光:在手部/剑刃局部坐标生成一段弧形 Graphics,沿劈砍方向做 alpha 衰减与 scaleX 拉伸,结束 destroy()

      • 命中判定(可选):在发力中段开放 80~120ms 的判定窗口(不在本示例中实现逻辑,仅说明)。

    • skill(旋斩:本体快速旋转一圈 + 大斩光):

      • 躯干/本体整体:root.rotation 在 0.35~0.5s 内旋转 360°(或分两段 2x180°),缓动 Cubic.out

      • 剑轨:在旋转过程中以固定时间间隔(每 30~40ms)采样当前 sword 端点,生成半透明“残影片段”(短线段或三角扇形),alpha 递减并延迟销毁;

      • 披风:在旋转期间增加外摆延迟(末段角度振幅 +30%);

      • 结束:统一 stop() 本技能内部 tween,清理所有临时 Graphics

    • hurt(受击:后仰 + 闪烁):

      • 躯干:rotation 向后 -8°y 上抬 4px,0.08~0.12s;

      • 回弹:0.10~0.16s 回到 idle 范围;

      • 闪烁:对 root.alpha 做两次 0.1s 的 0.5 ↔ 1 切换;

      • 可选:添加极短的水平位移模拟后退感,结束归位。

  • 动画演示

6.4法师

  • VectorSorcerer(层级结构)
    • 层级(从父到子):

      • root(本体)

      • torso(躯干,决定整体朝向与漂浮效果)

      • shoulder(肩枢纽,手臂与长袍的共同旋转基点)

      • rightArmstaff(法杖)

      • leftArm

      • hip(可与 torso 合并)→ leftLeg / rightLeg

      • robe(长袍,受躯干运动带动,下摆有摆动效果)

      • shadow(仅作地面投影,跟随本体 X/Y)

    • 锚点/局部坐标:

      • shoulder 放置在躯干上缘位置,作为手臂与长袍的旋转中心;

      • rightArm 的 pivot 位于肩点,staff 的 pivot 位于握把处,宝珠在法杖顶端;

      • robe 起点在肩部,下摆使用 2~3 段骨线实现飘逸效果;

      • 腿部 leftLeg/rightLeg 的 pivot 位于髋部,便于步态对摆。

  • 主要动作实现算法说明
    • idle(漂浮 + 长袍摆动 + 宝珠闪烁):

      • 躯干:y[-3, +3] 范围内缓慢上下浮动,缓动 Sine.inOut,周期 2.5s;

      • 长袍:以肩点为基,下摆段角度在 [-5°, +5°] 间缓慢摆动,相位延迟 0.3s;

      • 法杖:随右臂轻微晃动,rotation[-2°, +2°] 内;

      • 宝珠:scale[0.95, 1.05] 间脉动,alpha[0.8, 1.0] 间变化,周期不同步;

      • 光晕:使用 fillCircle 绘制,scalealpha 反向变化,营造呼吸感。

    • move(跳步步态 + 肢体对摆):

      • 躯干:y 以 0.5~0.7s 周期作 ±4~6px 起伏,最高点在步态中间;

      • 腿部:leftLeg.rotation = A*sin(ωt)rightLeg.rotation = -A*sin(ωt),A≈15°;

      • 手臂:与腿部相反相位,A≈10°,右臂幅度略小以保持法杖稳定;

      • 长袍:下摆摆动幅度增加 30%,相位延迟 0.2s;

      • 场景移动:水平位移由 DemoScene 的点击控制。

    • attack(施放魔弹):

      • 预备(0.15s):torso 轻微后仰(-5°),rightArm 抬起至约 -45°,法杖指向目标;

      • 施法(0.10s):右手向前推出,rightArm.rotation-45°+15°,缓动 Back.out

      • 生成魔弹:在法杖顶端生成魔弹,带有拖尾粒子效果;

      • 收势(0.20s):手臂缓慢回到待机位置;

      • 魔弹:沿直线飞行,带有拖尾,distance 后自动销毁。

    • skill(法阵冲击波):

      • 起手(0.10s):torso 下蹲(y +10px),双手握杖举过头顶;

      • 施法(0.15s):法杖猛击地面,触发法阵生成;

      • 法阵效果:

        • 内圈:固定大小的法阵,带有符文图案;

        • 外圈:从内向外扩散的冲击波,scale 从 0 到 2,alpha 从 1 到 0;

        • 地面波纹:多个同心圆依次扩散;

      • 收势(0.25s):角色恢复站立姿态;

      • 清理:所有特效在播放完成后自动 destroy

    • hurt(受击反应):

      • 后仰:torso.rotation 向后 -10°y 上抬 5px,0.1s;

      • 闪烁:对 root.alpha 做两次 0.1s 的 0.5 ↔ 1 切换;

      • 恢复:0.2s 内回到 idle 状态。

  • 动画演示

二、说明

本样例中的所有代码均有AI生成,遇到问题,只需要将问题抛给AI让其修复即可。几轮基于修复问题的提示词如下:

  • 创建一套基于Phaser的矢量动画角色控制框架,通过不断补充角色库基于角色编号实例化角色,通过动画名称播放动画。

  • idle动作目前是右手抬起,轻微摆动,应该是双手自然下垂轻微摆动;而wave目前是右手抬起但是没有动作,应该是右手抬起轻微摆动;

  • 1.增加一个小汽车侧视的矢量动画角色,动画包括小汽车向左和向右行使;2. 同时为小汽车矢量动画角色编写同名".md"格式说明文档;3. 在界面中增加选择样例角色的功能,可以在不同的样例角色之间切换,设计时考虑好后续不断增加样例角色的扩展。

  • 界面中的动作提示,根据选择不同的样例而提示不同的内容,而不是多个样例的动作提示一起显示。

  • 为src目录下的所有".js"代码文件编写详细的同名“.md"格式的说明文档。

那么如果想增加新的矢量动画,只需要想好示例效果,让其读取全部工程后,自己生成即可。

 本章工程源代码:H5下游戏矢量动画管理框架资源-CSDN下载

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐