分享
2026.5.7-日报-王雨默
输入“/”快速插入内容
2026.5.7-日报-王雨默
用户2965
用户2965
5月8日修改
一.工作内容概述
•
碎片收集系统数据框架、UI初步搭建
•
实现碎片拼图效果绘制逻辑
•
基于昨日进度,继续尝试GPT-Image2生图
二.碎片拼图效果实现
预期效果
1.
碎片拼图视觉效果
◦
碎片海报应当呈现接近真实拼图的效果,海报外边缘保持平直,内部碎片边缘呈现凹凸互补,而不是简单的矩形切图。
◦
每张海报会根据配置被切分成不同数量的拼图碎片,例如 4x6、5x6、9x15 等。
◦
不同切分数量下,碎片形状可以不同,但海报内容必须保持连续。同一张图片在同一归一化位置上的采样内容应保持一致,不会因为碎片数量变化导致整张图案整体偏移或每片独立拉伸。
2.
轮廓线表现
◦
轮廓线只用于表达“未收集区域”的拼图形状,不干扰已经收集到的海报内容。
◦
已填充碎片不显示轮廓线,避免完整海报画面被线条切碎。
◦
玩家已经收集到的区域应当更像真实图片,而不是一堆被描边的小块。未填充碎片继续显示拼图轮廓,用来提示剩余空位的位置和形状。
◦
轮廓线应当粗细稳定、透明度一致。相邻未填充碎片之间的共享边只绘制一次,避免左右或上下两个碎片重复描边,导致线条叠加变粗、变亮。
3.
飞入填充动画
◦
新获得并分配的碎片不会直接瞬间出现在海报上,而是通过飞入动画表现“获得并填入”的过程。
◦
动画开始前,目标位置仍然显示为空位轮廓。系统会创建一个临时飞行碎片,让它从碎片入口或广告按钮附近飞向目标海报位置。
◦
飞行中的碎片使用与目标位置一致的拼图形状和海报贴图内容,避免出现飞行时和落地后视觉不一致的问题。当碎片飞到目标位置后,临时飞行节点会被移除,目标位置正式显示为已收集碎片,同时该位置的轮廓线消失。
◦
整体流程为:碎片飞向海报 → 填入空位 → 海报内容恢复
实现思路
1. 拼图视觉表现
拼图渲染的核心由
PuzzlePosterRenderer
和
PuzzleShapeGenerator
配合完成。
•
PuzzleShapeGenerator 负责生成碎片形状。系统会根据海报的行列数和 seed 生成一张边缘表。海报外边界固定为平边,内部边缘随机生成凸起或凹槽。相邻碎片读取同一条边,但方向相反,因此可以保证凹凸关系互补。
•
每个碎片最终会被转换成一组多边形点。平边直接连接,凸起和凹槽则通过曲线采样生成。为了交给 Mesh 稳定渲染,系统还会把这些拼图多边形拆成三角形索引,再交给 Mesh 渲染。为了避免大量节点,已收集碎片不会每块创建一个节点,而是会遍历整张海报的所有碎片,只处理已经收集并且当前没有隐藏的碎片。每个碎片会贡献三类数据:
◦
顶点位置:决定碎片画在海报中的哪里。
◦
UV 坐标:决定这个顶点从海报原图的哪里取颜色。
◦
三角形索引:决定这些顶点如何组成可绘制的面。
所有已收集碎片的数据会被合并进同一个 Mesh。这样一张海报只需要一个主要 MeshRenderer,就能显示多个碎片,避免碎片节点过多可能带来的性能问题。
之前曾按“每块碎片自己的外接范围”做归一化,也就是每片碎片都把自己的形状单独铺满一个格子的贴图区域。这个方案会导致每片都被独立拉伸,文字和线条很容易错位。
现在改为按海报全局位置计算 UV。可以理解为:先确定当前碎片顶点在整张海报网格中的真实位置,再换算到原图上的对应位置。
核心思路类似:
代码块
Plain Text
sourceX = (col + 0.5) * sourceCellW + (point.x / cellW) * sourceCellW;
sourceY = (row + 0.5) * sourceCellH + (point.y / cellH) * sourceCellH;
•
col / row 表示当前碎片位于第几列、第几行。
•
sourceCellW / sourceCellH 表示原图中每个格子占多少宽高。
•
point.x / point.y 表示碎片边缘上的这个点相对格子中心偏移了多少。
•
合起来就是这个点在整张海报原图中的真实采样位置。
这样做以后,凸起部分如果几何上伸到相邻区域,就会采到原图中对应位置的内容,而不是被强行压回自己格子内部。文字、线条和图案因此可以跨碎片保持连续。
2. 轮廓线表现
•
轮廓线由
PuzzlePosterRenderer._drawOutline()
负责绘制,它和已收集碎片 Mesh 是分开的:海报图片内容是一层,轮廓线是另一层。这样系统可以独立决定哪些碎片显示图片,哪些位置显示轮廓。
•
当前轮廓规则是:如果某个位置已经收集并且不是动画隐藏状态,就不画轮廓;如果未收集,或者新分配碎片正在飞入、目标位置还处于隐藏状态,就继续画轮廓。这样可以保证已收集区域尽量干净,未收集区域仍然有空位提示。