Files
erqiwang_youle/client/index.html
T
joywayerandClaude Opus 5 35ee85e1d6 二七王:回退自造的图集叠绘,改用平台既有 SpriteManager.setNumberImage
方案作废并纠正认知:多帧图片精灵【不是】只能显示一位数——SpriteManager 第 1154 行
早有 setNumberImage(spriteId, text, charWidth):把整串文本设给一个多帧图片精灵,
引擎按字符逐帧渲染,精灵宽度按「字符数 × charWidth」自动调整。bc75e40 造的
drawImageRegion + NumberRenderer 是重复轮子,本次整体回退(revert bc75e40)。

- 回退:删除 gameabc-framework/ui/NumberRenderer.js 与其单测,SpriteManager 与
  index.html 恢复到改动前(与 bc75e40^ 逐字节一致)。
- ImageResources.js:数字类资源改为 16 帧、固定帧序 0123456789.+-x/p,逐条写明
  各帧含义、第16帧后缀(选主张数=「张」;结算/叫分的后缀标注待美术与规则确认,未瞎填)、
  单字符宽高与整图尺寸(16 × 单字宽),并说明帧序不可重排、不可省略占位。
- LayoutConstants.js:NUM_STYLE 改为 setNumberImage 所需的 res/charWidth/charHeight/suffix。
- Layout_Action.js:两个数字节点 h 取 charHeight(SSOT),w 留运行时注入
  (宽度由 setNumberImage 按字符数自动改,随位数变)。
- Sprites_Action.js / Sprites_Result.js:注释改为 setNumberImage 用法;
  结算玩家栏 ACC_TPL_SCORE_NUM 是复制精灵也能用(该接口不依赖绘制回调)。
- test_constants.js:NUM_STYLE 守卫改为校验 charWidth/charHeight/suffix 与
  「h 同源、w 运行时注入」;suffix 限定为 setNumberImage 支持的 分/倍/张。
- 文档:清单 §1.3/§1.5/§3.6/§5.4/§6.8 与前端 02 的那一节全部按 setNumberImage 重写,
  三种机制改为「文字精灵 / setFrame 切帧 / setNumberImage」,并记下这次误判作为反例。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 00:07:35 +08:00

