ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

huashu-art-motion 长卷穿越片:一个骨架加按段并行,让主角从左走到右穿过 24 幅名画

huashu-art-motion 长卷穿越片:一个骨架加按段并行,让主角从左走到右穿过 24 幅名画 【免费下载链接】huashu-art-motion艺术动画skill35种艺术风格、9种解说语法用代码让画动起来。项目地址https://gitcode.com/gh_mirrors/hu/huashu-art-motion点击查看免费下载本篇讲解 huashu-art-motion 仓库中「长卷穿越片」的完整制作方法一条横向长画卷由多个「世界段」首尾相接主角一直向右走跨过边界的瞬间主角画风与世界一起切换。读完你能够看懂scripts/engine/demos/long_scroll/的骨架与各段实现掌握统一常量、按「互动开始」定时、只进不退相机等关键约定并按 4 步流程为新片加入一个世界段最后用静帧与qa.py验收。长卷穿越片是什么与「艺术史速通」的做法同一个房间、切换画风不同长卷穿越片是一条横向延展的长卷每个世界是一段横向的画各段首尾相接主角一直往右走跨过边界的那一刻他的画风和世界一起换。《花叔穿越名画》2026-10-05123.7 秒24 个世界就是这么做的仓库里收了一个 3 段示范埃及壁画 → 莫奈《日本桥》→ 8-bit 像素约 15.6 秒位于 scripts/engine/demos/long_scroll/。在仓库根目录即可运行示范uv run --with playwright python scripts/engine/render.py --film demos/long_scroll --stills 1,5,9 --out 试渲 # 三张静帧 uv run --with playwright python scripts/engine/render.py --film demos/long_scroll --out long_scroll.mp4 # 整段浏览器预览在scripts/engine/起一个静态服务打开index.html?filmdemos/long_scrollonly28_monet,14_8bit只排这几段v330试别的步速。从源码看render.py 会起本地 http 服务、用无头 Chromium 打开index.html逐帧调用window.renderFrame(t)读出 canvas 像素、管道送 ffmpeg 出 60fps mp4--stills只导出指定秒数的 PNGrender.py#L79-L83。页面出现pageerror或console.error时渲染会以非零退出等于自带一道冒烟测试。目录结构每个文件管什么文件管什么eras.js片子入口加载库、FILM_ORDER段的顺序、登记帧库、生成一个dur WORLD.total的段lib/world.js骨架WORLD时间轴走→停下互动→走、主角行进、相机、按边界裁开的主角、边界、角标。先读它的头部注释lib/crossing.jsXING读帧库、画角色帧XING.actor、笔触材质、莫奈世界lib/acts.jsACT小剧本工具打水漂的石子轨迹等lib/xing2_*.js几段共用的小工具由段文件开头按需同步加载segments/id.js一个世界一个文件调用WORLD.add({...})frames/key/角色帧库8 张透明 PNGmeta.json每帧脚底锚点ax/ay、尺寸、是否离地airref_h是站立身高的像素数eras.js 的全部逻辑只有几行先同步加载crossing.js、acts.js、world.js然后声明顺序——window.FILM_ORDER [02_egypt, 28_monet, 14_8bit]eras.js#L14接着按顺序加载每个segments/id.js并校验它确实调用了WORLD.add再把各段用到的帧库 keyhero.walk、acts[].key、sprites一次性登记进window.EXTRA_ASSETS引擎启动前全部加载最后WORLD.layout()并导出一个引擎段落window.ERAS [{ id: film, dur: WORLD.total, draw: (c, lt, t) WORLD.draw(c, t) }];也就是说整部长卷在引擎眼里就是一个「时代」渲染器不感知段的概念。骨架 world.js统一常量与全片时间轴lib/world.js#L19 把全片常量写死在骨架里const WD window.WORLD { segs: [], GROUND: 760, V: (…get(v) || 560), HERO_H: 300 };地面线WORLD.GROUND 760全片统一跨边界时两边脚底在同一高度主角站立身高HERO_H 300步速V默认 560 px/s可用 URL 参数?v330覆盖主角在画面左 38% 处即相机目标 主角 x − 720所以他始终站在 1920px 画面的 720px 位置。WORLD.layout()world.js#L24-L40按FILM_ORDER把各段首尾接起来给每段算x0/x1并把每段按acts互动点切成「走 → 停做动作 → 走」的时间轴得到全局的WD.plan与总时长WD.total。heroAt(t)在任意全片时刻给出主角位置开场主角从段内START_X 320起步保证第 0 帧整个人可见。边界不是直线而是一条轻微波浪线WD.seamX(s, y)world.js#L49每条边界相位不同。绘制的核心技巧在 world.js#L55-L80背景、主角、前景各自独立按「段」画一遍每段画之前先用band()沿左右两条边界线做 clip。于是主角被边界「裁开」左半身用左边段的世界坐标与画风帧绘制右半身用右边段的跨界的连续性由统一常量保证。跨界瞬间还会由XING.burst画一圈颜料迸散颜色由段的burst字段指定如jia_egypt画面右上角则随所在段切换「年份名」的角标切换时淡入。关键约定一所有事件相对「互动开始」定时这是整套做法里最重要的一条纪律段里所有事件的时间都相对「互动开始」不写「进段后第几秒」。骨架提供WORLD.actT(段, k)world.js#L100返回第 k 个互动开始的全片时刻段内事件一律写成r S.t - WORLD.actT(ME)xing2_jia.js 里的XJ.ta(seg, s)就是它的便捷版互动前为负。以 28_monet.js 为例石子四跳的节奏全部是相对出手动作开始的秒数// 事件按「互动开始后的秒数」r 定时r S.t - WORLD.actT(ME)。示范节奏4 跳拉开到 1.36 秒、间隔递增 const THROW [[0, 0], [0.18, 1], [0.36, 2], [0.44, 3], [0.5, 4], [0.66, 5]]; const HOPS [{ x: AT 170, y: 790, t: REL 0.22, s: 0.5 }, … { x: AT 460, y: 985, t: REL 1.36, s: 0.86, peak: 190 }];这样写的回报是实实在在的全片步速后来从 330 提到 560按这条约定写的段一处都不用改。同理帽子纪念品的落帽时刻推荐写item.atAct 互动开始后第几秒WD.itemTworld.js#L101-L102旧的gotAt进段后第几秒写法在步速变化后会错位骨架注释里已经标明。关键约定二镜头只进不退跟拍长卷最怕「倒带」感。v1 审片时发现互动时镜头往前让出空间、结尾收回24 段里 17 段出现 68–256px 的后退qa.py测不到、审片一眼看出。修法写在WD.camAtworld.js#L81-L97相机目标 主角 x − 720 互动时向前让出的leadlead只升不降默认 160px对目标序列取历史最大值保证全程单调再做高斯平滑σ≈0.14s单调信号卷积正核仍单调停与起都不顿。所以全程 0 次后退。如果某个互动想让镜头别动比如主角原地跳水漂镜头前冲反而画外就在该互动写lead: 0——28_monet.js与02_egypt.js的互动都是这么做的。8-bit 段则反过来用lead: 140让镜头在起跳前多让一点空间保证砖块和金币都在画面里。关键约定三边界两侧怎么接得上段两端x0 和 xw 附近 ±150px地面必须回到 760地平线尽量落在 480–560跨边界时两边才接得上中间可以有桥、台阶段里写ground: lx y主角脚底高度优先取它world.js#L107。莫奈段就是整段站在拱桥桥面上ground: lx M().deckY(lx)28_monet.js#L62每段的边界用该段的签名语言画seam(c, y, sx, t)画「进入本段的那条边界」。示范三段的三种写法——埃及段是竖向四色彩块边墓室壁画的边框语言02_egypt.js#L232莫奈段是粉蓝绿奶白相间的印象派短笔触微微颤28_monet.js#L80-L848-bit 段是黑白相间的像素棋盘边14_8bit.js#L116。这就是「转场 下一个风格的签名语言」在长卷里的版本不写seam时骨架兜底画一条纸边。主角AI 生帧代码合成8 帧一个步态循环角色帧是 AI 按各画风重画的透明 PNG做法见 references/10-角色.md代码只决定在哪、多大、何时换帧、加什么材质。帧库与 meta.json。每个世界一张「走路 8 帧」有互动的再加一张「互动 8 帧」放进frames/key/。以 frames/egypt_walk8/meta.json 为例每帧记录脚底锚点ax/ay、帧尺寸w/h、是否离地air库级ref_h: 444是站立身高对应的像素数——XING.actor画帧时用o.h / ref_h统一缩放crossing.js#L106-L110保证整套帧同一比例、脚底精确落在y上。走路帧率随步速同比例。02_egypt.js#L12 量出帧库在步速 330 时的帧率fps: 12.6骨架里换帧相位是walked * (H0.fps || 8.5) * WD.V / 330world.js#L111步速 560 时帧率自动等比升到 21.48 帧一个步态循环不变、相位跨边界连续。再配XJ.walkLockxing2_jia.js#L40-L47做「脚底锁」一个半周期4 帧里支撑脚的世界位置不变用连续错切把膝盖以下平移回去支撑脚贴地不打滑边界两侧 220px 内渐隐到 0避免左右半身错位。停下/起步不硬切。XJ.glide(dur)xing2_jia.js#L80-L82在互动头尾各 0.22s 匀减/匀加XJ.glideWalk让缓冲期里继续播走路帧、步频随速度降到 0 再升回相位与互动前后首尾相接。埃及段的互动圣甲虫推太阳球滚过他跳开完整展示了这套写法acts: [{ at: AT, dur: DUR, key: K.act, lead: 0, ...XJ.glide(DUR), frame: XJ.actFrame([[0, 1], [0.22, 2], [0.3, 3], [0.42, 4], [1.04, 5], [1.2, 6], [1.4, 7]]), y: (lx, u) G - 140 * Math.sin(Math.PI * clamp((u - 0.22) / 0.9)) }],frame(u)把动作内秒数映射到帧号XJ.actFrame查表y(lx, u)给出脚底高度抛物线跳起两者都是相对互动的。8-bit 段的y则是起跳抛物线落地后的小欢呼跳14_8bit.js#L86-L88。画风材质在段里写不改共用库。需要再过一层该画风材质时在段里写hero.draw(c, key, i, o, S)自己合成。三种示范莫奈28_monet.jshero: { walk: monet_walk, mat: monet, … }直接用XING.actor内置的莫奈短笔触材质——笔触只乘在人身上source-atop暖黄光斑与淡紫阴影按世界坐标落在身上他走过时光从身上滑过crossing.js#L111-L120埃及02_egypt.jshero.draw里调XJ.actor(c, key, i, o, egypt, heroMat)heroMat把灰泥墙面斑驳纹理只乘在角色上XJ.texInside纹理层destination-in剪影后multiply回去白帽保持纯白不变灰8-bit14_8bit.js#L75-L80AI 生的像素小人帧再按 6px 网格降采样、alpha 二值化去抗锯齿、色值吸附到 36 的倍数保证真·硬边像素。加一段的 4 步流程写段文件。在segments/新建id.js调用WORLD.add({ id, year, name, w, hero, acts, back, front, seam })完整接口见 lib/world.js 头部注释world.js#L4-L16w是段宽世界 px注释要求 ≥1900示范段取 2000–2150原片各段 2000–2800back(c, s)/front(c, s)画背景/前景s提供camX段内、t全片秒、lt进段后秒、hx/hy主角段内坐标、act:{i, u}正在做的互动及动作内秒、W:1920, H:1080世界本身用代码画优先把 scripts/engine/scenes/ 里现成的风格场景改造成横向延展的版本如埃及段沿用 scenes/02_egypt.js 的象形字库、彩块边框与 multiply 壁画表面。生角色帧。每个世界一张「走路 8 帧」有互动的再加一张「互动 8 帧」按该画风让生图模型重画、绿幕、切帧scripts/key_split.py去绿溢、按列空隙切成单个姿势白底线稿用--white只裁不抠需保留原画面坐标时用 scripts/key_green.py放进frames/key/写好meta.json。做法细节见 references/10-角色.md。登记顺序。把id加进 eras.js 的FILM_ORDER加段 往segments/放一个文件再把 id 写进来帧库会自动登记。验收。渲静帧核边界两侧--stills取跨界前后两个时刻再跑uv run qa.py --project scripts/engine --film demos/long_scroll确定性必须 ✓。qa.py 会对每段做四件事同一时刻冷渲热渲两次逐像素比对确定性、每帧耗时、运动面积与静止帧对比例动感、相邻帧差峰值跳变并检查文字框景与字幕带qa.py#L10-L18。配乐画面先定音乐后配原片配乐的经验是每段放整数拍逐段把速度在86–104 BPM之间微调让每条边界都落在小节第一拍——24 条边界最大误差 11.7ms、平均 3ms单一 BPM 时最好也差 112ms人耳听不出 ±8% 的逐段速度差但听得出换乐器没踩在重拍上。音频合成与对齐见 scripts/audio/synth_艺术史速通.py 与 references/风格配方/_音轨_艺术史速通.md。并行协作与几条负面清单这套「骨架写死统一常量、段与骨架解耦」的结构使得长片可以按段并行完整片里 24 个世界由 4 组 agent 各写 6 段按年代排序后一次拼成 123.7 秒qa确定性 ✓、跳变 0审片核对 23 条边界的地面高度与主角连续性全部通过见 references/07-正面经验.md 第 36–38 条。还有两条默认关闭/不做的事写进骨架防跑偏不要替主角加没要的梗。骨架里有「帽子上摞纪念品」的功能window.FILM_HAT_ITEMSworld.js#L117 与WD.drawHatStack容易与场景争夺视觉注意力默认关闭段也可以用hideHatItems(S)接管帽子被叫飞、摘帽放桌上时由段自己画。事件相对互动定时这条纪律的反例同样写在注释里全片步速从 330 提到 560 之所以「一处都不用改」正是因为所有段都没写「进段后第几秒」。小结长卷穿越片的全部技巧可以压缩成一句话把全片统一的东西地面线 760、身高 300、步速、事件定时基准写死在骨架lib/world.js把每段特有的东西背景画法、互动剧本、签名边界隔离进segments/id.js角色用 AI 生帧代码合成。这样新段是纯增量、全片可并行、步速与音乐后配都不回头改段render.py --stills加qa.py两道验收兜住确定性。想动手的话从index.html?filmdemos/long_scrollonly28_monet,14_8bit开始看再照上面的 4 步流程加你的第一个世界段。赞分享【免费下载链接】huashu-art-motion艺术动画skill35种艺术风格、9种解说语法用代码让画动起来。项目地址https://gitcode.com/gh_mirrors/hu/huashu-art-motion点击查看免费下载相关推荐huashu-art-motion「一帧先行」工作流详解四条让画面动起来的实战路线huashu art motion「一帧先行」工作流详解四条让画面动起来的实战路线 本篇技术文章以 huashu art motion 仓库的方法文档 03huashu-art-motion 角色实现指南AI 生帧 代码合成让角色在 35 种画风里动起来huashu art motion 角色实现指南AI 生帧 代码合成让角色在 35 种画风里动起来 本文基于仓库文档 references/10 角色.huashu-art-motion 深度解读让 Coding Agent 用代码画出会动的艺术动画huashu art motion 深度解读让 Coding Agent 用代码画出会动的艺术动画 这是一篇面向「给 AI Agent 派活」场景的技术指南上一篇grok-build 0.2.116 版本详解streaming-json 增强、/undo 命令与登录稳定性修复下一篇Slang 图形着色器与计算内核入口点全解析从 [shader(stage)] 属性到全部管线阶段创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进