尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用Scratch制作FNF模组:镜头移动与缩放实战解析

用Scratch制作FNF模组:镜头移动与缩放实战解析 用 Scratch 编 FNF 模组 Plutos Reprisal Part4镜头移动和放大缩小这种效果都能做出来这件事值得好好拆一遍。很多人一听 FNF 模组第一反应是去改原版游戏的资源包但用 Scratch 做模组完全是另一条路不用装引擎不用碰代码文件所有逻辑都用积木拼核心难点不是“能不能做”而是怎么把镜头变化、节拍同步、角色出场这些时序理顺。这个主题适合两类人看一类是想做音游模组但还不熟悉 Unity、Godot 这类引擎的爱好者另一类是已经在用 Scratch 做小游戏想加入镜头动效但不知道从哪下手的玩家。我这次围绕 Plutos Reprisal Part4 的实际开发过程把镜头移动、放大缩小的实现思路、边拍边修 bug 的流程、以及真正会卡住你的那些坑点都整理出来。1. 用 Scratch 做 FNF 模组到底是在做什么1.1 音游模组的核心不是画面而是节奏和状态切换FNFFriday Night Funkin本身是节奏游戏。玩家跟着音乐在上下左右箭头到达判定线时按下对应方向键。所谓模组通常是把原版角色、背景、歌曲、谱面替换成新内容。用 Scratch 做模组不是去改原版游戏文件而是用 Scratch 重新搭一个玩法接近的音游成品。既然玩法是音游那整个游戏的核心就两条音符掉落和判定是否准确画面变化和音乐节拍是否对得上。镜头移动放大缩小属于第二条里的表现层它是锦上添花但也是很容易翻车的地方。很多人在 Scratch 里做音游先去做角色动画、特效、背景结果音符判定和音乐对不上后面全白搭。正确顺序应该反过来先把节奏框架跑稳再往上加镜头变化。Plutos Reprisal Part4 能把镜头移动放大缩小做出来说明底层的时间线已经先立住了。1.2 相比 Unity、Godot 等引擎Scratch 的优势和短板Scratch 做这种项目优势非常明显不需要安装复杂引擎打开网页编辑器或者离线编辑器就能开始。不用写代码逻辑全部靠积木拼接适合没接触过编程的人。事件处理很直观比如“当收到广播”“当按下方向键”天然适合做按键响应。调试时可以随时点绿旗重启改一个积木就能立刻看到效果。短板同样明显性能上限低。克隆体多、素材大、特效复杂时很容易卡顿。音频和画面不同步。Scratch 播放声音时没有一个稳定可靠的“当前播放到哪一毫秒”的接口这让音游对拍特别麻烦。舞台大小和图层机制有限。复杂场景、多层视差、精细特效表现力不如引擎。发布和分享受限。在线项目对素材体积、运行环境有更多不确定性。所以如果你只是想把一个 FNF 模组做得“能玩、像样、能给别人点开试试”Scratch 完全够。如果你想做成长型作品加入复杂过场、精确判定、大量特效那就得认真做资源管理和性能取舍。2. 镜头移动和放大缩小我先拆成三件事2.1 坐标更新镜头位置本质是“所有舞台元素偏移”Scratch 里没有摄像机对象所以“镜头移动”要用变量模拟。我当时给整个工程定义了一套虚拟相机变量比如 camera_x、camera_y、camera_zoom。这套变量的含义是摄像机现在盯着世界里的哪个点以及当前画面放大到了多少倍。舞台上所有角色实际显示位置都需要基于这套变量重新计算。举个例子。一个角色的世界坐标是 world_x、world_y那么它在屏幕上的显示坐标大致是屏幕x world_x - camera_x 屏幕y world_y - camera_y当 camera_x 从 0 变成 200所有角色的屏幕 x 都会往左偏移 200看起来就像镜头向右移动了。这是镜头移动最基本的原理。但这里有一个很关键的问题Scratch 的角色位置是直接通过“移到 x/y”积木设置的你要么把所有元素都按这套公式手动计算要么把角色塞进同一个“图层组”里统一管理。我建议使用前面的方式虽然计算量变大但后期调整单个角色非常方便。2.2 缩放用造型大小和图层距离模拟镜头变焦放大缩小的实现比移动麻烦一些。Scratch 本身没有“镜头缩放”功能你能控制的只有每个角色的“大小”。所以我的做法是当 camera_zoom 改变时每个元素的最终大小 base_size * camera_zoom。这听起来简单实际上有三个坑第一个坑是缩放中心。角色放大后默认是围绕造型中心点缩放。如果镜头中心不是角色中心视觉上就会“偏”。需要给每个元素定义一个统一的锚点比如角色脚底中心、舞台中心点、背景左上角。缩放时先按锚点重算位置再设置大小。第二个坑是位图模糊。如果素材是位图图片放大后会糊成一片。解决办法是素材尽量用矢量造型或者把原图做大一点缩小显示给放大留出余量。网上找的素材想直接在 Scratch 里用最好先确认格式和分辨率不要直接导入一张 200×200 的小图就指望放大了还清晰。第三个坑是缩放和移动的联动。镜头缩放时元素不仅大小会变位置也必须跟着变。如果只改大小不改位置就会出现角色原地变大、背景没跟着动的怪效果。2.3 平滑过渡不要直接跳而是用补间计数镜头最忌“跳变”。camera_x 从 0 直接变成 200画面会“唰”一下瞬移过去非常生硬。要做出“镜头滑过去”的感觉需要用补间逻辑。我当时用的是很简单的插值法每帧把当前值向目标值移动一部分camera_x 增加 ((目标x - camera_x) * 0.1)这种写法会让镜头一开始快、后面慢有种缓出效果。如果想要更精准控制时间可以用一个过渡进度变量过渡进度 过渡进度 0.02 如果 过渡进度 1那么 过渡进度 1 camera_x 起点x (目标x - 起点x) * 过渡进度 camera_y 起点y (目标y - 起点y) * 过渡进度 camera_zoom 起点缩放 (目标缩放 - 起点缩放) * 过渡进度用这种写法你能精确知道镜头在某一帧处于什么位置排查问题时会方便很多。纯靠“增加 0.1 倍距离”虽然写起来快但镜头到没到目标、什么时候到不好判断。我一般会先做移动再做缩放最后把两者合并到同一条过渡逻辑里。不要一开始就同时上移动和缩放出 bug 你都分不清是位置问题还是缩放问题。注意补间系数不要设太大。有人为了让镜头“更有感觉”把系数设成 0.3、0.4结果镜头像被弹簧拽着一直乱晃。对新手来说系数在 0.08 到 0.15 之间比较稳妥。3. 实际制作顺序先单镜头再接谱面再对拍3.1 第一步只做一条轨道和一个镜头脚本我开始做 Part4 的时候没有一上来就铺满整个歌曲。我先建了一个只有一个音符的测试谱面然后在这个基础上调试镜头。整个过程分成三块音符生成模块负责在特定时间生成左右上下箭头并按节拍向下移动。判定模块负责检测按键是否在判定区域内按下。镜头模块负责根据歌曲进度切换位置、大小和过渡效果。第一步先把这三个模块的“空壳”搭出来也就是让角色出现在舞台上、音符能下落、角色能播放一个 idle 动画。镜头模块先放一边只有 camera_x、camera_y、camera_zoom 三个变量和默认值。为什么要先这样因为镜头只是表现层它必须依附在稳定的逻辑层之上。音符下落都卡顿的话镜头再炫也没有用。3.2 第二步让镜头变化绑定到歌词或节拍时间点搞定基础谱面之后再让镜头“动起来”。镜头的触发时机不能靠人为目测得有明确的时间点。Scratch 没有稳定读取音频播放位置的积木所以我采用了一个“帧计数器”思路绿旗启动后每帧把变量 tick 加 1然后根据设定的帧率估算歌曲时间。比如目标帧率是 30那么 tick 到 60 大约就是 2 秒。然后用条件广播控制镜头如果 tick 90那么发送广播“镜头切近景” 如果 tick 210那么发送广播“镜头拉远”这种方式虽然粗糙但胜在可控。只要歌词、谱面和镜头全部挂在同一个 tick 时间轴上就算稍微有偏差也能通过微调 tick 触发值来解决。如果有条件更稳的方式是让音乐文件自身带节拍点比如先把歌曲在音频软件里标出段落位置再把这些时间点转换成 tick 参考值。不要靠“感觉差不多”去对时间那样后期一定会返工。3.3 第三步加入角色出场和背景切换最后再叠特效谱面和镜头对拍稳定之后才开始叠加其他内容。角色出场的标准做法是先让角色造型隐藏到指定 tick 时切换造型并显示同时播放一段入场动画。入场动画可以通过连续切换几个造型来实现也可以用“重复执行”配合位置变化实现滑入效果。背景切换同样挂在 tick 上。Part4 的场景变化比较多我在切换背景时给背景加了一个透明度和大小渐变让过渡不那么生硬。最后才做特效比如音符命中后的闪光、连击数字、背景粒子。特效是最吃性能的部分后面再提怎么控制。这里我踩过一个教训千万不要在镜头过渡还没结束的时候同时触发背景切换和角色入场。多个动画叠加时如果都用了不同的计时器很容易出现角色已经到位了、背景还在缩放、镜头又重新开始的混乱局面。我的做法是把镜头过渡、背景切换、角色入场全部统一到同一个进度变量也就是同一个过渡公式里。4. “边拍边修 bug”的正确打开方式4.1 先把“复现”变成可重复操作“边拍边修 bug”听起来像自嘲其实是非常高效的开发状态。镜头动效这种视觉项目你很难光看代码逻辑就判断“这样会出问题”。最可靠的方式是录制回放肉眼观察。我实际的操作流程是调整某个镜头逻辑。绿旗启动然后边操作边录屏。回放录像看具体在哪一帧出现了问题。根据问题修改积木再重新录制对比。这里最重要的是“复现可控”。如果 bug 只在某种操作顺序下出现那你就必须每次都按相同顺序操作。把输入固定下来不要靠随机。比如测试时音符下落速度、镜头目标位置、触发 tick 都写死不要每次都不一样。Scratch 里虽然没有传统日志系统但可以借助“列表”来记录关键事件。我习惯在镜头移动时把当前 tick、camera_x、camera_y、camera_zoom 追加到一个列表里等跑完一遍后查看列表就能判断到底是哪一步出了问题。4.2 修 bug 的优先级阻挡游戏的 bug 先修视觉瑕疵后修镜头 bug 也分等级。我一般按这个优先级排序优先级问题类型例子P0阻挡游戏正常运行音符判定失效、游戏卡死、无法返回标题P1严重视觉错误镜头飞到舞台外、缩放后角色错位、背景重叠P2轻微视觉瑕疵某一帧角色跳了一下、特效闪得不自然P3可优化项镜头缓动不够顺滑、背景层次感不足如果同时出现多个问题先从 P0 开始修。镜头乱飞虽然很显眼但如果音符判定和声音错位了那才是真正要命的。修完 P0再看 P1P2、P3 可以留到最后统一处理。4.3 录制回放和日志怎么判断是画面问题、逻辑问题还是素材问题边拍边修的时候最怕的是不知道问题出在哪一层。我常用的判断链路是先看画面是否按预期动了。如果画面没动检查镜头变量是否在变。再看变量是否在变。如果变量在变但画面不对说明是坐标计算、图层或大小设置的问题。如果变量根本没变说明是触发条件没满足比如广播名字写错、tick 时间点不对、条件分支被跳过。如果触发条件也正确但还是有问题查积木顺序。Scratch 里积木是按顺序执行的有时候你把“将大小设为”放在“移到 x/y”前面和后面的效果完全不同。最后看素材。角色显示异常时先检查造型名称是否匹配、素材中心点是否合理、图片是否是透明背景。这一套顺序能排除大部分问题。不要一上来就去怀疑“内部 bug”很多问题都是素材、触发条件、重置状态没处理好。5. 我在 Part4 里实际踩到的问题和排查顺序5.1 镜头突然飞到舞台角落这个 bug 在开发过程中非常常见。表现形式是镜头过渡到一半突然“嗖”一下跑到舞台左下角或者右上角然后永远回不来。排查之后发现两种主要原因一种是因为局部变量和全局变量重名。Scratch 里的变量可以区分是“仅适用于当前角色”还是“适用于所有角色”。如果某个角色内部有一个和全局变量同名的局部变量很容易互相覆盖。另一种是因为镜头过渡循环没有在适当的时候停止。比如角色到达目标位置后过渡循环还在继续运行把 camera_x 越拉越远。这种情况要加一个“过渡结束”标志到达目标值后立刻停止循环。5.2 缩放回调之后角色位置错位放大后拉远角色应该回到初始位置结果它偏了。这个问题我排查了很久最后发现是角色的造型中心点不一致。Scratch 中一个角色可以拥有多个造型每个造型的图片中心点可能不一样。镜头缩放对位置的计算默认使用当前造型的锚点。当角色在镜头放大过程中切换了造型中心点变了位置自然就偏了。解决办法是所有角色的所有造型中心点必须统一最好都用脚底中心作为锚点。或者给每个角色单独编写“重新定位”积木在镜头缩放结束后强制将角色放到正确坐标。5.3 音符判定区域和背景发生分离镜头放大缩小后背景和音符判定线位置不统一。音符还在原来的判定线位置但背景已经偏移了导致玩家按方向键时感觉“明明按了才对实际判定却不对”。这个问题的根源通常是音符的生成坐标和背景的坐标没有使用同一套世界坐标。如果用 Scratch 默认的舞台坐标来生成音符而背景却基于虚拟镜头坐标计算一旦镜头移动两者就会分离。修复方式把音符、角色、背景、判定线全部统一纳入虚拟镜头坐标系。判定线不要放在固定舞台位置而是和音符一样根据 camera_x、camera_y 实时计算显示位置。5.4 卡顿、掉帧和声音不同步卡顿在 Scratch 音游里比任何功能 bug 都难处理。掉帧会直接影响音符下落速度进而影响判定。我遇到的卡顿主要集中在三处克隆体太多。音符生成使用了克隆体每个克隆体每秒还要更新一次位置。如果当前画面上有 20 个克隆体以上低配电脑就开始吃紧。声音播放重叠。多个声音同时播放时Scratch 的性能会明显下降。背景图片过大。导入了一张高分辨率背景图舞台每次渲染都要处理大图片帧率直线下降。解决思路把音符数值降到合理范围不要一次性显示太多音符。优化素材图片能压缩就压缩不要直接用超大原图。减少同时播放的音效数量可以用变量做“最近一次音效播放时间”避免同一帧播放多个音效。在测试阶段先关掉不影响逻辑的特效比如背景粒子、命中闪光。另外强烈建议使用 Scratch 离线编辑器进行开发。在线版受浏览器性能影响更大录制时也容易掉帧。离线版更稳定也方便备份工程文件。注意如果镜头缩放时出现明显卡顿先检查当前帧是否有多个大型造型同时缩放。你可以把缩放改成“只改重要角色背景用淡入淡出”来降低压力。6. 如果你想做类似模组记住这几条边界6.1 素材来源与版权做 Scratch 模组时很多素材来自网络包括角色立绘、背景图、音乐、音效。如果是基于 FNF 的歌曲、角色或画风进行再创作请务必只把它当作学习练习不要以原作品名义发布或用于商业用途。网上找的素材要直接在 Scratch 中使用建议先做三件事确认格式最好 png/svg、确认透明通道、确认分辨率。不要导入后才发现背景是一个白色矩形遮挡了其他角色。6.2 性能上限低配电脑、在线版和离线版Scratch 项目的性能上限很难量化因为它依赖浏览器和设备。我的建议是不要追求复杂的镜头粒子特效而是把动态控制在“几层背景 几个角色 几条音符轨道”以内。我先给一个保守配置参考项目建议范围同时存在的克隆体30 个以内同时播放的声音3 个以内舞台背景图片单张尺寸不超过 1000×600镜头缩放范围0.8 到 1.2 之间单个角色造型数量10 个以内如果你的机器配置比较低这些数值还要再降。能跑通不代表适合长时间玩更不代表适合直播录制。低配环境下先把分辨率、克隆体数量和音效数量降下来。6.3 判断“能玩”和“能发布”的验收标准一个 Scratch 音游模组做到什么程度算“能玩”我自己的验收标准是从绿旗启动开始是否能不卡死地进入游戏。是否能完整打完至少一关。音符判定是否稳定按键反馈是否正常。镜头移动、缩放是否在预期时间和位置触发。镜头拉回后音符判定是否恢复正常。失败后是否能重新开始不会出现状态残留。连续测试三遍不会出现随机性错误。如果这七条全部通过才说明这个模组具备分享给别人玩的条件。如果只能跑出画面、只能看动画那不叫完成了。6.4 后续扩展思路道具、过场、多角色、谱面生成镜头移动和放大缩小实现后可以做的扩展还有很多音符速度变化。某些高能段落把音符下落速度调快制造压迫感。判定反馈特效。在判定线附近加闪光、放大、变色。多角色切换。不同角色使用不同的攻击反应动画。过场系统。在歌曲段落之间插入对话和场景切换。谱面自动化生成。把谱面数据写进列表生成音符时直接读取减少手动堆积木。但要注意任何扩展都要保持“一次只动一个变量”。想加道具系统那就先只加道具不要同时改镜头和音符速度。否则你根本分不清问题出在哪块。回到 Plutos Reprisal Part4镜头移动和放大缩小能做出来说明时序管理已经过关了。最开始我也觉得镜头难后来发现真正难的不是让镜头动而是让它在正确的时间动、动到正确的位置、结束后还能干干净净地复位。边拍边修 bug 不是效率低而是视觉开发里最稳妥的验证方式你把过程录下来回放时大部分问题都会自己现形。如果只是学习Scratch 完全够用如果要长期维护记得把镜头变量、触发表、素材归档都理清楚这才是最容易被忽略的一步。
返回列表