297 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=0,viewport-fit=cover"/>
<title>jxmahjong</title>
<style>
body {
padding-top: constant(safe-area-inset-top);
padding-left: constant(safe-area-inset-left);
padding-right: constant(safe-area-inset-right);
padding-bottom: constant(safe-area-inset-bottom);
}
</style>
</head>
<body style='position:fixed;bottom:0;'>
<div id="ifastgame2" style="position:absolute;left:0px;top:0px;z-index:10">
<canvas id="bg1" width="1" height="1">
<p>Your browser does not support the canvas element.</p>
</canvas>
</div>
<div id="ifastgame_4" style="position:absolute;left:0px;top:0px;z-index:1">
<canvas id="ifastgame_bg" width="1" height="1">
<p>Your browser does not support the canvas element.</p>
</canvas>
</div>
<div id="ifastgame3" style="position:absolute;left:0px;top:0px;z-index:11">
<canvas id="bg2" width="1" height="1">
<p>Your browser does not support the canvas element.</p>
</canvas>
</div>
<div id="ifastgame" style="position:absolute;left:0px;top:0px;z-index:2">
<canvas id="canvas" width="6000" height="3000">
<p>Your browser does not support the canvas element.</p>
</canvas>
</div>
<!-- Spine WebGL 叠加层:z-index 3 夹在主画布(2)与 bg1(10)之间,
精确复刻"Spine 画在主画布内部、被 bg1/bg2 遮挡"的既有层级关系。
pointer-events:none 保证不抢主画布的触摸输入。-->
<div id="ifastgame_spine" style="position:absolute;left:0px;top:0px;z-index:3;pointer-events:none">
<canvas id="spine_gl" width="1" height="1"></canvas>
</div>
<style type="text/css">
* { margin: 0; padding: 0; }
html, body { height: 100%; width: 100%;
overflow-x:hidden;overflow-y:hidden;
backgroundColor:"rab(255,0,0)";
}
canvas { display: block; }
</style>
<script>
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
setupWebViewJavascriptBridge(function(bridge){});
</script>
<!-- <script>
returnCitySN={
ip:'127.1.1.1',
province:'',
city:''
};
</script> -->
<script src="http://47.98.203.17:8085/cityjson" ></script>
<script type="text/javascript" src="js/vendor/jquery-2.1.1.min.js"></script>
<script language='javascript'>var gameabc_face = gameabc_face||{};</script>
<script language='javascript'>gameabc_face.path="assets/bmp";</script>
<!-- Spine 运行时按需加载。
spine-canvas.js 与 spine-webgl.js 都以 var spine = (() => {...})() 暴露
同一个全局名 spine,同时加载会互相覆盖,故只能二选一。
强制切换(验证用):在本段之前设 window.__spineForceBackend = 'canvas' 或 'webgl'。-->
<script type="text/javascript">
(function(){
var forced = window.__spineForceBackend;
var useWebGL;
var reason;
if (forced === "webgl" || forced === "canvas") {
useWebGL = (forced === "webgl");
reason = "被 window.__spineForceBackend 强制指定为 " + forced;
} else if (location.protocol === "file:") {
// file:// 下 <img> 会被标记 tainted,texImage2D 拒绝上传
// (Canvas2D 的 drawImage 则允许,故 canvas 后端仍可工作)。
// 项目文档要求 HTTP 环境调试;此处兜住误用 file:// 的情形,
// 回退 canvas 保证特效可见,而不是抛一片 DOMException。
useWebGL = false;
reason = "file:// 协议下 WebGL 无法上传纹理,强制回退 canvas";
} else {
useWebGL = false;
reason = "WebGL 探测失败(getContext 返回空)";
try {
var probe = document.createElement("canvas");
var gl = probe.getContext("webgl") || probe.getContext("experimental-webgl");
if (gl) {
useWebGL = true;
reason = "WebGL 探测通过";
// 释放探测用 context:浏览器对并发 WebGL context 数量有限制,
// 泄漏会导致叠加层拿不到 context。
var lose = gl.getExtension("WEBGL_lose_context");
if (lose) lose.loseContext();
}
} catch (err) {
useWebGL = false;
reason = "WebGL 探测抛异常: " + err.message;
}
}
if (typeof console !== "undefined" && console.log) {
console.log("[Spine] 运行时选择: " + (useWebGL ? "spine-webgl.js" : "spine-canvas.js") + "(" + reason + ")");
}
document.write('<script type="text/javascript" src="js/vendor/spine-'
+ (useWebGL ? "webgl" : "canvas") + '.js"><\/script>');
})();
</script>
<script type="text/javascript" src="js/vendor/gameabc.min.js"></script>
<!-- Spine 资源清单:列出需要预加载的 Spine 资源基础名 -->
<script type="text/javascript" src="generated/spine_assets.js"></script>
<!-- Spine 文本数据嵌入(解决 file:// 协议 CORS 问题) -->
<script type="text/javascript" src="generated/spine_data.js"></script>
<!-- Spine 渲染后端:必须在 SpineMgr.js 之前加载(SpineMgr 末尾会立即执行预加载块)-->
<script type="text/javascript" src="js/gameabc-framework/spine/SpineOverlayTransform.js"></script>
<script type="text/javascript" src="js/gameabc-framework/spine/SpineBackendCanvas.js"></script>
<script type="text/javascript" src="js/gameabc-framework/spine/SpineBackendWebGL.js"></script>
<!-- SpineMgr: 自动初始化+自动渲染,必须在 gamemain.js 之前加载 -->
<script type="text/javascript" src="js/gameabc-framework/spine/SpineMgr.js"></script>
<script type="text/javascript" src="app_data.js"></script>
<script type="text/javascript" src="app_battery.js"></script>
<script type="text/javascript" src="app_network.js"></script>
<script type="text/javascript" src="app_gamesname.js"></script>
<script type="text/javascript" src="js/gamemain.js"></script>
<script type="text/javascript" src="js/00_Surface/02_Const.js"></script>
<script type="text/javascript" src="js/00_Surface/04_Data.js"></script>
<script type="text/javascript" src="version.js"></script>
<script type="text/javascript" src="js/00_Surface/08_Utl_Output.js"></script>
<script type="text/javascript" src="js/00_Surface/07_Desk.js"></script>
<script type="text/javascript" src="js/00_Surface/05_Func.js"></script>
<script type="text/javascript" src="js/00_Surface/10_Game.js"></script>
<script type="text/javascript" src="js/00_Surface/11_GameUI.js"></script>
<script type="text/javascript" src="js/00_Surface/12_Logic.js"></script>
<script type="text/javascript" src="js/00_Surface/00_minhttp.js"></script>
<script type="text/javascript" src="js/00_Surface/09_Net.js"></script>
<script type="text/javascript" src="js/00_Surface/06_Player.js"></script>
<script type="text/javascript" src="js/00_Surface/03_Banwords.js"></script>
<!-- 阶段0: 强制工具类(必须最先加载) -->
<script type="text/javascript" src="js/gameabc-framework/core/GameABCUtils.js"></script>
<script type="text/javascript" src="js/gameabc-framework/network/RpcHelper.js"></script>
<script type="text/javascript" src="js/gameabc-framework/system/EventBus.js"></script>
<!-- 精灵事件控制器(框架 system):须早于任何使用精灵交互的组件/回放/JingMark 加载 -->
<script type="text/javascript" src="js/gameabc-framework/system/SpriteEventController.js"></script>
<!-- 精灵手势识别器(框架 system):双击/滑动/点击判定,建立在 SpriteEventController 之上 -->
<script type="text/javascript" src="js/gameabc-framework/system/SpriteGestureRecognizer.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/AlignmentUtils.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/SpriteCopyUtils.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/DynamicSpriteList.js"></script>
<!-- UI组件 -->
<script type="text/javascript" src="js/gameabc-framework/core/SpriteManager.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/BaseComponent.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/UIManager.js"></script>
<!-- 通用战绩页组件(依赖 DynamicSpriteList/SpriteEventController/SpriteManager,均已在前加载) -->
<script type="text/javascript" src="js/gameabc-framework/ui/RecordViewDefaultConfig.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/RecordView.js"></script>
<!-- 动画系统 (Phase 5) -->
<script type="text/javascript" src="js/gameabc-framework/system/AnimationManager.js"></script>
<!-- 音频系统 -->
<script type="text/javascript" src="js/gameabc-framework/system/AudioManager.js"></script>
<!-- 阶段5: 二七王子游戏实现层 -->
<!-- 5.1 配置常量(纯数据,无依赖,最先加载) -->
<script type="text/javascript" src="js/01_SubGame/codes/config/Layers.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Groups.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/ImageResources.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/SoundResources.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_Table.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_Cards.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_Action.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_Result.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_CreateRoom.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/LayoutConstants.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_Table.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_Cards.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_Action.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_Result.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_CreateRoom.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/AnimConstants.js"></script>
<!-- 5.2 前后端共享算法(只读副本,改动落在服务端 shared/,跑根目录 sync_shared.cmd 同步) -->
<script type="text/javascript" src="js/01_SubGame/codes/shared/cards.js"></script>
<!-- 5.3 纯逻辑核心 -->
<script type="text/javascript" src="js/01_SubGame/codes/core/CardCodec.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/core/SeatMap.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/core/CardOrder.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/core/CardMark.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/core/SpriteIndex.js"></script>
<!-- 5.4 布局求解 -->
<script type="text/javascript" src="js/01_SubGame/codes/ui/LayoutSolver.js"></script>
<!-- 5.5 平台接入(须在依赖之后、三文件转发壳之前) -->
<script type="text/javascript" src="js/01_SubGame/codes/SubGameHooks.js"></script>
<!-- 子游戏 Hooks 实现(转发壳三文件转发到此;须在依赖的 controllers/handlers 之后、三文件之前)-->
<script type="text/javascript" src="js/01_SubGame/00_SubGame_Config.js"></script>
<script type="text/javascript" src="js/01_SubGame/01_SubGame_modify.js"></script>
<script type="text/javascript" src="js/01_SubGame/02_SubGame_Input.js"></script>
<!----------------------------------------------------------------------------->
<script type="text/javascript" src="output/gameabc_data.min.js"></script>
</body>
</html>