模板工程升级修改

This commit is contained in:
2026-08-11 22:17:54 +08:00
parent 047561675b
commit 3b7c103387
38 changed files with 16607 additions and 1205 deletions
@@ -0,0 +1,88 @@
// ============================================================
// SpineOverlayTransform —— WebGL 叠加层坐标标定(纯函数)
//
// 职责:把 gameabc 主画布的权威变换矩阵换算成 WebGL 的 MVP 矩阵。
// 无副作用、无 DOM 依赖,可独立单测。
//
// 为什么不逆向 gameabc.min.js:那是混淆代码(变量名全打乱),读不出它内部如何
// 映射坐标。而 Spine 绘制发生在 gameenddraw(gameabc 绘制流程末尾),此刻 ctx
// 上已带着 gameabc 设好的全局变换 —— 直接向 ctx 要矩阵即可,权威、且 gameabc
// 后续改缩放/响应旋转时自动跟随。
//
// ⚠️ 真机实测确认:Spine 实际画在 gameabc_face.dc.canvas 这张离屏画布上
// (backing 约 1280x720,不在 DOM),gameabc 再把它 blit 到 DOM 中可见的显示
// 画布 #canvas(backing 约 1912x880),最后经 CSS 缩放到屏幕。本函数的
// canvasW/canvasH 必须传绘制缓冲画布(dc.canvas)的 backing 尺寸,因为
// Spine 坐标正是喂给这张画布的,分母须与其同源;叠加层自身的定位/CSS 尺寸/
// drawing buffer 则是另一个来源(显示画布 #canvas),由调用方
// SpineBackendWebGL 负责,不在本函数职责内。
//
// 推导(Spine 世界坐标 Y-up,画布 Y-down):
// 位移由调用方经 skeleton.x = e.x; skeleton.y = -e.y 承担,本矩阵只处理
// scale(1,-1) 与投影,等价于 Canvas 后端的 ctx.translate(e.x,e.y)+ctx.scale(1,-1)。
//
// 1) Spine 世界 → 逻辑坐标: Lx = vx, Ly = -vy
// 2) 逻辑 → 画布像素: Px = a*Lx + c*Ly + e, Py = b*Lx + d*Ly + f
// 3) 画布像素 → NDC: x = 2*Px/W - 1, y = 1 - 2*Py/H
//
// 合并:
// x_ndc = (2a/W)*vx + (-2c/W)*vy + (2e/W - 1)
// y_ndc = (-2b/H)*vx + ( 2d/H)*vy + (1 - 2f/H)
//
// 注意:叠加层 drawing buffer 尺寸在推导中被约掉(gl.viewport 覆盖整个 buffer,
// NDC 自动铺满),故本矩阵只依赖 ctx 变换与绘制缓冲画布 backing 尺寸。因此所有
// entry 共用同一个 MVP,可一次 batcher.begin/end 批量绘制。
// ============================================================
(function(){
var SpineOverlayTransform = {
// ----------------------------------------------------------
// buildMvp(m, canvasW, canvasH, out)
// m : {a,b,c,d,e,f} —— ctx.getTransform() 的六元素
// canvasW : 绘制缓冲画布(gameabc_face.dc.canvas)的 backing 宽(实测约 1280)
// canvasH : 绘制缓冲画布(gameabc_face.dc.canvas)的 backing 高(实测约 720)
// out : 可选,长度 16 的复用数组(避免每帧分配)
// 返回列主序 4x4 矩阵
// ----------------------------------------------------------
buildMvp: function(m, canvasW, canvasH, out) {
var r = out || new Array(16);
var sx = 2 / canvasW;
var sy = 2 / canvasH;
// 第 0 列:vx 的系数
r[0] = sx * m.a;
r[1] = -sy * m.b;
r[2] = 0;
r[3] = 0;
// 第 1 列:vy 的系数
r[4] = -sx * m.c;
r[5] = sy * m.d;
r[6] = 0;
r[7] = 0;
// 第 2 列:z 保持
r[8] = 0;
r[9] = 0;
r[10] = 1;
r[11] = 0;
// 第 3 列:平移
r[12] = sx * m.e - 1;
r[13] = 1 - sy * m.f;
r[14] = 0;
r[15] = 1;
return r;
}
};
if (typeof module !== "undefined" && module.exports) {
module.exports = SpineOverlayTransform;
}
// 友乐运行时有 module 无 require 且共享全局作用域,须无条件暴露全局名
window.SpineOverlayTransform = SpineOverlayTransform;
})();